⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 portdirection.c

📁 基于ARM7的ucos-ii移动收发通信编程ADS开发源码
💻 C
📖 第 1 页 / 共 5 页
字号:
#define PORT_DIRECTION_C

#include "config.h"
#include "I2CINT.h"
#include "sysmem.h"
#include "fm3164.h"
#include "main.h"
#include "crc16.h"
#include "transform.h"
#include "port.h"

//状态机状态变量
static INT8U newStaNorth = 0;
static INT8U newStaSouth = 0;

//RS485接口
#define S_QueryModuleSta        	0x01	//查询南向模块状态
#define S_QueryModuleStaWait		0x02	//等待应答
#define S_QueryBufDat     			0x03	//查巡南向模块缓冲区数据
#define S_QueryBufDatWait			0x04	//等待应答
#define S_BufDatPro					0x06
#define S_SendToSouthWait			0x05	//等待FSK应答
#define S_End						0x01
//北向
#define  N_QueryUpDataWait			16
#define  N_SendData					11	//检查有无下发数据
#define  N_FskSendWait				17
#define  N_QueryModuleSta			13	//查下行模块状态
#define  N_QueryModuleStaWait		14
#define  N_End						13

#define TIME_OUT_MAX				(OS_TICKS_PER_SEC)

////////////////////////////////////////////////////
#define TS_PRO_HEADER			0x7e
#define TS_PRO_TAIL				0x7f
#define TS_PRO_TYPE_OPTO		0x06
#define TS_PRO_ACK_ERR_OK		0x00	
//光模块命令编号(东方信联有源协议)
#define CMD_QUERY_MODULE_STA	0x11
#define CMD_QUERY_BUF_DAT		0x81
#define CMD_FSK_SEND			0x80
//////////////////////////////////////////////////////
//RS485接受缓冲区
INT8U RecSouthPortData[1024] = {'\0'};
INT8U RecNorthPortData[1024] = {'\0'};
//查询光模块的命令

INT8U queryModuleState[10]=	{0x7E, 0x06, 0x00, 0x11, 0x00, 0x00, 0x00, 0xf2, 0xe0, 0x7F};
//查询南向光模块数据缓冲区的命令
uint8 S_QueryDatBuf[]=		{0x7E, 0x06, 0x00, 0x81, 0x00, 0x00, 0x00, 0x6d, 0x26, 0x7F};
//同步命令
//							1	  2     3     4     5     长度        设备地址           状态  校验和	
uint8 cmdSyc[]=				{0x7e, 0x06, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x7f};

void setAddr(uint8 *commAddr, uint8 level, uint8 addr);
INT8U SysGain;
///////////////////////////////////
//同步不同的设备时的同步命令的组包
//逐一改变设备地址,重新计算校验
//addr		新的地址地址
//ptr		同步数据包的头地址
uint8 querySycDataGroup(uint8 *addr, uint8 *ptr)
{
	uint16 crc;
	struct TS *ptrTS;
	MY_PROTOCAL *ptrMyProtocal;
	
	ptrTS = (struct TS *)ptr;
	ptrMyProtocal = (MY_PROTOCAL *)(&ptrTS->firstDat);
	
	ptrMyProtocal->addr[0]=addr[0];
	ptrMyProtocal->addr[1]=addr[1];
	//ptrMyProtocal->addr[2]=addr[2];
	
	OSSchedLock();	
    crc = CRC16(ptr+1, ptrTS->datLen[0]+(ptrTS->datLen[1]<<8)+6);		 
    OSSchedUnlock();
    
    ptr[ptrTS->datLen[0]+(ptrTS->datLen[1]<<8)+7] = (uint8)(crc>>0);
    ptr[ptrTS->datLen[0]+(ptrTS->datLen[1]<<8)+8] = (uint8)(crc>>8);
    
    return(ptrTS->datLen[0]+(ptrTS->datLen[1]<<8)+10);
}

///////////////////////////////////////////
//把同步信息拷贝
//desPtr	目标存储区开始地址
//srcPtr	同步信息源数据开始地址
//len		拷贝的数据长度(固定为14)
void  copyInfo(uint8 *desPtr, uint8 *srcPtr, uint8 len)
{
	uint16 n;
	for(n=0; n<len; n++)
	{
		if(3==n)
		{//要插入一个状态字节
			*desPtr++ = STA_SYC;
		}
		else
		{
			*desPtr++ = *srcPtr++;
		}
	}
}
/////////////////
//内存拷贝
//d		目标地址
//s		源地址
//len	长度
void strCopy(uint8 *d, uint8 *s, uint8 len)
{
	uint8 cnt=0;
	for(cnt=0; cnt<len; cnt++)
	{
		*(d+cnt) = *(s+cnt);
	}
}
/////////////////////////////////////
//同步应答组包(内部协议层)
//把存在的设备的信息打包
//desPtr	目标缓冲区, 缓冲区要足够大
//返回		数据包长度
uint16 ackSycDataGroup(uint8 *desPtr)
{
	uint16 cnt=0;
	uint16 n, m;
	uint8  *ptr;
	
	OSSchedLock();	
	//本机信息
	ptr = (uint8*)expandDevice.expandInfo.addr;
	copyInfo(desPtr+cnt, ptr, SYC_INFO_LEN);
	cnt+=SYC_INFO_LEN;
	
	expandDevice.expandInfo.sycInfo.state[1] &= ~0x80;	//清除配置变更标志
	
	//8个端口
	for(n=0; n<8; n++)
	{
		if(0x01==expandDevice.devicePort[n].portCheckEnable)//mainDevice.flag)
		{//检查各个端口上有设备
			ptr = (uint8*)expandDevice.devicePort[n].mainDevice.addr;
			setAddr(ptr, deviceLevel, deviceAddr);
			copyInfo(desPtr+cnt, ptr, SYC_INFO_LEN);
			cnt+=SYC_INFO_LEN;
			
			if(0x01==expandDevice.devicePort[n].mainDevice.sycInfo.deviceType)
			{//如果接的是扩展机
				for(m=0; m<8; m++)
				{
					if(0x01==expandDevice.devicePort[n].slaveDevice[m].flag)
					{//检查扩展机下面的远端是否存在
						ptr = (uint8*)expandDevice.devicePort[n].slaveDevice[m].addr;
						setAddr(ptr, deviceLevel, deviceAddr);
						copyInfo(desPtr+cnt, ptr, SYC_INFO_LEN);
						cnt+=SYC_INFO_LEN;
					}
				}
			}
		}
	}
	OSSchedUnlock();	
	return(cnt);
}
//应答查询的包组包
//desPtr	打包后存的地址首地址
//返回		数据长度(字节)
uint16 ackQueryDataGroup(uint8 *desPtr)
{
	uint16 cnt=0;
	uint16 n, m;
	uint8  *ptr;
	
	OSSchedLock();	
	//本机信息
	strCopy(desPtr+cnt, expandDevice.expandInfo.addr, 3);
	cnt+=3;
	*(desPtr+cnt) = STA_QUERY;
	cnt+=1;
	strCopy(desPtr+cnt, (uint8*)&expandDevice.expandInfo.basisInfo, BASIS_INFO_LEN);
	cnt+=BASIS_INFO_LEN;
	
	//8个端口
	for(n=0; n<8; n++)
	{
		//端口检查使能, 知道曾经接过设备就使能, 上电清0
		if(0x01==expandDevice.devicePort[n].portCheckEnable)	
		{
			//各个端口上的主设备
			ptr = (uint8*)expandDevice.devicePort[n].mainDevice.addr;
			setAddr(ptr, deviceLevel, deviceAddr);
			strCopy(desPtr+cnt, ptr, 3);	//拷贝地址
			cnt+=3;
			*(desPtr+cnt) = STA_QUERY;		//数据标志
			cnt+=1;
			ptr = (uint8*)&expandDevice.devicePort[n].mainDevice.basisInfo;
			strCopy(desPtr+cnt, ptr, BASIS_INFO_LEN);	//拷贝数据
			cnt+=BASIS_INFO_LEN;
			
			if(0x01==expandDevice.devicePort[n].mainDevice.sycInfo.deviceType)
			{//如果接的是扩展机
				for(m=0; m<8; m++)
				{
					//端口上的从设备
					if(0x01==expandDevice.devicePort[n].slaveDevice[m].flag)
					{//检查扩展机下面的远端是否存在
						ptr = (uint8*)expandDevice.devicePort[n].slaveDevice[m].addr;
						setAddr(ptr, deviceLevel, deviceAddr);
						strCopy(desPtr+cnt, ptr, 3);
						cnt+=3;
						*(desPtr+cnt) = STA_QUERY;
						cnt+=1;
						ptr = (uint8*)&expandDevice.devicePort[n].slaveDevice[m].basisInfo;
						strCopy(desPtr+cnt, ptr, BASIS_INFO_LEN);
						cnt+=BASIS_INFO_LEN;
					}
				}
			}
		}
	}
	OSSchedUnlock();	
	return(cnt);
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
//TS层打包, 在内部协议层已经打好包的情况下
//addr		光模块地址
//ptr		目标数据包的头指针
//ptrDat	内部协议数据包指针头
//datLen	内部协议数据长度
uint16 myDatGroup(uint8 addr, uint8 *ptr, uint8 *ptrDat, uint16 datLen)
{
	uint16 cnt;
	uint16 crc;
	struct TS *ptrTS;
	
	ptrTS = (struct TS *)ptr;
	
	ptrTS->header 	= TS_PRO_HEADER;
	ptrTS->type 	= TS_PRO_TYPE_OPTO;
	ptrTS->addr 	= addr;
	ptrTS->cmd		= 0x80;		//转发
	ptrTS->ack 		= 0x00;
	ptrTS->datLen[0]	= datLen&0xff;	//数据长度,现在是uint16类型,注意	
	ptrTS->datLen[1]	= (datLen>>8)&0xff;
	
	for(cnt=0; cnt<datLen; cnt++)
	{
		*(&ptrTS->firstDat+cnt)=*(ptrDat+cnt);
	}
	OSSchedLock();	
    crc = CRC16(ptr+1, ptrTS->datLen[0]+(ptrTS->datLen[1]<<8)+6);		 
    OSSchedUnlock();
    //校验和
    ptr[ptrTS->datLen[0]+(ptrTS->datLen[1]<<8)+7] = (uint8)(crc>>0);
    ptr[ptrTS->datLen[0]+(ptrTS->datLen[1]<<8)+8] = (uint8)(crc>>8);
    //结束符
    ptr[ptrTS->datLen[0]+(ptrTS->datLen[1]<<8)+9] = TS_PRO_TAIL;
    
    return(ptrTS->datLen[0]+(ptrTS->datLen[1]<<8)+10);
}
//////////////////////////
//得到对应层的地址 
//commAddr	地址头指针
//level		层
uint8 checkAddr(uint8 *commAddr, uint8 level)
{
	uint8 addrP=0;
	if(1==level)
	{//本机扩展1
		addrP =(0x0f&(commAddr[2]>>4));
	}
	else if(2==level)
	{//本机扩展2
		addrP =(0x0f&(commAddr[2]>>0));
	}
	else if(3==level)
	{//本机扩展2
		addrP =(0x0f&(commAddr[1]>>4));
	}
	else
	{//拨码设置错误
		addrP = 0;
	}
	return(addrP);
}
///////////////////////////////
//设置对应层的地址
//commAddr		地址指针头
//level			层
//addr			要设置成的地址
void setAddr(uint8 *commAddr, uint8 level, uint8 addr)
{/*
	commAddr[0]=0x00;
	commAddr[1]=0x00;
	//commAddr[2]=0x00;
	if(1==level)
	{//本机扩展1
		commAddr[1]&=0x0f;
		commAddr[1]|=((addr&0x0f)<<4);
	}
	else if(2==level)
	{//本机扩展2
		commAddr[1]&=0xf0;
		commAddr[1]|=((addr&0x0f)<<0);
	}
	else if(3==level)
	{//本机扩展2
		commAddr[0]&=0x0f;
		commAddr[0]|=((addr&0x0f)<<4);
	}
	else
	{//拨码设置错误
		addr = 0;
	}*/
	
	*commAddr=0x00;
	*(commAddr+1)=0x00;
	//commAddr[2]=0x00;
	if(1==level)
	{//本机扩展1
		*(commAddr+1)&=0x0f;
		*(commAddr+1)|=((addr&0x0f)<<4);
	}
	else if(2==level)
	{//本机扩展2
		*(commAddr+1)&=0xf0;
		*(commAddr+1)|=((addr&0x0f)<<0);
	}
	else if(3==level)
	{//本机扩展2
		*commAddr&=0x0f;
		*commAddr|=((addr&0x0f)<<4);
	}
	else
	{//拨码设置错误
		addr = 0;
	}
	
}

//////////////////////////////////////////
//处理同步信息的设置处理
//ptr	操作的设备的开始
//cmd	内部协议命令的数据区
//cmdLen命令区长度	
void setPro(DEVICE_INFO *ptr, uint8 *cmd, uint8 cmdLen)
{
	uint8 cnt=0, timeOutCnt=0;
	SET_CMD * ptrSetCmd;
	
	while(cnt<cmdLen && timeOutCnt<20)
	{
		timeOutCnt++;
		ptrSetCmd = (SET_CMD *)(cmd+cnt);
		switch(ptrSetCmd->cmd)
		{
			case SET_DEVICE_XINGHAO:	//单元型号
				ptr->basisInfo.deviceXinghao[0] = *(&ptrSetCmd->cmdFirstData+0);
				ptr->basisInfo.deviceXinghao[1] = *(&ptrSetCmd->cmdFirstData+1);
				ptr->basisInfo.deviceXinghao[2] = *(&ptrSetCmd->cmdFirstData+2);
				ptr->basisInfo.deviceXinghao[3] = *(&ptrSetCmd->cmdFirstData+3);
				break;
			case SET_SERIALNUM:			//生产序列号
				ptr->basisInfo.serialNum[0] = *(&ptrSetCmd->cmdFirstData+0);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -