📄 ircomm.c
字号:
/*===========================================================================
* Copyright (c) 2004,三星科技有限公司
* All rights reserved.
*
* 文件名称:IRCOMM.C
* 文件标识:
* 摘 要:DDS188
*
*
* 当前版本:V 1.0
* 作 者:叶孟军
* 修改内容:
* 开始日期:2005年7月25日
==============================================================================*/
#include <machine.h>
#include <stdio.h>
#include "iodefine.h"
#include "extern.h"
/******************************************************************************/
#define Re_Te (IO.PDR4.BIT.B0) //控制RS485发送/接收
/*******************************************************************************/
void BroChkEng_frost(void);
/**********************************************************
通讯缓冲区绕尾处理
说明:只要有头尾指针加操作的地方一定要进行绕尾处理
***********************************************************/
unsigned char *Bufferl_Tail_OP(unsigned char *Temp)
{
if(Temp > &BufferInOut_Comm[BufferInOutMax_Comm-1])
{
Temp -= BufferInOutMax_Comm;
}
return Temp;
}
/**********************************************************
通讯主流程及状态切换
与中断接口:void Set_RxState(void); //发完后开收中断处理(注:可讨论是否在此处理)
void Startup_Send(void); //启动发送处理
***********************************************************/
unsigned char Get_BuffData_Len(void); //取缓冲区数据的长度
void Protocel_Main_Comm(void)
{
//命令续发处理
while(NeedSign_Comm == 1) //把读命令续发与发送统一处理,进来后先看是否在续发态
{
if(Get_BuffData_Len() >= 34) //缓冲区待发数据长度等于或超过34个字节,则退出
{
break;
}
else //缓冲区待发数据长度未超过34个字节,则继续填待发数据
{
DataHold_Comm_DLT645(); //续发态,向缓冲区继续塞数处理
}
}
//收 态
if((RxTxState_Comm == AtRxState_Comm) && (system_timer_in_13ms - TxRxTime_Comm) > 30) //命令缓冲区从串口收到的命令并且解析完成,SIO 收发标志置为收 38 = 500ms/13.3ms
{
if (BufferHead_Comm!=BufferTail_Comm) //收发缓冲区头尾指针是否相等
{
BufferHead_Comm = BufferTail_Comm; //若不等令头尾指针相等
Set_RxState(); //开收接收中断
}
else
{
// IENR1.BYTE |= 0x01; //开启红外接收中断
Sci_Define();
// Tx_Flg = 0x00;
// CKSTPR2.BYTE &=0xfd; //关闭红外调制信号
}
}
//(待)发 态
if(RxTxState_Comm==AtTxState_Comm && (system_timer_in_13ms-TxRxTime_Comm)>90) //2 = 2个char发时间/13.3ms*2
{
if(BufferHead_Comm == BufferTail_Comm)
{
Set_RxState(); //开收接收中断
}//发送完状态关闭发送标志位,
else
{
TxRxTime_Comm= 0x00;
system_timer_in_13ms = 0x00;
Startup_Send(); //启动发送处理
}
}
//既非收态也非发态
if(RxTxState_Comm!=AtRxState_Comm && RxTxState_Comm!=AtTxState_Comm)//
{
RxTxState_Comm = AtRxState_Comm;
BufferHead_Comm = BufferTail_Comm;
Set_RxState(); //开收接收中断
}
}
//取缓冲区数据的长度
unsigned char Get_BuffData_Len(void)
{
unsigned char len;
len = BufferTail_Comm - BufferHead_Comm;
if(len > BufferInOutMax_Comm) //尾指针地址小于头指针地址
{
len += BufferInOutMax_Comm;
}
return len;
}
void Set_RxState(void)
{
unsigned char i;
BufferHead_Comm = BufferInOut_Comm; //外部UART1接收定义
BufferTail_Comm = BufferInOut_Comm;
for(i=0;i<BufferInOutMax_Comm;i++)
{
BufferInOut_Comm[i] = 0x00;
}
Re_Te = 1; //RS485的控制位处接收状态
//SCI3.SCR3.BYTE = 0x50; //接收中断使能
Sci_Define();
IENR1.BYTE |= 0x01; //开启红外接收中断
Rx_Command_Flg.BYTE = 0x00;
RxTxState_Comm = AtRxState_Comm; //处于接收状态
Tx_Flg = 0x00;
CKSTPR2.BYTE &=0xfd; //关闭红外调制信号
}
void Startup_Send(void)
{
RxTxState_Comm = AtTxState_Comm;
if(Tx_Txd_Comm_Flg == 0x33) //表示解析成功的接收数据为红外接收而得,发送须为红外发送
{
Tx_Flg = 0x68;
TxData_state.BYTE = 0x01; //红外发送字节初始状态
TMRF.TCFL = 0x00; //定时器FL计数器清零
}
else if(Tx_Txd_Comm_Flg == 0x55) //表示解析成功的接收数据为RS485接收而得,发送须为RS485发送
{
Txd_Flg = 0x68;
SCI3.SCR3.BYTE =0xa0; //SCI处于发送状态
SCI3.TDR = 0xfe;
// SCI3.SSR.BYTE = 0x00;
// SCI3.SCR3.BYTE =0xa0; //SCI处于发送状态
}
}
/**********************************************************
通讯协议解析
说明:
***********************************************************/
void F_ProtocolResolve_Comm(void)
{
unsigned char *Temp1_Pointer,*Temp2_Pointer,i,j,len,cs;
ErrByte_Comm.BYTE = 0x00; //清错误信息字
if (RxTxState_Comm == AtTxState_Comm) //在发状态吗?
{
return;
}
if(Get_BuffData_Len() < 12) //**是否到最小解析长度
{
return;
}
Temp1_Pointer = BufferHead_Comm;
if(*Temp1_Pointer == 0x68) //**第1个为68H吗
{
Temp1_Pointer += 7;
Temp1_Pointer = Bufferl_Tail_OP(Temp1_Pointer);
if(*Temp1_Pointer == 0x68) //**第7个为68H吗
{
Temp2_Pointer = RMtNo_Dtr;
j = 0;
Temp1_Pointer = BufferHead_Comm;
for(i=0; i<6; i++) //广播地址判断
{
Temp1_Pointer += 1;
Temp1_Pointer = Bufferl_Tail_OP(Temp1_Pointer);
if(*Temp1_Pointer != 0x99)
{
break;
}
j += 1;
}
if(j != 6)
{
j=0;
Temp1_Pointer = BufferHead_Comm;
for(i=0; i<6; i++) //本机地址判断
{
Temp1_Pointer += 1;
Temp1_Pointer = Bufferl_Tail_OP(Temp1_Pointer);
if((*Temp1_Pointer!=0xAA) && (*Temp1_Pointer!=*Temp2_Pointer))
{
break;
}
j++;
Temp2_Pointer += 1;
}
}
if (j == 6) //**广播或本机地址正确
{
Temp1_Pointer += 3;
Temp1_Pointer = Bufferl_Tail_OP(Temp1_Pointer);
if(Get_BuffData_Len() != (*Temp1_Pointer+12)) //**接收长度到吗
{
return;
}
len = *Temp1_Pointer;//数据域长度
Temp1_Pointer = BufferHead_Comm;
cs=0;
for(i=0;i<(len+10);i++) //计算cs
{
cs += *Temp1_Pointer;
Temp1_Pointer++;
Temp1_Pointer = Bufferl_Tail_OP(Temp1_Pointer);
}
if(cs == *Temp1_Pointer) //**cs正确吗
{
Temp1_Pointer++;
Temp1_Pointer = Bufferl_Tail_OP(Temp1_Pointer);
if(*Temp1_Pointer == 0x16) //**16H正确吗
{
BufferHead_Comm += 8;
BufferHead_Comm = Bufferl_Tail_OP(BufferHead_Comm);
CommandByte_Comm = *BufferHead_Comm;//控制码
CommandDataLength_Comm = len; //数据域长度
BufferHead_Comm += 2;
BufferHead_Comm = Bufferl_Tail_OP(BufferHead_Comm);
CommandDataPointer_Comm = BufferHead_Comm;//数据域首址指针
BufferHead_Comm = BufferTail_Comm; //协议解析成功令头尾指针相等
IrComm_Disp = 1;
Jump_OP_Comm();//协议解析成功转到执行跳转程序
return;//解析正确退出
}
}
}
}
}
CommandDataPointer_Comm = 0; //上述任一条件错误,数据帧丢掉一个字节
BufferHead_Comm++;
BufferHead_Comm = Bufferl_Tail_OP(BufferHead_Comm);
}
/**************************************************************/
void ClrDate_Comm(void)
{
unsigned char i;
Hello_Flg = 0x38;
if ( !Progrm_Disp) //**编程开关打在编程禁止
{
return;
}
if((*CommandDataPointer_Comm == 0x48) && (*(++CommandDataPointer_Comm) == 0x49)) //系统复位
{
CommandDataPointer_Comm++;
for(i=0;i<CommandDataLength_Comm;i++) //取出数据域数据
{
Temp_WrtDt_Comm[i] = *CommandDataPointer_Comm-0x33;
CommandDataPointer_Comm++;
CommandDataPointer_Comm = Bufferl_Tail_OP(CommandDataPointer_Comm);
}
if(Judge_BCD() == 1) //非法数据
{
ErrByte_Comm.BYTE |= 0x01;
Abn_Answer(); //异常应答处理子程序
return;
}
if(Compare_sub_code() == 1) //密码错
{
ErrByte_Comm.BYTE |= 0x04;
Abn_Answer(); //异常应答处理子程序
return;
}
WatchDog_Set();
Reset_Data();
while(1)
{
NOP;
}
}
else if ((*CommandDataPointer_Comm == 0x47) && (*(++CommandDataPointer_Comm) == 0x49)) //历史数据清零
{
CommandDataPointer_Comm++;
for(i=0;i<CommandDataLength_Comm;i++) //取出数据域数据
{
Temp_WrtDt_Comm[i] = *CommandDataPointer_Comm-0x33;
CommandDataPointer_Comm++;
CommandDataPointer_Comm = Bufferl_Tail_OP(CommandDataPointer_Comm);
}
if(Judge_BCD() == 1) //非法数据
{
ErrByte_Comm.BYTE |= 0x01;
Abn_Answer(); //异常应答处理子程序
return;
}
if(Compare_sub_code() == 1) //密码错
{
ErrByte_Comm.BYTE |= 0x04;
Abn_Answer(); //异常应答处理子程序
return;
}
WatchDog_Set();
EngerData_Clr();
while(1)
{
NOP;
}
}
}
/**********************************************************
通讯执行跳转程序
***********************************************************/
void Jump_OP_Comm(void)
{
if (CommandDataPointer_Comm == 0)
{
return;
}
switch (CommandByte_Comm)
{
case 0x01:
ReadOrder_Comm(); //一、请求读数据处理;
break;
case 0x04:
WriteOrder_Comm(); //二、主站向从站请求设置数据(或编程)处理;
break;
case 0x08:
CheckTime_Comm(); //三、强制从站与主站时间同步,即广播校时处理;
break;
case 0x0a:
WirteDevcNo_Comm(); //四、写设备地址,即设置某从站的地址码处理
break;
case 0x0f:
AmendCode_Comm(); //五、写密码处理;
break;
case 0x13:
ClrDate_Comm(); //七、内存数据复位,内存电量清零
break;
case 0x19: //电量冻结命令
BroChkEng_frost(); //广播冻结电量命令
default:
NeedSign_Comm = 0;
CommandByte_Comm = 0;
// Error_Trig=1; //无此命令;显示Error
Error_Flg = 0x38;
break;
}
CommandDataPointer_Comm = 0; //通讯结束,清相关变量
CommandByte_Comm = 0;
CommandDataLength_Comm = 0;
return;
}
/**********************************************************
一、请求读数据处理
***********************************************************/
void ReadOrder_Comm(void)
{
unsigned int length,temp3;
unsigned char temp1,temp2,Pointer;
unsigned char i,*p;
Hello_Flg = 0x38; //通信协议解析成功;触发 Hello 显示
temp1 = *CommandDataPointer_Comm - 0x33;//将数据域数据进行减0x33操作
CommandDataPointer_Comm++;
CommandDataPointer_Comm = Bufferl_Tail_OP(CommandDataPointer_Comm);
temp2 = *CommandDataPointer_Comm - 0x33; //将数据域数据进行减0x33操作
DI1DI0_Comm = ((unsigned int)temp2*256) + ((unsigned int)temp1); //**得到标识
CoutSign_Len = 0; //number 默认为0
if((DI1DI0_Comm <= 0x941f) && (DI1DI0_Comm >= 0x9410)) //上月正向有功
{
DI1DI0_Comm +=0x4f00;
}
if((DI1DI0_Comm <= 0x981f) && (DI1DI0_Comm >= 0x9810)) //上上月正向有功
{
DI1DI0_Comm +=0x4b10;
}
if((DI1DI0_Comm <= 0xe3cf) && (DI1DI0_Comm >= 0xe310))//对历史电量的标识进行修正
{
if(F_BlckRead_Eeprm(HstryEngy_Pter,&Pointer,1))//取出历史电量偏移量
{
RMtWd_Dtr[0] &= 0xfd; //存储芯片无错
}
else
{
RMtWd_Dtr[0] |= 0x02; //存储芯片出错
}
if((DI1DI0_Comm + (Pointer * 0x0010)) > 0xe3cf)
{
DI1DI0_Comm = DI1DI0_Comm + Pointer * 0x0010 - 0x00c0;
}
else
{
DI1DI0_Comm = DI1DI0_Comm + Pointer * 0x0010;
}
}
if((DI1DI0_Comm <= 0xe219) && (DI1DI0_Comm >= 0xe210))//对电流反向事件标识进行修正
{
if(F_BlckRead_Eeprm(CrntRvrs_Pter,&Pointer,1))//取出电流反向事件偏移量
{
RMtWd_Dtr[0] &= 0xfd; //存储芯片无错
}
else
{
RMtWd_Dtr[0] |= 0x02; //存储芯片出错
}
if((DI1DI0_Comm + Pointer) > 0xe219)
{
DI1DI0_Comm = DI1DI0_Comm + Pointer - 0x0a;
}
else
{
DI1DI0_Comm = DI1DI0_Comm + Pointer;
}
}
if((DI1DI0_Comm <= 0xe229) && (DI1DI0_Comm >= 0xe220))//对停电事件标识进行修正
{
if(F_BlckRead_Eeprm(PDRcd_Pter,&Pointer,1))//取出停电事件偏移量
{
RMtWd_Dtr[0] &= 0xfd; //存储芯片无错
}
else
{
RMtWd_Dtr[0] |= 0x02; //存储芯片出错
}
if((DI1DI0_Comm + Pointer) > 0xe229)
{
DI1DI0_Comm = DI1DI0_Comm + Pointer - 0x0a;
}
else
{
DI1DI0_Comm = DI1DI0_Comm + Pointer;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -