📄 rscomm.c
字号:
#include <Reg936.h>
#include <Rscomm.h>
#include <Meter_def.h>
#include <General.h>
#include <Math.h>
#include <var.h>
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
//函数定义
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
void LCDView(void);
void Comm_Proc(void);
void ReadMeter(void);
void WriteMeter(void);
void Proc33(uchar procdata);
bit TimeTerm(void);
uchar RxdCheck(void);
uchar PsWdCHK(uchar PsWdPtr);
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
//函数外部引用
//※※※※※※※※※※※※※※※※※※※※※※※※※※※※※
extern void RTC_Read(void);
extern void RTC_Init(void);
extern void RTC_Set(uchar staddr,uchar idata *ptr,uchar len);
extern bit DateTerm(void);
extern bit DateCHK(uchar idata *ptr);
extern bit TimeCHK(uchar idata *ptr);
extern uchar LastMonthSN(uchar sn);
extern uchar Temp_Read(void);
extern void CreateRealTimeEry(void);
extern void PowerDownProcess(void);
extern bit Write24C64(uchar idata *ptr,uchar Addr1,uchar Addr2,uchar DataLen);
extern bit Read24C64(uchar idata *ptr,uchar Addr1,uchar Addr2,uchar DataLen);
//**********************************************************
//名称:Comm_Proc()
//功能:
//说明:通讯处理函数
//**********************************************************
void Comm_Proc(void)
{
uchar i,j;
uchar TFlag;
if(RxdFlag==1) //接收结束,进行数据处理并回应上位机
{
Watchdog_feed(); //喂狗
Flag &= 0xE0;
//TimeAdj = 0; //校时时间
//TimeProg = 0; //编程时间
//RxdFlag = 0; //接收状态
//TxdFlag = 0; //通信应答
//TxdWork = 0; //发送状态
ErrInfFlag = 0x00; //通讯错误信息标志
TFlag = RxdCheck(); //通讯帧格式及通讯地址检查
if(TFlag!=0x00) //检查正确
{
CommLCDSec = CommLCDTime; //液晶通讯指示显示时间
Proc33(0xCD); //数据去0x33处理
if(TFlag==0x10) //广播校时,无应答
{
if((TimeCHK(&ComBuf[RS_CmdPtr+0])==1)&&(DateCHK(&ComBuf[RS_CmdPtr+3])==1))//日期时间检查正确
{
//在5分钟有效时间判断函数TimeTerm()中使用以下变量
ComBuf[RS_CmdPtr+6+0] = ComBuf[RS_CmdPtr+0]; //秒
ComBuf[RS_CmdPtr+6+1] = ComBuf[RS_CmdPtr+1]; //分
ComBuf[RS_CmdPtr+6+2] = ComBuf[RS_CmdPtr+2]; //时
if((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); //日、月、年
Flag |= 0x03;
//TimeAdj = 1; //校时标志
//TimeProg = 1; //编程标志
Fee_Flag = 1; //时段费率判断
EryBln_Flag = 1; //电量结算
}
}
}
else if(TFlag==0x20) //密码修改
{
//密码初始化
if((ComBuf[10]==0x00)&&(ComBuf[11]==0x23)&&(ComBuf[12]==0x09)&&(ComBuf[13]==0x94))
{
j = 0x10;
}
//密码修改(老密码修改新密码)
else
{
j = PsWdCHK(RS_CmdPtr); //旧密码检查
}
//从站出错不应答
if((j!=0x00)&&(PAN>=PAO)) //高密级可修改低密级
{
for(i=4;i>0;--i) //构造返回数据,新密级+新密码
{
ComBuf[RS_CmdPtr+i-1] = ComBuf[RS_CmdPtr+4+i-1];
}
i = PAN; //暂存待修改密码的密级
ComBuf[RS_CmdPtr+4] = ~SumCHK(&ComBuf[RS_CmdPtr+1],3);//密码的校验和
Write24C64(&ComBuf[RS_CmdPtr+1],0x08,0x54+i*4,4); //保存新密码
Flag |= 0x0A;
//TimeProg = 1; //编程标志
//TxdFlag = 1; //回应标志
RS_Len = 0x04;
}
}
else if(TFlag==0x21) //读电表数据或LCD显示屏查看
{
if(RS_Len==0x02) ReadMeter(); //读电表数据
else if((RS_Len==0x03)&&(RS_CmdL==0xE1)&&(RS_CmdH==0xEE)) LCDView(); //LCD显示屏查看
else Flag &= 0xE0;
}
else if(TFlag==0x22) //设置电表数据
{
WriteMeter();
}
else
{
Flag &= 0xE0;
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
if(TimeProg==1) //编程时间及编程次数
{
TimeProg = 0;
RTC_Read();
//编程时间
ComBuf[50] = Min; //分
ComBuf[51] = Hour; //时
ComBuf[52] = Day; //日
ComBuf[53] = Month;//月
ComBuf[54] = SumCHK(&ComBuf[50],4);//校验和
//读编程次数和编程事件指针
Read24C64(&ComBuf[55],0x08,0xF9,5);
i= ComBuf[55]+ComBuf[56];
//读编程次数失败的处理
if(i!=ComBuf[57])
{
ComBuf[55] = 0x00;
ComBuf[56] = 0x00;
}
//读编程事件指针失败的处理
if(ComBuf[59]!=~ComBuf[58])
{
ComBuf[58] = 0x00;
ComBuf[59] = 0xFF;
}
BCDINC(&ComBuf[55],2); //编程次数+1
ComBuf[57]=ComBuf[55]+ComBuf[56];
ComBuf[58]++; //编程事件指针+1
if(ComBuf[58]==0x05) ComBuf[58] = 0x00;
ComBuf[59] = ~ComBuf[58];
//写编程次数和编程事件指针
Write24C64(&ComBuf[55],0x08,0xF9,5);
//写编程时间
Write24C64(&ComBuf[50],0x08,0xE0+ComBuf[58]*5,5);
//写校时时间
if(TimeAdj==1)
{
TimeAdj = 0;
ComBuf[54] = ~ComBuf[54];
Write24C64(&ComBuf[50],0x08,0x7A,5); //写本次校时时间
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//通讯回应处理
ComPtr = 0x00; //通讯缓冲区初始指针
if(TxdFlag==1) //电表应答
{
TxdFlag = 0;
Proc33(0x33); //数据加0x33处理
RS_Ctrl |= 0x80; //从机应答标识符
if(ErrInfFlag==0xAA) RS_Ctrl |= 0x40; //通讯错误信息标志
RS_CRC = SumCHK(ComBuf,RS_CmdPtr+RS_Len);
RS_End = 0x16;
//※※※※※※※※※※※※※※※※※※※※※※※※※※※
//信道配置
HW38K = 1; //P0.7红外调制信号输出引脚
CTRL485 = 1; //关闭RS485输出信道,打开默认的红外调制
TMOD |= 0x21; //设置Timer0,选择定时器模式2--通讯超时检测
//设置Timer1,选择定时器模式3--红外载波
TAMOD = 0x00; //T0M2=0,T1M1=0,T1M0=1
//T1M2=0,T1M1=1,T1M0=0
TH1 = 0xD0; //Timer1设置自动重装值
TL1 = 0xD0;
AUXR1 |= 0x20; //ENT1=1,Timer1溢出使P0.7发生翻转
TR1 = 1;
if(COMMSEL==1) //RS485发送配置
{
CTRL485 = 0; //打开RS485输出信道
TR1 = 0; //关闭默认的红外调制
}
//※※※※※※※※※※※※※※※※※※※※※※※※※※※
TxdWork = 1; //发送标志,此时不允许接收
CommFlag = 0; //UART通讯状态标志
ES = 1;
TB8 = 1; //偶校验
SBUF = 0xFE; //发送第一个字节值
}
else
{
ES = 0; //关闭UART中断允许
ReinitUARTFlag = 1; //UART重新初始化标志
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//清事件记录(清过程)
if(ClearEvenFlag==1)
{
ClearEvenFlag = 0;
ArrayInit(&ComBuf[40],32);
//设置电表运行状态字
//设置电表管理状态
//预留一次清零机会
ComBuf[73] = 0xA0; //默认清零事件指针为0
ComBuf[74] = 0x5F;
Write24C64(&ComBuf[73],0x05,0xE7,2);
//清日时段表切换时发生的冻结电量
Write24C64(&ComBuf[40],0x09,0x6A,22);
Write24C64(&ComBuf[40],0x09,0x80,16);
//清开盖、开端钮盒事件
KBG_Last_State = 1; //预置表盖状态(按下为高)
KDNH_Last_State = 0; //预置端钮盒状态(按下为低)
KBGDeLayTimer = 0;
KDNHDeLayTimer = 0;
KBGSec = 0;
KDNHSec = 0;
Write24C64(&ComBuf[40],0x09,0x00,32);
Write24C64(&ComBuf[40],0x09,0x20,32);
//清编程事件
Write24C64(&ComBuf[40],0x08,0xE0,30);
//清上次结算日月份
Write24C64(&ComBuf[40],0x08,0x8B,2);
//清上次校时时间
Write24C64(&ComBuf[40],0x08,0x7A,5);
//清除电池报警时间、工作时间
Write24C64(&ComBuf[40],0x00,0xE0,10);
//清除有功反向累计总时间、当前月累计反向时间、最后一次反向起止时间
//上1~12月累计反向时间、最后一次反向起止时间
EryRev = 0; //电能反向标志清零
RevDeLayTimer = 0;
RevSec = 0;
for(i=0;i<7;i++)
{
Write24C64(&ComBuf[40],0x04,(i*2)<<4,32);
}
//清清零事件
for(i=0;i<8;i++)
{
Write24C64(&ComBuf[40],0x05,(i*2)<<4,32);
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////
ePowerDownCheckFlag = ENABLE; //打开掉电检测
//////////////////////////////////////////////
PowerDownProcess(); //掉电检测处理程序
}
//**********************************************************
//名称: ReadMeter()
//功能: 读电表中的数据
//说明:
//**********************************************************
void ReadMeter(void)
{
char Temp[2];
uint RSCommand;
uchar i,j,addr1,addr2;
uchar LLastEryFlag=0x00;
if(isLastMonthEry==0x01) LLastEryFlag = 0x01; //用上上月电量代替上月电量
TxdFlag = 1; //数据返回标志
RS_Len = 2+16; //返回数据长度
RSCommand = (RS_CmdH<<8)+RS_CmdL;
switch(RSCommand)
{
case 0x5501://软件版本号
{
ComBuf[RS_DataPtr+0] = 0x30; //版本序号:3.0
ComBuf[RS_DataPtr+1] = 0x06; //年号:06
ComBuf[RS_DataPtr+2] = 0x55; //用户地区号:55
ComBuf[RS_DataPtr+3] = 0x00; // 00
ComBuf[RS_DataPtr+4] = 0x00; //OEM外协厂家编号、备用码:00
ComBuf[RS_DataPtr+5] = 0x42; //产品分类号:B
ComBuf[RS_DataPtr+6] = 0x56; // V
ComBuf[RS_DataPtr+7] = 0x34; //产品型号:4
ComBuf[RS_DataPtr+8] = 0x38; // 8
ComBuf[RS_DataPtr+9] = 0x32; // 2
ComBuf[RS_DataPtr+10] = 0x46; // F
RS_Len =2+11;
break;
}
case 0x9010://当前月正向总有功(总)指数
case 0x9012://当前月正向总有功(峰)指数
case 0x9013://当前月正向总有功(平)指数
case 0x9014://当前月正向总有功(谷)指数
{
if(RS_CmdL==0x10) i = 0;
else i = RS_CmdL-0x11;
CreateRealTimeEry();
for(j=0;j<4;j++)
{
ComBuf[RS_DataPtr+j] = CommVariant[16+i*4+j];
}
RS_Len =2+4;
break;
}
case 0x9020://当前月反向总有功(总)指数
case 0x9022://当前月反向总有功(峰)指数
case 0x9023://当前月反向总有功(平)指数
case 0x9024://当前月反向总有功(谷)指数
{
if(RS_CmdL==0x20) i = 0;
else i = RS_CmdL-0x21;
CreateRealTimeEry();
for(j=0;j<4;j++)
{
ComBuf[RS_DataPtr+j] = CommVariant[32+i*4+j];
}
RS_Len =2+4;
break;
}
case 0x901F://当前月正向总有功指数数据块
case 0x902F://当前月反向总有功指数数据块
{
if(RS_CmdL==0x1F) i = 16;
else i = 32;
CreateRealTimeEry();
for(j=0;j<16;j++)
{
ComBuf[RS_DataPtr+j] = CommVariant[i+j];
}
//RS_Len =2+16;
break;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -