📄 portdirection.c
字号:
#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 + -