📄 rscomm.c
字号:
#include <Reg931.h>
#include <Rscomm.h>
#include <Meter_def.h>
#include <General.h>
#include <Math.h>
#ifdef uchar
#define READYDEF 1 //宏uchar已定义
#else
#define uchar unsigned char
#endif
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
// 变量定义
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
// MeterFlag
extern uchar bdata MeterFlag;
extern bit Battery;
extern bit Hardware;
extern bit RsComm;
extern bit AdjTime;
extern bit EryRev;
extern bit AdjDate;
extern bit Fee0;
extern bit Fee1;
//Flag
extern uchar bdata Flag;
extern bit TimeAdj;
extern bit TimeProg ;
extern bit RxdFlag;
extern bit TxdFlag;
extern bit TxdWork;
extern bit DspType;
extern bit DspPage;
extern bit DspFlag;
//SystemStates
extern uchar bdata SystemStates;
extern bit Comm_RTC_Err;
extern bit Comm_EPM_Err;
extern bit Data_RTC_Err;
extern bit Data_EPM_Err;
extern bit EryBln_Flag;
extern bit Prog_Flag;
extern bit Fee_Flag;
extern bit CommFlag;
extern uchar DspSec;
extern uchar DspPtr;
extern uchar ComPtr;
extern uchar CommTimer;
extern uchar CommSec;
extern uchar Len[2];
extern uchar Addr[2];
extern uchar DspPara[4];
extern uchar PulseTmp[6];
extern uchar EryTmp[6];
extern uchar Ptr[8];
extern uchar RTC[8];
extern uchar idata ComBuf[RS_MaxSize];
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
// 函数定义
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
void Comm_Proc(void);
void ReadMeter(void);
void WriteMeter(void);
void Proc33(uchar procdata);
void ReadMeterData(uchar addr,uchar saddr,uchar DataLen);
bit TimeTerm(void);
uchar RxdCheck(void);
uchar PsWdCHK(uchar PsWdPtr);
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
// 函数外部引用
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
extern void RTC_Read(void);
//extern void Fee_CHK(void);
extern void WriteEPMData(uchar idata *ptr);
extern void RTC_Init(void);
extern void RTC_Set(uchar staddr,uchar idata *ptr,uchar len);
extern void ErrorModify(uchar addr,uchar idata *ptr);
extern bit DateTerm(void);
extern bit DateCHK(uchar idata *ptr);
extern bit TimeCHK(uchar idata *ptr);
extern bit ReadData(uchar idata *ptr);
extern uchar LastMonthSN(uchar sn);
//**********************************************************
//名称:Comm_Proc()
//功能:
//说明:通讯处理函数
//**********************************************************
void Comm_Proc(void)
{
uchar i;
uchar j;
uchar TFlag;
if( RxdFlag==1 )
{
Watchdog_feed(); //喂狗
//※※※※※※※※※※※※※※※※※※※※※※※※※※※
//信道配置
HW38K = 1;
CTRL485 = 1; //打开默认:红外调制
TR1 = 1;
if(COMMSEL==1) //RS485发送配置
{
CTRL485 = 0;
TR1 = 0;
}
//※※※※※※※※※※※※※※※※※※※※※※※※※※※
Flag &= 0xE0;
//TimeAdj = 0; //校时时间
//TimeProg = 0; //编程时间
//RxdFlag = 0; //接收状态
//TxdFlag = 0; //通信应答
//TxdWork = 0; //发送状态
TFlag = RxdCheck(); //通讯帧格式及通讯地址检查
if( TFlag!=0x00 )
{
Proc33(0xCD); //数据去0x33处理
if(TFlag==0x10) //广播校时,无应答
{
if((TimeCHK(&ComBuf[RS_CmdPtr]+0)==1)&&(DateCHK(&ComBuf[RS_CmdPtr+3])==1))
{
ComBuf[RS_CmdPtr+6] = ComBuf[RS_CmdPtr+0];
ComBuf[RS_CmdPtr+7] = ComBuf[RS_CmdPtr+1];
ComBuf[RS_CmdPtr+8] = ComBuf[RS_CmdPtr+2];
if(Prog_Flag==1||((ComBuf[RS_CmdPtr+3]==Day)&&(ComBuf[RS_CmdPtr+4]==Month)&&(ComBuf[RS_CmdPtr+5]==Year)&&(TimeTerm()==1)))
{
//RTC_Init();
RTC_Set(0x00,&ComBuf[RS_CmdPtr+0],0x03); //秒、分、时
RTC_Set(0x40,&ComBuf[RS_CmdPtr+3],0x03); //日、月、年
CommSec = CommLEDTime; //亮10秒
LED_COMM = 0;
Flag |= 0x03;
//TimeAdj = 1; //校时标志
//TimeProg = 1; //编程标志
Fee_Flag = 1; //时段费率判断
//*******
EryBln_Flag = 1; //电量结算
}
}
}
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※
else if( TFlag==0x11 ) //广播设置电表表号
{
for(i=0;i<6;i++)ComBuf[1+i] = ComBuf[RS_CmdPtr+i]; //表号数据返回
ComBuf[RS_CmdPtr+6] = SumCHK(&ComBuf[RS_CmdPtr],6); //表号检验和
Addr[0] = 0xA0;
Addr[1] = 0xF0; //写局编号
//Addr[1] = 0xF8; //写出厂编号
Len[1] = 0x07;
WriteEPMData(&ComBuf[RS_CmdPtr]);
RS_Len = 0x00;
Flag |= 0x0A;
//TimeProg = 1;
//TxdFlag = 1;
}
/*
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※
else if( TFlag==0x12) //自定义命令集
{
if( RS_CmdH==0x00 && RS_CmdL==0x00) //数据清零命令
{
LED_F = 0;
LED_G = 0;
LED_COMM = 0;
CommSec = CommLEDTime; //亮10秒
EA = 0;
ArrayInit(ComBuf,RS_MaxSize);
//数据清零
for(i=0;i<16;i++)
{
Addr[0] = 0xA0;
Addr[1] = i*16;
Len[1] = 16;
WriteEPMData(ComBuf);
Addr[0] = 0xA2;
WriteEPMData(ComBuf);
}
ComBuf[0] = 0x02;
ComBuf[1] =~0x02;
Addr[0] = 0xA0;
Addr[1] = 0xBE;
Len[1] = 0x02;
WriteEPMData(ComBuf);
AUXR1 |= 0x08; //复位
}
}
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※
*/
else if(TFlag==0x20) //密码修改
{
j = PsWdCHK(RS_CmdPtr); //旧密码检查
for(i=0;i<4;i++) //构造返回数据
{
ComBuf[RS_CmdPtr+i] = ComBuf[RS_CmdPtr+4+i];
}
ComBuf[RS_CmdPtr+4] = ~SumCHK(&ComBuf[RS_CmdPtr+1],3);//密码的校验和
Addr[0] = 0xA0;
Len[1] = 0x04;
if((j==0x10)&&(ComBuf[RS_CmdPtr]==0x00))//清零密码
{
Addr[1] = 0xE8;
WriteEPMData(&ComBuf[RS_CmdPtr+1]);
Flag |= 0x0A;
//TimeProg = 1;
//TxdFlag = 1;
}
if((j==0x11)&&(ComBuf[RS_CmdPtr]==0x01))//编程密码
{
Addr[1] = 0xEC;
WriteEPMData(&ComBuf[RS_CmdPtr+1]);
Flag |= 0x0A;
//TimeProg = 1;
//TxdFlag = 1;
}
RS_Len = 0x04;
}
else if(TFlag==0x21) ReadMeter(); //读电表数据
else
{
WriteMeter(); //设置电表数据
RS_Len = 0x00;
}
}
if( TimeProg==1 ) //编程时间及编程次数
{
TimeProg = 0;
RTC_Read();
//编程时间
ComBuf[40] = Min; //分
ComBuf[41] = Hour; //时
ComBuf[42] = Day; //日
ComBuf[43] = Month; //月
ComBuf[44] = SumCHK(&ComBuf[40],4); //校验和
//编程次数
Addr[0] = 0xA0;
Addr[1] = 0xE5;
Len[1] = 0x03;
do
{
ReadData(&ComBuf[45]);
i= ComBuf[45]+ComBuf[46]; //SumCHK(&ComBuf[45],2);
} while((i!=ComBuf[47])&&(Addr[0]<=0xA4));
if(i!=ComBuf[47])
{
ComBuf[45] = 0x00;
ComBuf[46] = 0x00;
}
BCDINC(&ComBuf[45],2,1); //编程次数+1
ComBuf[47]=ComBuf[45]+ComBuf[46]; //SumCHK(&ComBuf[45],2);
//写编程时间+编程次数
Addr[0] = 0xA0;
Addr[1] = 0xE0;
Len[1] = 0x08;
WriteEPMData(&ComBuf[40]);
//写校时时间
if(TimeAdj==1)
{
TimeAdj = 0;
Addr[0] = 0xA2;
Addr[1] = 0xF8;
Len[1] = 0x05;
WriteEPMData(&ComBuf[40]);
}
}
ComPtr = 0x00; //通讯缓冲区初始指针
if(TxdFlag==1) //电表应答
{
TxdFlag = 0;
LED_COMM = 0;
CommSec = CommLEDTime; //亮10秒
Proc33(0x33); //数据加0x33处理
RS_Ctrl |= 0x80; //从机应答标识符
RS_CRC = SumCHK(ComBuf,RS_CmdPtr+RS_Len);
RS_End = 0x16;
TxdWork = 1; //发送标志
ES = 1;
TB8 = 1; //偶校验
SBUF = 0xFE; //发送第一个字节值
}
else
{
COMMSEL = 0; //默认红外通讯方式
CTRL485 = 1; //RS485接收状态
TR1 = 0; //Timer1关闭,无红外载波
// HW38K = 1; //P0.7置高
CommFlag= 0;
ArrayInit(ComBuf,RS_MaxSize);
TR0 = 0;
TH0 = 0x53; //Timer0定时12mS初值
TL0 = 0x33;
TR0 = 1; //打开Timer0
}
}
}
//**********************************************************
//名称:ReadMeter()
//功能:读电表中的数据
//说明:
//**********************************************************
void ReadMeter(void)
{
uchar Temp[2];
TxdFlag = 1; //数据返回标志
RS_Len = 2+4; //返回数据长度
if((RS_CmdH==0x90)&&(RS_CmdL==0x1F)) //当前有功电量集合
{
ReadMeterData(0xA0,0xC0,16); //整数
ComBuf[RS_DataPtr+0] = EryTmp[0]; //总电量小数
ComBuf[RS_DataPtr+4] = EryTmp[1]; //峰电量小数
ComBuf[RS_DataPtr+8] = EryTmp[2]; //平电量小数
ComBuf[RS_DataPtr+12] = EryTmp[3]; //谷电量小数
RS_Len = 2+16;
}
else if((RS_CmdH==0x90)&&(RS_CmdL==0x20)) //反向累计电量
{
ReadMeterData(0xA0,0xD0,0x04); //反向电量整数
ComBuf[RS_DataPtr] = EryTmp[4]; //反向电量小数
//RS_Len = 2+4;
}
else if((RS_CmdH==0xB0)&&(RS_CmdL==0x20)) //反向起始时间
{
ReadMeterData(0xA0,0xAA,4);
//RS_Len = 2+4;
}
else if((RS_CmdH==0xB0)&&(RS_CmdL==0x21)) //反向累计时间
{
ReadMeterData(0xA0,Ptr[6],3);
RS_Len = 2+3;
}
else if((RS_CmdH==0xB2)&&(RS_CmdL==0x10)) //编程时间
{
ReadMeterData(0xA0,0xE0,4);
//RS_Len = 2+4;
}
else if((RS_CmdH==0xB2)&&(RS_CmdL==0x12)) //编程次数
{
ReadMeterData(0xA0,0xE5,2);
RS_Len = 2+2;
}
else if((RS_CmdH==0xC0)&&(RS_CmdL==0x10)) //当前日期及周次
{
ComBuf[RS_DataPtr+0] = Week;
ComBuf[RS_DataPtr+1] = Day;
ComBuf[RS_DataPtr+2] = Month;
ComBuf[RS_DataPtr+3] = Year;
//RS_Len = 2+4;
}
else if((RS_CmdH==0xC0)&&(RS_CmdL==0x11)) //当前时间
{
ComBuf[RS_DataPtr+0] = Sec;
ComBuf[RS_DataPtr+1] = Min;
ComBuf[RS_DataPtr+2] = Hour;
RS_Len = 2+3;
}
else if((RS_CmdH==0xC0)&&(RS_CmdL==0x20)) //运行状态
{
ComBuf[RS_DataPtr] = MeterFlag;
RS_Len = 2+1;
}
else if((RS_CmdH==0xC0)&&(RS_CmdL==0x30)) //电表常数
{
ComBuf[RS_DataPtr+0] = 0x00;
ComBuf[RS_DataPtr+1] = 0x16;
ComBuf[RS_DataPtr+2] = 0x00;
RS_Len = 2+3;
}
else if((RS_CmdH==0xC0)&&((RS_CmdL==0x32)||(RS_CmdL==0x33)))
{
Temp[0] = 0xF8; //出厂编号
if(RS_CmdL==0x33) Temp[0] = 0xF0; //局编号
//else Temp[0] = 0xF8; //出厂编号
ReadMeterData(0xA0,Temp[0],6);
RS_Len = 2+6;
}
else if((RS_CmdH==0xC1)&&(RS_CmdL==0x17)) //自动抄表日期
{
ReadMeterData(0xA0,0xD4,3);
RS_Len = 2+2;
}
else if((RS_CmdH==0xC3)&&(RS_CmdL==0x3F)) //时段表
{
//有效时段数
Addr[0] = 0xA2;
Addr[1] = 0xCE;
Len[1] = 0x02;
ReadData(Temp);
//数据范围限制
if( (Temp[0]>12)||(Temp[0]<2))Temp[0] = 0x02;
Temp[0] *= 0x03;
ReadMeterData(0xA2,0xD0,Temp[0]);
RS_Len = 2+Temp[0];
}
else if((RS_CmdH==0xD1)&&(RS_CmdL>=0x20)&&(RS_CmdL<=0x2B))//电量历史数据
{
Temp[0] = LastMonthSN(RS_CmdL&0x0F)<<4;
ReadMeterData(0xA2,Temp[0],16);
RS_Len =2+16;
}
else TxdFlag = 0; //命令不在服务范围
}
//**********************************************************
//名称:
//功能:
//说明:
//**********************************************************
void WriteMeter(void)
{
uchar i;
uchar j;
uchar k;
uchar TFlag;
uchar Temp[2];
Watchdog_feed(); //喂狗
Flag |= 0x0A;
//TxdFlag = 1; //回应
//TimeProg= 1; //编程时间
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -