📄 com.c
字号:
/************************************* (C) 2005 485表项目 ****************************************
项 目: 485表项目
编译环境 : IARAVR 编译器 4.12A
模块名称 : com.c
版 本 : V 1.0
建立时间 : 2008-5-3 21:51
修改时间 : 2008-5-3 16:47
作 者 : 郝瑜云
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
功能描述 : 645通讯子程序
程序结构 : Protlcol_DLT645_New() 645规约处理程序
|
________________________________|_______________________________
| ? ? |
DLT645Explain(COM1) Com1Reset() Com2Reset() DLT645Explain(COM2)
| 串口复位 串口复位 |
CommDisplay() CommDisplay()
串口1处理并指示 串口2处理并指示
-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
修改 : 2005-11-29: 启用用新的串口通讯程序,查询式
2005-11-29: 表地址编程只用密码保护
2005-12-18: 使用结构指针操作通讯变量,有效降低RAM使用量,但ROM增加60字节
**************************************************************************************************/
#include "Include.h"
/*
*************************************************************************************************
函数 : void Protocol_New(void)
功能 : 645 通讯串口处理程序
输入 : 无
*************************************************************************************************
*/
void Protlcol_New(void)
{
INT8U all_length;
//-------------------------------------------------------------------------
if(Com1Var.CommEnd == 0xAA) // 串口1通讯处理
{
Com1Var.CommEnd = 0;
all_length = Comm_Data_Check_DLT645(Com1Var.RxBuff);
if(all_length>0)
{
//Com1Var.TxConst = 0;
if(DLT645Explain(all_length)) //通讯数据处理
{
goto COM1_SEND;
}
}
Com1Reset();
}
if(CHKBIT(Com1Bits,ComRST))
{
Com1Reset();
}
//-------------------------------------------------------------------------
// #ifdef _COM2_HW_EN // 红外允许定义
if(Com2Var.CommEnd == 0xAA) // 串口2通讯处理
{
Com2Var.CommEnd = 0;
all_length = Comm_Data_Check_DLT645(Com2Var.RxBuff);
if(all_length>0)
{
//Com2Var.TxConst = 0;
if(DLT645Explain(all_length)) // 通讯数据处理
{
goto COM2_SEND;
}
}
Com2Reset();
}
if(CHKBIT(Com2Bits,ComRST))
{
Com2Reset();
}
// #endif
//-------------------------------------------------------------------------
return;
COM1_SEND:
CopyRam(ComVar.TxAllBuff,Com1Var.TxBuff,ComVar.TxConst); // 传递发送数据
Com1Var.TxConst = ComVar.TxConst;
Com1Var.ComInitTimer = 0; // 串口1初始化定时器清零
Com1Var.TxPoint = 0; // 置发送起始指针
SETBIT(Com1Bits,EnComTx); // 允许发送数据
SETBIT(ComBits,EnStatus); // 通讯指示
//------------------------------// 发送返回数据
Com1Var.ComTxStep = 0; // 发送节拍清零
return;
//-------------------------------------------------------------------------
// #ifdef _COM2_HW_EN
COM2_SEND:
CopyRam(ComVar.TxAllBuff,Com2Var.TxBuff,ComVar.TxConst);
Com2Var.TxConst = ComVar.TxConst;
Com2Var.ComInitTimer = 0; // 串口2初始化定时器清零
TCCR2A = 0x00;
// CommDisplay(); // 通讯指示 红外通讯亮背光
//------------------------------// 发送返回数据
Com2Var.TxPoint = 0; // 置起始指针
SETBIT(ComBits,EnStatus); // 通讯指示
Com2Var.ComTxStep = 0; // 发送节拍清零
//-----------------------------------------------------------------
Com2Var.OverTimer = 0; // 清零超时定时器
SETBIT(Com2Bits,EnComTx); // 允许发送数据// 发送返回数据
//#endif
//-------------------------------------------------------------------------
}
/*
***************************************************************************************************
函 数 : void Comm_Data_Check_DLT645(void)
功 能 : 串口接收数据帧检查函数
输 入 : 无
***************************************************************************************************
*/
INT8U Comm_Data_Check_DLT645(INT8U *buff)
{
INT8U i,datalength,*buff_bak;
buff_bak = buff; // 执行645规约检测 检测有无帧头字节
for(i=0;i<6;i++)
{
if(*buff == 0x68)
{
goto NEXT1_STEP; // i 即为数据起始地址
}
buff++;
}
return(0);
NEXT1_STEP: // 检测数据长度是否合法
// CLRBIT(PORTB,IO_ALARM );
buff += _COM_DATA_LENGTH;
datalength = *buff;
buff = buff_bak + i + datalength + 11;
if( datalength> 36) return(0); // 数据长度判断
if( *buff == 0x16) // 检测有无帧尾标志
{
datalength = datalength+12; // 计算数据总长度
buff_bak += i;
CopyRam(buff_bak,ComVar.RxBuff,datalength); // 传递接收数据
return(datalength);
}
return(0);
}
//*****************************************************************************
// 函数 : INT8U DLT645Explain(pointer) *
// 功能 : DLT645通讯解释处理程序 *
// *
// 输入 : rxcnt:串口缓冲区数据个数 *
//*****************************************************************************
INT8U DLT645Explain(INT8U rxcnt)
//ComVarDef *pointer; // 指向ComVarDef类型的指针
{
INT8U datalength;
INT16U cmd;
INT16U eep_address;
INT8U i,erro,consttmp[7];
// float temp;
//-------------------------------------------------------------------------
rxcnt -= 2; // 检测数据有效性
if(ComVar.RxBuff[rxcnt]!=(DataAddCS(ComVar.RxBuff,rxcnt)))//检测累加和
{
return(0);
}
//-------------------------------------------------------------------------
erro = 0; // 测试表地址
for(i=0;i<7;i++) // 执行645规约检测 检测有无帧头字节
{
if(ComVar.RxBuff[i]!=0x99) {erro = 0x55;} // 判断是否为广播地址
}
if(erro == 0)
{
goto MTR_ADDRESS_OK;
}
erro = 0; // 判断真实表地址
CopyEEPToRam(ADDRESS_C032E,EEPVar.I2cBuff+1,6); // 读入6字节表地址
for(i=1;i<7;i++) // 如果表地址空位补A才能使用缩位
{
if((ComVar.RxBuff[i]!=0xAA)&(ComVar.RxBuff[i]!=0xBB))
{
if(ComVar.RxBuff[i]!=EEPVar.I2cBuff[i])
{
return(0);
}
}
}
//-------------------------------------------------------------------------
MTR_ADDRESS_OK:
RamFill(ComVar.TxAllBuff,0,40); // 发送缓冲区清零,使用缓冲区注意,已经清零了
ComVar.TxAllBuff[0] = 0x68; // 填充发送帧头
ComVar.TxAllBuff[7] = 0x68;
CopyEEPToRam(ADDRESS_C032E,ComVar.TxAllBuff+1,6); // 将表地址拷入发送缓冲 // 检测数据长度是否合法
datalength = ComVar.RxBuff[9]; // 取出数据长度
DataDec33(ComVar.RxBuff+10,datalength); // 数据-33处理
CopyRam(ComVar.RxBuff+10,(INT8U *)&cmd,2); // 取出命令码合并为INT
eep_address = 0; // 清除RAM和EEP操作数地址
//---------------------------------------------------------
//*********************************************************************
switch(ComVar.RxBuff[_COM_CTR_CODE]) // 通讯模式
{
//*****************************************************************
case 0x01: // 判断读模式
CopyRam(ComVar.RxBuff+10,ComVar.TxAllBuff+10,2); // 传递命令码
ComVar.TxAllBuff[_COM_CTR_CODE] = 0x81; // 置控制码:正常应答,无后续帧
ComVar.TxConst = 8; // 重置发送数据个数
//bcd_enable = 1; // BCD 转换允许,由于大多数数据需HEX到BCD转换
switch(cmd)
{
case 0x5501: // 读命令 5501 软件标识号
datalength = 6;
ComVar.TxAllBuff[12]= _VERSION;
break;
case 0x9010: // 读命令 9010 当前有功正向总电量
datalength = 4;
goto BUILD_901F;
case 0x901F: // 读命令 901F 当前有功正向总电量集合
datalength = 20;
BUILD_901F:
BuildPower();
CopyRam(PowerVar.ActInPow,ComVar.TxAllBuff+12,4);
HEXToBCD8(ComVar.TxAllBuff+12,4); // 将数据转成BCD码
CopyRam(ComVar.TxAllBuff+12,ComVar.TxAllBuff+24,4); // 复制总电量至平电量:安徽中天要求
break;
case 0xC030: // 读命令 C030 表常数
//eep_address = ADDRESS_C030E;
i = ((_PulseConst/10)<<4)+(_PulseConst%10);
ComVar.TxAllBuff[12]=0x00;
ComVar.TxAllBuff[13]=i;
ComVar.TxAllBuff[14]=0;
datalength = 3;
// bcd_enable = 0; // 清零BCD转换标志
break;
case 0xC032: // 读命令 C032 表地址
eep_address = ADDRESS_C032E;
datalength = 6;
// bcd_enable = 0; // 清零BCD转换标志
break;
case 0xD400: //读命令 D400 显示域
eep_address = ADDRESS_D400E;
datalength = 22;
break;
case 0xC113: //循显时间
eep_address = ADDRESS_C113E;
datalength = 1;
break;
case 0xD406: // 读命令 D406 产品条形码号
eep_address = ADDRESS_D406E;
datalength = 60;
break;
case 0xC098: // 读命令 C098 误差分频数
mIICReadPage( consttmp,0x06, 0xA0, 0x00);
CopyRam(consttmp,ComVar.TxAllBuff+12,6);
//eep_address = ADDRESS_C098E;
datalength = 6;
break;
default: // 发送错误帧: 代码 01 :非法数据
erro = 0x34;
goto SEND_645_ERRO; // 非法数据
}
//-------------------------------------------------------------
if(eep_address!=0) // 调入相应数据
{
CopyEEPToRam(eep_address,ComVar.TxAllBuff+12,datalength);
}
//-------------------------------------------------------------
ComVar.TxAllBuff[_COM_DATA_LENGTH] = datalength+2; // 置数据长度:n字节
// if(bcd_enable)
// {
// HEXToBCD8((*pointer).Buff+12,datalength); // 将数据转成BCD码
// }
DataAdd33(ComVar.TxAllBuff+10,(datalength+2));
ComVar.TxConst = datalength+14;
ComVar.TxAllBuff[ComVar.TxConst-2] = DataAddCS(ComVar.TxAllBuff,(datalength+12)); // 计算校验和
ComVar.TxAllBuff[ComVar.TxConst-1] = 0x16;
break;
//*****************************************************************
case 0x04: // 判断编程模式
if(PasswordCheck(12))
{
if((ComVar.ProgEn!=0xAA)&(ComVar.AdjustEn!=0xAA)) // 检测编程允许标志
{
goto INVALID_DATA;
}
EEPVar.WriteProtectAA = 0xAA;
//---------------------------------------
switch(cmd)
{
case 0xD400:
CopyRamToEEP(ADDRESS_D400E,ComVar.RxBuff+16,22);
ReadDispConst(); //读出显示域
break;
case 0xC113: //修改循显时间
CopyRamToEEP(ADDRESS_C113E,ComVar.RxBuff+16,1);
ReadDispConst(); //读出循显时间
break;
// case 0xC030: // 写命令 C030 表常数
// CopyRamToEEP(ADDRESS_C030E,ComVar.RxBuff+16,3);
// ReadPulseConst(); // 读出脉冲常数
// break;
case 0xC032: // 写命令 C032 电表号
case 0x230C:
CopyRamToEEP(ADDRESS_C032E,ComVar.RxBuff+16,6);
CopyRamToEEP(ADDRESS_230BE,ComVar.RxBuff+16,4); //更新产品条形码中的资产号
CopyRam(ComVar.RxBuff+16,ComVar.TxAllBuff+1,6);
break;
case 0x230A: //产品条形码1(低30字节)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -