📄 comm_module.c
字号:
void DL645_Command(void)
{
unsigned char i,j;
MoveData_Api(eMeterNo_Dtr+e2RAM_Adr,(unsigned int)(&TempChar[0]),6); //读入表号存入TempChar共用数据区
//--------------------------------------------------------------------------------
// 表号比较,支持半字节缩位
j=0;
for (i=0;i<6;i++)
{
if (((TempChar[i] & 0x0F) == (RxTxBuf[i+1] & 0x0F)) && (!j ))
{
if ((TempChar[i] & 0xF0) != (RxTxBuf[i+1] & 0xF0))
{
j=12;
if ((RxTxBuf[i+1] & 0xF0) != 0xA0)
{
j=0xff;
break;
}
}
}
else
{
if (RxTxBuf[i+1] != 0xAA)
{
if (RxTxBuf[i+1] == 0x99)
{
j++; //记录广播地址"99"的个数 (6个字节的99才算广播地址)
}
else
{
j=0xff;
break;
}
}
}
}
if ((j!=6) && (j!=0) && (j!=12))
return; //非本表地址,返回。
//--------------------------------------------------------------------------------
Comm_Flg=1; //显示通信提示符号
if (Key_Flg )
Key_Time = KeyMaxTime; //刷新编程有效时间
//--------------------------------------------------------------------------------
// 校验和检查
j=RxTxBuf[0];
for (i=1;i<RxTxLen-2;i++)
{j += RxTxBuf[i];} //求校验和
for (i=0;i<RxTxBuf[9];i++)
{RxTxBuf[10+i] -=0x33;} //数据 -0x33H处理
if (j != RxTxBuf[RxTxLen-2])
{ //校验和检查错误,返回非法数据错误。
RxTxBuf[8] |=0xC0;
RxTxBuf[9] = 1;
RxTxBuf[10] = Data_err; // 非法数据
DL645_DataSend(); //按照DL/T-645协议发送数据
return;
}
//--------------------------------------------------------------------------------
// 通信命令处理
switch (RxTxBuf[8]) //CommandByte 命令字节
{
case 0x01:
Read_Response(); //"01"读命令处理
break;
case 0x04:
Write_Response(); //"04"写命令处理
break;
case 0x08:
// TimeChecking_Response(); //"08"广播校时命令处理
break;
default:
// //非法命令,返回非法数据应答
break;
}
}
//-----------------------------------------------------------------------------------------------
// 异常应答设置
// 错误命令
// 错误字
void ErrorResponse(unsigned char err_comm,unsigned char err_word )
{
RxTxBuf[8] = err_comm;
RxTxBuf[9] = 1;
RxTxBuf[10] = err_word;
}
//-----------------------------------------------------------------------------------------------
/* 发送数据
; 1、判断当前是红外口还是RS485口在通信,根据不同进行处理
2、关闭接收
; 3、启动偶校验发送(一字节0xfe)
; 4、其余的数据由中断发送完毕
; 5、发送数据在RxTxBuf[]数据区钟,发送数据长度在RxTxLen中
*/
void DL645_DataSend(void)
{
unsigned char i,add;
RxTxBuf[0] = 0x68;
ReadE2prom_Api((eMeterNo_Dtr+e2RAM_Adr),(unsigned int)(&RxTxBuf[1])+xRAM_Adr,6);
/*
for (i=0;i<6;i++)
{RxTxBuf[i+1] = MeterAdr[i];} //装载表号
RxTxBuf[7] = 0x68;
*/
for (i=0;i<RxTxBuf[9];i++)
{ RxTxBuf[10+i] +=0x33; } //+33
add = RxTxBuf[0];
for (i=1;i<(RxTxBuf[9] + 10);i++)
{add += RxTxBuf[i];}
RxTxBuf[i] = add; //校验和
RxTxBuf[i+1] = 0x16; //帧结束标志
//-----------------------------------------------------------------------------------------------
if (IR_CTRL) //是否为红外通信?
{
EPCFG_bit.MODE38_TxD = 1; //38KHz输出到发送端口
CommHWDelyTime = 250;
}
RxTxLen = RxTxBuf[9]+12; //设定发送长度(645标准)
RxTxAdr = RxTxBuf; //置发送数据首地址
SCON_bit.REN = 0; //关接收
SCON_bit.TI = 0; //清发送中断
SendByte(0xfe); //发送一个字节
CommByte_Time =8; //80ms(发送一个字节最大等待时间80ms)
RxTxFlg = 3; //置发送状态
}
//-----------------------------------------------------------------------------------------------
// 01 通信命令(即读命令)
void Read_Response(void)
{
unsigned int id,idAdr;
unsigned char idDataLen;
id = RxTxBuf[10] + (RxTxBuf[11] << 8); //取id
if (RxTxBuf[11]==0x01) //0x0100~0x012A
{ //读能量寄存器
ReadEnergyReg3(RxTxBuf[10]);
RxTxBuf[12]=Temp8L;
RxTxBuf[13]=Temp8M;
RxTxBuf[14]=Temp8H;
RxTxBuf[8] = 0x81;
RxTxBuf[9] = 5;
DL645_DataSend(); //按照DL/T-645协议发送数据
return;
}
idAdr = GetDataTree_Adr_Len(id,&idDataLen ); //获取id数据地址和长度
idDataLen &=0x7F;
if (idDataLen)
{
RxTxBuf[8] = 0x81;
RxTxBuf[9] = idDataLen + 2;
MoveData_Api(idAdr,(unsigned int)(&RxTxBuf[12])+xRAM_Adr,idDataLen); //转送数据
}
else
{
ErrorResponse(0xC1,iD_err); //发送无此标识信息错误应答
}
DL645_DataSend(); //按照DL/T-645协议发送数据
}
//-----------------------------------------------------------------------------------------------
// "0x11"读能量寄存器数据命令
void Read_Energy(void)
{
}
//-----------------------------------------------------------------------------------------------
// "04"写命令处理
void Write_Response(void) //"04"写命令处理
{
unsigned int id,idAdr;
unsigned char idDataLen;
id = RxTxBuf[10] + (RxTxBuf[11] << 8); //取id
idAdr = GetDataTree_Adr_Len(id, &idDataLen ); //获取id数据地址和长度
if (CompareE2prom(ePassWd00_Dtr,(unsigned int)(&RxTxBuf[12])+xRAM_Adr,4)==ErrorTrue) //是否是用户密码?
{
if (CompareE2prom(eComposerPassword_Dtr,(unsigned int)(&RxTxBuf[12])+xRAM_Adr,4)==ErrorTrue) //是否是设计者密码?
{
ErrorResponse(0xC4,Password_err); //密码不正确,返回密码错误
}
else
{
goto Down_comm;
}
}
else if (Key_Flg &&(idDataLen & 0x80)) //判断是否是可写数据项和编程开关是否打开?
{
Down_comm:
idDataLen &= 0x7f;
MoveData_Api((unsigned int)(&RxTxBuf[16])+xRAM_Adr,idAdr,idDataLen); //转送数据
if (id==0xC011)
SetTime(); //设置时钟
else if (id==0xC010)
{
Temp8 = Week;
Week = Date;
Date = Month;
Month = Year;
Year = Temp8;
}
RxTxBuf[8] = 0x84; //正常应答返回
RxTxBuf[9] = 0;
}
else
{
ErrorResponse(0xC4,Data_err); //不是可写数据项或编程开关没有打开,返回非法数据操作
}
DL645_DataSend(); //按照DL/T-645协议发送数据
CommRefurbish(); //通信需要刷新的数据
}
//===============================================================================================
#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -