📄 protocol.c
字号:
putStrRTClow(0x03, BuffPLC+c_OffsetData+4, 0x04); //0x03,时钟芯片周次地址
v_FrameC = 0x84;
v_FrameL = 0x00;
goto BuffPLCCheckEnd;
}
else if((v_DI0 == 0x11) && (v_FrameL == 0x09))
{
//设置时钟(ssmmhh)
v_ExtRunFlag = c_putStrRTC;
putStrRTClow(0x00, BuffPLC+c_OffsetData+4, 0x03); //0x0,时钟芯片时间
v_FrameC = 0x84;
v_FrameL = 0x00;
goto BuffPLCCheckEnd;
}
}
v_FrameC = 0xc4;
}
else if(0x09 == v_FrameC) //删除表号
{
if(0 == v_FrameL)
{
v_ExtRunFlag = c_FMSet;
FMSet(a_MeterID, 0xff, 192); //表号全部删除!!
v_FrameC = 0x89;
v_FrameL = 0x00;
goto BuffPLCCheckEnd;
}
}
else if(0x0d == v_FrameC) //
{
if(0 == v_FrameL)
{
//恢复默认
v_ExtRunFlag = c_FMInit;
FMInit(); //恢复默认参数值!!!
v_ExtRunFlag = c_FMSet;
FMSet(a_MeterID, 0xff, 192); //表号全部删除!!
v_FrameC = 0x8d;
v_FrameL = 0x00;
goto BuffPLCCheckEnd;
}
}
v_FrameL = 0x01;
BuffPLC[c_OffsetDI0] = 0x02; //非法数据标识
goto BuffPLCCheckEnd;
}
BuffPLCCheckEnd:
ReturnFrameSet();
ei();
return;
BuffPLCCheckErr:
BuffPLCMark.Sta = c_Free;
BuffPLCMark.ptr = BuffPLC;
ei(); //使能中断!!!
Nop();
}
// ********** 广播指令处理 ***********
// Return _TRUE :需要返回帧
// Return _FALSE :不需要返回帧
// ***********************************
unsigned char BroadDispose(void)
{
if(0x01 == v_FrameC)
{
if(0x02 == v_FrameL)
{
if((v_DI0 == 0x32) && (v_DI1 == 0xc0)) //广播读地址不响应
{
return _FALSE;
}
}
}
if(0x0A == v_FrameC)
{
if(0x06 == v_FrameL)
{
//设置采集器红外地址
if(_Set == 1) return _FALSE;
v_ExtRunFlag = c_putStrFM;
putStrFMlow(a_CollecterID, BuffPLC+c_OffsetDI0, 0x06);
lowmemcpy(BuffPLC+1, BuffPLC + c_OffsetDI0, 0x06);
v_FrameC = 0x8A;
v_FrameL = 0x00;
return _TRUE;
}
else if(0x01 == v_FrameL)
{
//广播读地址,只有红外可以68 99 99 99 99 99 99 68 0A 01 01 CS 16
if(0x01 != BuffPLC[c_OffsetL]) return _FALSE;
//判断按键
if(_Set == 1) return _FALSE;
//返回帧: 68 11 01 00 00 00 00 68 8A 02 34 34 D6 16
getStrFMlow(BuffPLC+1, a_CollecterID, 0x06);
v_FrameC = 0x8A;
v_FrameL = 0x02;
v_DI0 = 0x01; //未加33
v_DI1 = 0x01; //未加33
return _TRUE;
}
}
else if(0x08 == v_FrameC)
{
//广播校时68 99 .. 68 08 06 ss mm hh dd mm yy cs 16
if(0x06 == v_FrameL)
{
//设置秒分时
v_ExtRunFlag = c_putStrRTC;
putStrRTClow(0x00, BuffPLC+c_OffsetDI0, 0x03);
//设置日月年
v_ExtRunFlag = c_putStrRTC;
putStrRTClow(0x04, BuffPLC+c_OffsetData+1, 0x03);
//指令广播到485总线
// memcpyl2h(Buff485, BuffPLC, v_FrameL + 12);
//enable485send;
// v_DI0485 = Buff485[c_OffsetDI0];
// v_DI1485 = Buff485[c_OffsetDI1];
// v_FrameC485 = 0x08;
// v_FrameL485 = 0x06;
// highmemset(tempBuff1, 0x99, 6);
// Buff485Mark.feCont = 2;
// FrameSet485(tempBuff1);
}
}
else if(0x12 == v_FrameC)
{
//冻结相关
if(0x01 == v_FrameL) //冻结时,仅设置冻结时间
{
v_ExtRunFlag = c_putStrFM;
putStrFMlow(a_FreezeTime, BuffPLC+c_OffsetDI0, 1);
}
else if(0x02 == v_FrameL) //冻结日时
{
v_ExtRunFlag = c_putStrFM;
putStrFMlow(a_FreezeTime, BuffPLC+c_OffsetDI0, 2);
}
else if(0x00 == v_FrameL) //马上冻结
{
v_hhTask = timerBuff[hh];
v_hhTask = bytebcdtohex(v_hhTask);
v_FreezeTask = timerBuff[dd];
}
}
//指令广播到485总线
memcpyl2h(Buff485, BuffPLC, v_FrameL + 12);
//enable485send;
v_DI0485 = Buff485[c_OffsetDI0];
v_DI1485 = Buff485[c_OffsetDI1];
v_FrameC485 = Buff485[c_OffsetC];
v_FrameL485 = Buff485[c_OffsetL];
highmemset(tempBuff1, 0x99, 6);
Buff485Mark.feCont = 2;
FrameSet485(tempBuff1);
return _FALSE; //广播指令不需回应,特意设置为错误
}
//组织回应帧(载波或者红外)
void ReturnFrameSet(void)
{
unsigned char len;
unsigned char cs;
BuffPLC[0] = 0x68;
memcpyh2l(BuffPLC+1, CollectorID, 6);
BuffPLC[c_Offset68_2] = 0x68;
BuffPLC[c_OffsetC] = v_FrameC;
BuffPLC[c_OffsetL] = v_FrameL;
if(v_FrameL > 8) //DI0+DI1+表号
{
BuffPLC[c_OffsetDI0] = v_DI0;
BuffPLC[c_OffsetDI1] = v_DI1;
}
BuffPLCMark.len = v_FrameL + 12; //帧长=L + 12,包括CS 16
//数据域加33
p_BuffPLC = BuffPLC + c_OffsetData - 2;
len = v_FrameL;
while(len--)
{
*p_BuffPLC += 0x33;
p_BuffPLC++;
}
//计算CS
p_BuffPLC = BuffPLC;
cs = 0;
len = v_FrameL + 10; //需要计算CS的个不算CS 0x16
while(len--)
{
cs += *p_BuffPLC;
p_BuffPLC++;
}
*p_BuffPLC++ = cs;
*p_BuffPLC = 0x16;
//设置返回参数
BuffPLCMark.ptr = BuffPLC;
BuffPLCMark.Sta = c_Send;
//发送一个FE
if(v_RecPort == c_Port_Irf)
{
putCharIrf(0xfe);
}
else
{
putCharPLC(0xfe);
}
}
//[]============================================================
//功能: 指令对象确认
//输出: _TRUE 针对采集器,_FALSE针对485表
//说明: 长度<6肯定针对采集器
// 长度>6,但对象是采集器的指令有(设置类带密码)
// C038, C010(L=0x0A采集器, L = 0x0A+6 针对表),C011(L=0x09), C117(L=0x08)
//[]============================================================
unsigned char CommObjCheck(void)
{
if(v_FrameL < 6)
{
return _TRUE; //指令针对采集器
}
//长度大于6的指令,只有部分设置类指令(0x04)是针对采集器
if(v_FrameC != 0x04)
{
if(v_FrameC == 0x01)
{
if((v_DI1 == 0xc0) && (v_DI0 == 0x38) && (0x08 == v_FrameL))
return _TRUE; //读取电表特征字
}
return _FALSE; //长度大于6的非设置类指令针对电表
}
if(0xc0 == v_DI1)
{
if((0x10 == v_DI0) && (0x0a == v_FrameL)) //C010 + 0a 采集器日期周次+4字节密码
{
return _TRUE;
}
else if((0x11 == v_DI0) && (0x09 == v_FrameL))//C010 + 09 采集器时钟
{
return _TRUE;
}
else if((0x38 == v_DI0) && (0x07 == v_FrameL))//c038 + 07 采集间隔
{
return _TRUE;
}
}
else if((0xc1 == v_DI1) && (0x17 == v_DI0)) //C117 + 08 自动抄表日时(冻结)
{
if(0x08 == v_FrameL)
{
return _TRUE;
}
}
return _FALSE;
}
//************* 获取电表数量
//前提必须保证meterBuff,中存放正确表号
unsigned char getMeterAmount(void)
{
unsigned char loop1;
unsigned char loop2 = 0; //8次读取=32只表
unsigned char amount = 0;
bank2 unsigned char *p_data;
while(loop2 < 8)
{
//获取4只电表表号
getStrFM(tempBuff, a_MeterID+loop2*24, 24);//一次4只表
p_data = tempBuff;
loop1 = 4;
while(loop1--)
{
if(_TRUE == MeterIDCheck(p_data))
{
amount++;
}
p_data += 6;
}
loop2++;
}
return amount;
}
//表号有效性判断
//全零和带有0xff的均为非法表号
unsigned char MeterIDCheck(bank2 unsigned char *p)
{
unsigned char cnt0=0, cntff=0, i;
unsigned char j;
for(i=6; i>0; i--)
{
j = *p++;
if(j == 0xff)
{
cntff++;
}
else if(j == 0)
{
cnt0++;
}
}
if((cnt0 == 6u) || (cntff > 0)) //全零,或者有一个以上的ff均为非法
{
return _FALSE;
}
return _TRUE;
}
//645帧格式判断,要求输入帧起始地址
unsigned char frame645Check(bank2 unsigned char *p_comm)
{
unsigned char len, cs;
bank2 unsigned char *p_data;
p_data = p_comm + c_OffsetDI0; //数据域-33时用
//判第一个68
if(0x68 != *p_comm)
{
return (_FALSE);
}
//第二个68
if(0x68 != *(p_comm + c_Offset68_2))
{
return (_FALSE);
}
//获取长度
len = *(p_comm + c_OffsetL);
//判断16结束符:c_DefaltLen = 645规约除了数据域以外所有字节长度,包括CS 16
if(0x16 != *(p_comm + len + c_DefaltLen - 1))
{
return (_FALSE);
}
//计算CS
len += c_DefaltLen - 2; //需要计算CS的字节数
cs = 0;
while(len --)
{
cs += *p_comm++; //计算完成p_comm指向CS
}
//判断CS
if(cs != *p_comm) //p_comm指向CS
{
return (_FALSE);
}
//数据域减33
len = *(p_data - 1);
while(len--)
{
*p_data++ -= 0x33;
}
return (_TRUE);
}
unsigned char frame645Checklow(unsigned char *p_comm)
{
unsigned char len, cs;
unsigned char *p_data;
p_data = p_comm + c_OffsetDI0; //数据域-33时用
//判第一个68
if(0x68 != *p_comm)
{
return (_FALSE);
}
//第二个68
if(0x68 != *(p_comm + c_Offset68_2))
{
return (_FALSE);
}
//获取长度
len = *(p_comm + c_OffsetL);
//判断16结束符:c_DefaltLen = 645规约除了数据域以外所有字节长度,包括CS 16
if(0x16 != *(p_comm + len + c_DefaltLen - 1))
{
return (_FALSE);
}
//计算CS
len += c_DefaltLen - 2; //需要计算CS的字节数
cs = 0;
while(len --)
{
cs += *p_comm++; //计算完成p_comm指向CS
}
//判断CS
if(cs != *p_comm) //p_comm指向CS
{
return (_FALSE);
}
//数据域减33
len = *(p_data - 1);
while(len--)
{
*p_data++ -= 0x33;
}
return (_TRUE);
}
/*************************************
* 返回所有电表地址
* 帧较长特殊处理,直接返回红外
**************************************/
void ReturnAllMeterID(void)
{
unsigned char temp;
unsigned char loop;
unsigned char serial;
unsigned char CS;
unsigned char *p_data;
//1、控制字 C
BuffPLC[c_OffsetC] = 0x81;
//2、长度 L
temp = getMeterAmount();
BuffPLC[c_OffsetL] = 6*temp + 3; //+DI0 DI1 表数量
//3、控制字 DI0, DI1 + 33
BuffPLC[c_OffsetDI0] += 0x33;
BuffPLC[c_OffsetDI1] += 0x33;
//4、表数量+33
temp += 0x33;
BuffPLC[c_OffsetData] = temp;
//5、发送表号之前的数据
CS = 0;
loop = 13; //68 xx xx xx xx xx xx 68 C L DI0 DI1 N
p_data = BuffPLC;
while(loop--)
{
temp = *p_data;
CS += temp;
putCharIrf(temp);
p_data++;
}
//发送表号
for(serial=0; serial<32; serial++)
{
if(_TRUE == getMeterID(tempBuff, serial))
{
for(loop=0; loop<6; loop++)
{
temp = tempBuff[loop] + 0x33;
CS += temp;
putCharIrf(temp);
}
}
}
//发送CS, 16
putCharIrf(CS);
putCharIrf(0x16);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -