📄 communicate.c
字号:
#define COMM_GLOBALS
#include "includes.h"
const INT8U SuperPassWord[]={0x00,0x27,0x10,0x79};
const struct CommunicateDataStruct CommunicateDataTable[]=
{ /*
数据标识;
数据长度;
数据特征:
b7~b6:数据寻址方式:
00:数据在RAM中;
01:数据在EEPROM中固定地址;
10:数据在EEPROM中动态地址;
11:数据在RAM和EEPROM固定地址中,并且要求两者同步更新;
b5:是否允许读操作;
b4:是否允许写操作;
b3~b0:特殊处理过程编号;
EEPROM数据地址;
RAM数据地址;
*/
{0x901f , 16 , 0x20 , 0 , (INT16U)&EnergyData.ActiveTotalEnergy[0]}, //(当前)正向有功电能集合
{0x9020 , 4 , 0x20 , 0 , (INT16U)&EnergyData.ActiveReverseEnergy[0]},//反向累计电量
{0xb020 , 4 , 0x60 , LAST_POWER_REVERSE_TIME_ID , 0},//最后一次反向起始时间
{0xb021 , 3 , 0x20 , 0 , (INT16U)&ReverseTotalTime[0]},//反向累计总时间
{0xb210 , 4 , 0x60 , LAST_PROGRAM_TIME_ID , 0},//最近一次编程时间
{0xb212 , 2 , 0x20 , 0 , (INT16U)&ProgramTimes[0]},//总的编程次数
{0xC010 , 4 , 0x32 , 0x00 , (INT16U)&CurrentTime.Weekday}, // 日期及周次
{0xC011 , 3 , 0x33 , 0x00 , (INT16U)&CurrentTime.Second}, // 时间
{0xC020 , 1 , 0x20 , 0x00 , (INT16U)&MeterRunningState}, // 电表运行状态
{0xC030 , 3 , 0x60 , P_METER_CONST_ID , 0},// 电表常数(有功)
{0xC032 , 6 , 0x70 , METER_NUMBER_ID , 0},// 表号
{0xC033 , 6 , 0xe0 , USER_NUMBER_ID , (INT16U)&UserNumber},// 用户号(局编号)v
{0xC115 , 3 , 0xd4 , DISPLAY_SELECT_ID , (INT16U)&DisplaySelect[0]},// 显示选择
{0xC117 , 2 , 0xf0 , MONTH_STORE_DATE_ID , (INT16U)&MonthStoreDate[0]},// 月转存日期
{0xC119 , 0 , 0x16 , 0 , 0},//正向总、峰、平、谷、反向总(使用清零密码)
{0xC33f , 36 , 0x35 , TIMESLICETABLE_ID , (INT16U)&TimeSliceInfo.TimeSlice[0].RateID},// 时段表设置
{0xd120 , 16 , 0xa1 , ACTIVE_ENERGY_ID0 , 0}, //上1月正向有功电能集合
{0xd121 , 16 , 0xa1 , ACTIVE_ENERGY_ID0 , 0}, //上2月正向有功电能集合
{0xd122 , 16 , 0xa1 , ACTIVE_ENERGY_ID0 , 0}, //上3月正向有功电能集合
{0xd123 , 16 , 0xa1 , ACTIVE_ENERGY_ID0 , 0}, //上4月正向有功电能集合
{0xd124 , 16 , 0xa1 , ACTIVE_ENERGY_ID0 , 0}, //上5月正向有功电能集合
{0xd125 , 16 , 0xa1 , ACTIVE_ENERGY_ID0 , 0}, //上6月正向有功电能集合
{0xd126 , 16 , 0xa1 , ACTIVE_ENERGY_ID0 , 0}, //上7月正向有功电能集合
{0xd127 , 16 , 0xa1 , ACTIVE_ENERGY_ID0 , 0}, //上8月正向有功电能集合
{0xd128 , 16 , 0xa1 , ACTIVE_ENERGY_ID0 , 0}, //上9月正向有功电能集合
{0xd129 , 16 , 0xa1 , ACTIVE_ENERGY_ID0 , 0}, //上10月正向有功电能集合
{0xd12a , 16 , 0xa1 , ACTIVE_ENERGY_ID0 , 0}, //上11月正向有功电能集合
{0xd12b , 16 , 0xa1 , ACTIVE_ENERGY_ID0 , 0}, //上12月正向有功电能集合
};
void CommunicateInit(void)
{
/*UART口初始化*/
HB_SCR3=0;
HB_SMR=0x20;//asy, 8bit, even,1stop
HB_BRR=129;//bps is 1200 when 10M crystal when using 38024F
DelayXms(1);
HF_SPCR_SPC32=1;
HF_SCR3_RE=1;
HF_SCR3_TE=0;
CommunicateReceiveEnable();
}
/*****************通信处理程序******************/
void CommunicateReceiveEnable(void)
{
_CommunicateReceiveEnableTask=0;
RecState=0;
HF_SCR3_RE=1;
HF_SCR3_TE=0;
HF_SCR3_RIE=1;
HB_SSR&=0x0c7;
Com485ReceiveBytes=0;
En_485Re;
Open_IRReceiveEdgInt;
Stop_IrMdlt;
}
void CommunicateSendEnable(void)
{
HF_SCR3_RE=0;
HF_SCR3_TE=1;
HF_SCR3_RIE=0;
HF_SCR3_TIE=0;
if(Com485ReceiveBytes>10)
{
En_485Tr;
}
else
{
Start_IrMdlt;
}
DelayXms(1);
_DataSend_=1;
PreCharactorCnt=1;
}
INT8U DichotomySearch(INT16U DataID)
{
INT8U Left=1;
INT8U Right=MAXCOMMUNICATENUM;
INT8U Middle;
while(Left<=Right)
{
Middle=(Left+Right)/2;
Middle--;
if (DataID==CommunicateDataTable[Middle].CommunicateDataID)
return Middle;
if (DataID>CommunicateDataTable[Middle].CommunicateDataID)
Left=Middle+2;
else Right=Middle;
}
return 255;
}
INT8U CommunicateReadData(void)
{
INT8U DataPos;
INT8U *Pnt;
INT8U i ;
INT16U DataTemp;
DataTemp=RecBuf[11];
DataTemp<<=8;
DataTemp+=RecBuf[10];
DataPos=DichotomySearch(DataTemp);
if(DataPos<MAXCOMMUNICATENUM)
{
if(CommunicateDataTable[DataPos].PropertyData1&0x20)
{
switch(CommunicateDataTable[DataPos].PropertyData1&0xc0)
{
case 0x00://ram区数据
case 0xc0://数据在RAM和EEPROM固定地址中
Pnt=(INT8U *)CommunicateDataTable[DataPos].RamDataAddress;
for(i=0;i<CommunicateDataTable[DataPos].DataLength;i++)
{
SendBuf[12+i]=*Pnt;
Pnt++;
}
break;
case 0x40://eeprom中固定地址数据
if(!ReadEepromData(CommunicateDataTable[DataPos].EepromDataId,&SendBuf[12]))
{
if(!ReadEepromData(CommunicateDataTable[DataPos].EepromDataId,&SendBuf[12]))
{
for(i=0;i<CommunicateDataTable[DataPos].DataLength;i++)
SendBuf[12+i]=0;
}
}
break;
case 0x80://eeprom中动态地址数据
i=RecBuf[10]&0x0f;
if(EnergyData.EnergyPointer>=(i+1))
{
TempBufOfMain[0]=(ACTIVE_ENERGY_ID0-1+EnergyData.EnergyPointer-i);
}
else
{
TempBufOfMain[0]=(ACTIVE_ENERGY_ID0+12+EnergyData.EnergyPointer-i);
}
if(!ReadEepromData(TempBufOfMain[0],&SendBuf[16]))
{
if(!ReadEepromData(TempBufOfMain[0],&SendBuf[16]))
{
for(i=0;i<CommunicateDataTable[DataPos].DataLength;i++)
SendBuf[12+i]=0;
}
}
break;
default:
return 0;
}
SendBuf[9]=CommunicateDataTable[DataPos].DataLength+2;
SendBuf[10]=RecBuf[10];
SendBuf[11]=RecBuf[11];
switch(CommunicateDataTable[DataPos].PropertyData1&0x0f)
{
case 1:
BcdAdd(&SendBuf[20],&SendBuf[16],TempBufOfMain,4);
BcdAdd(&SendBuf[24],TempBufOfMain,&SendBuf[12],4);
break;
case 5:
//时段表处理
SendBuf[9]=TimeSliceInfo.TimeSliceNum*3+2;
break;
default:
break;
}
return 1;
}
}
return 0;
}
INT8U CommunicateWriteData(void)
{
INT8U DataPos,Sign;
INT8U *Pnt;
INT8U i;
INT16U DataTemp;
if(Is_ProGramPermit)
{
if((RecBuf[10]==0x19)&&(RecBuf[11]==0xc1))
{
Sign=1;
for(i=0;i<4;i++)
{
if(RecBuf[12+i]!=Clear0PassWord[i])
{
Sign=0;
break;
}
}
if(Sign)
{
InitEnergyData(&RecBuf[20]);
_ProgramRecord=1;
SendBuf[9]=0;
return 1;
}
}
else
{
Sign=1;
for(i=0;i<4;i++)
{
if(RecBuf[12+i]!=ProgramPassWord[i])
{
Sign=0;
break;
}
}
if(Sign)
{
DataTemp=RecBuf[11];
DataTemp<<=8;
DataTemp+=RecBuf[10];
DataPos=DichotomySearch(DataTemp);
if(DataPos<MAXCOMMUNICATENUM)
{
if(CommunicateDataTable[DataPos].PropertyData1&0x10)//允许写
{
switch(CommunicateDataTable[DataPos].PropertyData1&0xc0)
{
case 0x00:
Pnt=(INT8U *)CommunicateDataTable[DataPos].RamDataAddress;
for(i=0;i<CommunicateDataTable[DataPos].DataLength;i++)
{
*Pnt=RecBuf[16+i];
Pnt++;
}
break;
case 0x40:
WriteEepromData(CommunicateDataTable[DataPos].EepromDataId,&RecBuf[16]);
break;
case 0xc0:
Pnt=(INT8U *)CommunicateDataTable[DataPos].RamDataAddress;
for(i=0;i<CommunicateDataTable[DataPos].DataLength;i++)
{
*Pnt=RecBuf[16+i];
Pnt++;
}
WriteEepromData(CommunicateDataTable[DataPos].EepromDataId,&RecBuf[16]);
break;
default:
return 0;
}
switch(CommunicateDataTable[DataPos].PropertyData1&0x0f)
{
case 2:
SetSystemDate(&CurrentTime.Weekday);
MultiRateInit();
if(IsBroadCalibrateTimePermit())
_BroadCalibrateTimeAllow_=1;
else
_BroadCalibrateTimeAllow_=0;
break;
case 3:
SetSystemTime(&CurrentTime.Second);
MultiRateInit();
if(IsBroadCalibrateTimePermit())
_BroadCalibrateTimeAllow_=1;
else
_BroadCalibrateTimeAllow_=0;
break;
case 4:
DisplayCircleInterval=(DisplaySelect[0]&0x0f)+(DisplaySelect[0]>>4)*10;
if(DisplaySelect[2]&0x80)
DisplayState=1;
else
DisplayState=0;
PaginationSign=0;
break;
case 5:
//时段表处理
TimeSliceInfo.TimeSliceNum=(RecBuf[9]-6)/3;
Pnt=&TimeSliceInfo.TimeSlice[TimeSliceInfo.TimeSliceNum].RateID;
for(i=RecBuf[9]-6;i<36;i++)
{
*Pnt=0;
Pnt++;
}
TimeSliceSort();
if(TimeSliceTableCheck())
{
WriteEepromData(CommunicateDataTable[DataPos].EepromDataId,&TimeSliceInfo.TimeSliceNum);
MultiRateInit();
}
else
{
if(!ReadEepromData(TIMESLICETABLE_ID,TempBufOfMain))
{
if(!ReadEepromData(TIMESLICETABLE_ID,TempBufOfMain))
InitEepromData(TIMESLICETABLE_ID);
}
InitRamData(TIMESLICETABLE_ID);
MultiRateInit();
return 0;
}
break;
default:
break;
}
_ProgramRecord=1;
SendBuf[9]=0;
return 1;
}
}
}
}
}
return 0;
}
void BroadcastSetTime(void)
{
CurrentTime.Year=RecBuf[15];
CurrentTime.Month=RecBuf[14];
CurrentTime.Day=RecBuf[13];
CurrentTime.Hour=RecBuf[12];
CurrentTime.Minute=RecBuf[11];
CurrentTime.Second=RecBuf[10];
CurrentTime.Weekday=GetWeekDay(CurrentTime.Month,CurrentTime.Day, CurrentTime.Year);
SetSystemDateAndTime(&CurrentTime.Second);
MultiRateInit();
TempBufOfMain[0]=CurrentTime.Hour;
TempBufOfMain[1]=CurrentTime.Day;
TempBufOfMain[2]=CurrentTime.Month;
TempBufOfMain[3]=CurrentTime.Year;
WriteEepromData(LAST_BROADCAST_TIME_ID,TempBufOfMain);
_BroadCalibrateTimeAllow_=0;
_ProgramRecord=1;
}
void CommunicateWriteUserID(void)
{
INT8U i;
INT8U *Pnt;
Pnt=&RecBuf[10];
for(i=0;i<6;i++)
{
UserNumber[i]=*Pnt;
TempBufOfMain[i]=*Pnt;
Pnt++;
}
WriteEepromData(USER_NUMBER_ID,&RecBuf[10]);
SendBuf[9]=0;
_ProgramRecord=1;
}
INT8U CommunicateChangePassword(void)
{
INT8U i,PasswordType;
INT8U *Pnt;
PasswordType=PROGRAM_PASSWORD;
for(i=0;i<4;i++)
{
if(RecBuf[10+i]!=ProgramPassWord[i])
{
PasswordType=CLEAR0_PASSWORD;
break;
}
}
if(PasswordType==CLEAR0_PASSWORD)
{
for(i=0;i<4;i++)
{
if(RecBuf[10+i]!=Clear0PassWord[i])
{
PasswordType=SUPER_PASSWORD;
break;
}
}
}
if(PasswordType==SUPER_PASSWORD)
{
for(i=0;i<4;i++)
{
if(RecBuf[10+i]!=SuperPassWord[i])
{
PasswordType=ERROR_PASSWORD;
break;
}
}
}
switch(PasswordType)
{
case ERROR_PASSWORD:
return 0;
case SUPER_PASSWORD:
if(RecBuf[14]==0)
{
SetClear0Password();
}
else if(RecBuf[14]==1)
{
SetProgramPassword();
}
else
return 0;
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -