📄 protocol.c
字号:
//0xC11B 设置有功电能起始读数的时间,年月日时分秒 6字节
_save_time_to_e2prom_(ADDRESS_OF_STARTING_COUNT_TIME);
return _NOWRITEE2PROM_;
}
//0xC33F,0xC34F,0xC35F,0xC36F,0xC37F,0xC38F,0xC39F,0xC3AF,0xC3BF,0xC3CF,0xC3DF,0xC3EF
static unsigned char _slvs_wr_proc4_(void)
{
//DI1DI0=((FrameBuffer[DI0]>>4)-0x03)*3 +ADDRESS_OF_TIME_SECT;
DI1DI0=ADDRESS_OF_TIME_SECT;
ReadPeriodOfTimeCount(&FrameBuffer[FRM_DATALEN]);
FrameBuffer[FRM_DATALEN]*=3;
return _WRITEE2PROM_;
}
const unsigned char _slvs_wr_p6_addr_[] =
{
ADDRESS_OF_PERIOD_OF_TIME_COUNT,//0xC312
//PTL_ADDRESS_OF_CHECKTIME_RANGE,//0xC013
//PTL_ADDRESS_OF_YEAR_TIME_ZONE_NUM,//0xC310
//PTL_ADDRESS_OF_DAY_TIMESECTION_TABLE_NUM,//0xC311
//PTL_ADDRESS_OF_CHARGE_TYPE_NUM,//0xC313
//PTL_ADDRESS_OF_COMM_HOLIDAY_NUM,//0xC314
ADDRESS_OF_SETTLEMENT_HOUR,//0xC117
//PTL_ADDRESS_OF_POWER_LIMIT,//0xC214
PTL_ADDRESS_OF_WATCH_NO,//0xC032
PTL_ADDRESS_OF_USER_NO,//0xC033
//PTL_ADDRESS_OF_DEVICE_NO,//0xC034
};
//
static unsigned char _slvs_wr_proc5_(void)
{
FrameBuffer[FRM_DATALEN]=_slvs_read_p5_len_[SlvsWrDataLenIdx];
DI1DI0=_slvs_wr_p6_addr_[SlvsWrDataAddrIdx];
return _WRITEE2PROM_;
}
static unsigned char _slvs_wr_proc6_(void)
{
DI1DI0=ADDRESS_OF_DEVICE_CONSTANT;
FrameBuffer[FRM_DATALEN]=3;
ReadPPC();
if(PowerPulseConstant_==0)
{
PowerPulseConstant_=FrameBuffer[17];
return _WRITEE2PROM_;
}
else
return _NOWRITEE2PROM_;
}
const unsigned short _slvs_cmds_write_[]=
{
0xC115,
0,
0xC010,0xC011,
0,
0xC119,
0,
0xC33F,//0xC34F,0xC35F,0xC36F,0xC37F,0xC38F,0xC39F,0xC3AF,0xC3BF,0xC3CF,0xC3DF,0xC3EF,
0,
0xF0F0,//Len=1
0xC312,//0xC013,//0xC310,0xC311,0xC313,0xC314,
0xF0F0,//Len=2
0xC117,
0xF0F0,//Len=3
0xF0F0,//Len=4
//0xC214,
0xF0F0,//Len=6
0xC032,0xC033,//0xC034,
//0,
//0xF0F0,
//0xC32F,
0,
0xC030,
0xFFFF
};
const COMM_PROC_PTR _slvs_process_write_ []=
{
_slvs_wr_proc1_,
_slvs_wr_proc2_,
_slvs_wr_proc3_,
_slvs_wr_proc4_,
_slvs_wr_proc5_,
_slvs_wr_proc6_
};
//电表清零
void _clear_power_data_(void)
{
unsigned char k;
_memset0_and_write_e2prom_(PTL_ADDRESS_OF_START_POWER,LEN_ADDRESS_OF_POWER);
_memset0_and_write_e2prom_(ADDRESS_OF_MONTH_CURRENT,LEN_ADDRESS_OF_POWER);
for(k=0;k<12;k++)
{
_memset0_and_write_e2prom_(ADDRESS_OF_MONTH_LOG+k*40,40);
}
_memset0_and_write_e2prom_(ADDRESS_OF_STARTING_COUNT,20);
_memset0_and_write_e2prom_(ADDRESS_OF_START_TIME_MINUS,37);
ClearPowerPulseDataInRam();
//写入E2PROM里面的内容为年月日时分秒
_save_time_to_e2prom_(PTL_ADDRESS_OF_POWER_CLEAR_TIME);
//清零次数累加,因为后面不需要DI1DI0的值了,所以这里借用一下
_bcd_short_add1_and_write_e2prom_(PTL_ADDRESS_OF_POWER_CLEAR_COUNT);
//写入最后一次编程时间,年月日时分秒
_save_time_to_e2prom_(ADDRESS_OF_PROGRAM_TIME);
// 累加 编程次数2字节
_bcd_short_add1_and_write_e2prom_(ADDRESS_OF_PROGRAM_TIMES);
}
unsigned char FindCmdItem(const unsigned short *cmds)
{
unsigned char i=0,Idx=0,cFlag=0;
do{
if(cmds[i]==DI1DI0)
return Idx;
if(cmds[i]==0)
{
Idx++;
SlvsWrDataAddrIdx=0;
SlvsWrDataLenIdx=0xFF;
cFlag=0;
}
if(cmds[i]==0xF0F0)
{
SlvsWrDataLenIdx++;
SlvsWrDataAddrIdx--;
cFlag=1;
}
if(cFlag)
{
SlvsWrDataAddrIdx++;
}
}while(cmds[i++]!=0xFFFF);
return 0xFF;
}
//校验密码
unsigned char CheckPassword(unsigned char *pucData)
{
unsigned char ucaTemp[4];
#ifdef SINGLE_PASSWORD_SCHEME
E2promRead(PTL_ADDRESS_OF_DEVICE_PASSWORD_0, ucaTemp,4);
#else
E2promRead(PTL_ADDRESS_OF_DEVICE_PASSWORD_0 + pucData[0]<<2, ucaTemp, 4);
#endif
if(!IsEqual(&ucaTemp[1],pucData,3)) return ERROR;
return OK;
}
unsigned char Read_SlaveStationData(void)
{
unsigned char pIdx;
pIdx=FindCmdItem(_slvs_cmds_read_);
if(pIdx!=0xFF)
{
pIdx=(_slvs_process_read_[pIdx])();
goto Read_Slave_E;
}
else
pIdx=FindCmdItem(_slvs_cmds_write_);
if(pIdx!=0xFF)
pIdx=(_slvs_process_write_[pIdx])();
else
goto Read_Slave_Return_Error;
Read_Slave_E:
if(pIdx==_NOREADE2PROM_)
goto Read_Slave_Return_Ok;
//Read_Slave_Read_E2prom:
E2promRead(DI1DI0,&FrameBuffer[FRM_DATA+2],FrameBuffer[FRM_DATALEN]);
//Read_Slave_No_Read_E2prom:
Read_Slave_Return_Ok:
FrameBuffer[FRM_DATALEN]+=2;
return OK;
Read_Slave_Return_Error:
return ERROR;
}
unsigned char Write_SlaveStationData(void)
{
unsigned char pIdx;
if(CheckPassword(&FrameBuffer[FRM_DATA+3]) != OK)
goto Write_Slave_Return_Error;
pIdx=FindCmdItem(_slvs_cmds_write_);
if(pIdx!=0xFF)
pIdx=(_slvs_process_write_[pIdx])();
else
goto Write_Slave_Return_Error;
if(pIdx!=_WRITEE2PROM_)
goto Write_Slave_Return_Ok;
//Write_Slave_Write_E2prom:
E2promWrite(DI1DI0, &FrameBuffer[16], FrameBuffer[FRM_DATALEN]);
//Write_Slave_No_Write_E2prom:
Write_Slave_Return_Ok:
FrameBuffer[FRM_DATALEN]=0;
//写入最后一次编程时间,年月日时分秒
_save_time_to_e2prom_(ADDRESS_OF_PROGRAM_TIME);
// 累加 编程次数2字节
_bcd_short_add1_and_write_e2prom_(ADDRESS_OF_PROGRAM_TIMES);
return OK;
Write_Slave_Return_Error:
return ERROR;
}
unsigned char TestCLR(void)
{
unsigned char i;
for(i=0;i<100;i++)
{
if(CLR_IN&CLR)
{
return(0);
}
else
{
Delay(10);
ClrWDT();
}
}
return(1);
}
void ClearWholeE2prom(void)
{
unsigned short ii;
for(ii=0;ii<2048;ii+=32)
{
_memset0_and_write_e2prom_(ii, 32);
}
DeviceBasicInit();
}
unsigned char ChkPwdAndSend(void)
{
if(CheckPassword(&FrameBuffer[FRM_DATA+1]) != OK) return ERROR;
FrameBuffer[FRM_DATALEN]=0;
Tx_FrameInfo();
LcdLightOn(5);
return OK;
}
//解析接收到的数据桢
void Parse_RxFrame(void)
{
unsigned char ucAddressFlag;
//unsigned char ucTemp,ucTemp1;
//unsigned short usTemp;
ucAddressFlag=CompareAddressArea();
DI1DI0=FrameBuffer[DI0]|(FrameBuffer[DI1]<<8);
if(ucAddressFlag==COMPARE_FLAG_SINGLE_NO)
{
if(FrameBuffer[FRM_COMMAND]!=0x01)
{
if((LcdDisplayChoose&0x1000)==0)
goto Parse_Err_CMD;
}
switch(FrameBuffer[FRM_COMMAND])
{
case 0x01:
if(Read_SlaveStationData()!=OK)
goto Parse_Err_CMD;
break;
case 0x04://写数据
if(Write_SlaveStationData()!=OK)
goto Parse_Err_CMD;
break;
case 0x0F://写密码
if(CheckPassword(&FrameBuffer[FRM_DATA+1]) != OK) goto Parse_End;;
#ifdef SINGLE_PASSWORD_SCHEME
//<<<<<<<<<<<<<<<<<<<<
#else
//提供的密码权限比要设定的密码权限小,退出
if(FrameBuffer[FRM_DATA] > FrameBuffer[FRM_DATA+4]) return;
#endif
memcpy(&FrameBuffer[FRM_DATA],&FrameBuffer[FRM_DATA+4], 4);
#ifdef SINGLE_PASSWORD_SCHEME
E2promWrite(PTL_ADDRESS_OF_DEVICE_PASSWORD_0, &FrameBuffer[FRM_DATA], 4); //<<<<<<<<<<<<<<
#else
//优化后的代码,去除了switch或者if语句,将密码顺序存放,所以可以顺序索引
ucTemp = PTL_ADDRESS_OF_DEVICE_PASSWORD_0 + pucData[0]<<2;
E2promWrite(ucTemp, pucData, 4);
//if() != OK)
//{
// memset(&(strFrameInfo.g_ucaFrame_Data[1]), 0, 3);
//}
#endif
FrameBuffer[FRM_DATALEN]=4;
break;
case 0x09:// 电量清零
FrameBuffer[FRM_COMMAND]=0x89;
if(ChkPwdAndSend()==OK)
{
_clear_power_data_();
}
goto Parse_End;
case 0x10:// 电表总清零
FrameBuffer[FRM_COMMAND]=0x8A;
if(ChkPwdAndSend()==OK)
{
_clear_power_data_();
_memset0_and_write_e2prom_(ADDRESS_OF_DEVICE_NUMBER,64);
_memset0_and_write_e2prom_(ADDRESS_OF_SETTLEMENT_HOUR,46);
}
goto Parse_End;
case 0x6F:// 清密码
if(TestCLR())
_memset0_and_write_e2prom_(ADDRESS_OF_DEVICE_PASSWORD1,12);
else
goto Parse_End;
break;
case 0x6E:// 清电表常数
if(TestCLR())
_memset0_and_write_e2prom_(ADDRESS_OF_DEVICE_CONSTANT,4);
else
goto Parse_End;
break;
case 0x6D:// 清E2prom
if(CheckPassword(&FrameBuffer[FRM_DATA+1]) != OK) goto Parse_End;
if(TestCLR())
{
ClearWholeE2prom();
ClearPowerPulseDataInRam();
//TotleTimeOfMiuns=0;
LcdLightOn(5);
}
goto Parse_End;
default:
goto Parse_Err_CMD;
}
}
else if(ucAddressFlag==COMPARE_FLAG_BROADCAST)
{
//广播校时
if(FrameBuffer[FRM_COMMAND]==0x08)
{
unsigned char ucTemp;
#ifndef _HARDWARE_RTC
unsigned char time_bcd[7];
#endif
//unsigned short ucTemp1,ucTemp2;
if(LcdDisplayChoose&0x1000)
goto Set_Time;
E2promRead(ADDRESS_OF_SUCCESSSETTIME_FLAG, &ucTemp, LEN_OF_SUCCESSSETTIME_FLAG);
//it doesn't use during Test
if(ucTemp != 1) //如果对时标记=1,说明已经在周期内对过时了,退出
{
//如果年、月、日不对,则退出
#ifdef _HARDWARE_RTC
if(!IsEqual(&g_time[SPACE_OF_DAY],&FrameBuffer[FRM_DATA+3], 3)) goto Parse_End;;
#else
GetSystemTimeBcd(time_bcd);
if(!IsEqual(&time_bcd[SPACE_OF_DAY],&FrameBuffer[FRM_DATA+3], 3)) goto Parse_End;;
#endif
if (CheckSystemTime(&FrameBuffer[FRM_DATA])==1)
{
goto Parse_End;
}
Set_Time:
//写入对时时间
#ifndef _HARDWARE_RTC
_DINT();
#endif
memcpy(g_time, &FrameBuffer[FRM_DATA], RTC_TIME_LEN);
memcpy(g_time+4, &FrameBuffer[FRM_DATA+3], RTC_DATA_LEN);
SetSystemTime(); //对时
#ifndef _HARDWARE_RTC
_EINT();
#endif
_save_time_to_e2prom_(PTL_ADDRESS_OF_LASTSETTIME_TIME);
ucTemp=0x01;
E2promWrite(ADDRESS_OF_SUCCESSSETTIME_FLAG,&ucTemp,1);
LcdLightOn(5);
}
goto Parse_End;
}
else if(FrameBuffer[FRM_COMMAND]==0x01)
{
if(Read_SlaveStationData()!=OK)
goto Parse_Err_CMD;
}
//写设备地址
else
{
if((LcdDisplayChoose&0x1000)==0)
goto Parse_Err_CMD;
if(FrameBuffer[FRM_COMMAND]==0x0A)
{
E2promWrite(PTL_ADDRESS_OF_WATCH_NO, &FrameBuffer[FRM_DATA], LEN_OF_WATCH_NO);
FrameBuffer[FRM_DATALEN]=0;
}
else if(FrameBuffer[FRM_COMMAND]==0x04)
{
if(Write_SlaveStationData()!=OK)
goto Parse_Err_CMD;
}
else
{
goto Parse_End;
}
}
}
else
{
goto Parse_End;
}
//Parse_Ok:
FrameBuffer[FRM_COMMAND]|=0x80;
LcdLightOn(5);
goto Parse_SendFrame;
Parse_Err_CMD:
//Parse_Err:
FrameBuffer[FRM_COMMAND]=0xCC;
FrameBuffer[FRM_DATALEN]=1;
FrameBuffer[FRM_DATA]=ERROR_DATA;
Parse_SendFrame:
Tx_FrameInfo();
Parse_End:
return;
}
//发送数据桢
void Tx_FrameInfo(void)
{
unsigned char ucCS=0;
//UartTxBondRate=UART_BOND_RATE_1200;//Set Uart Tx Boudrate
//P6OUT|=(IR_EN);
//先发送4个前导字
for(FramePointer=0; FramePointer<4; FramePointer++)
{
UartSendByte(PRE_FRAME_FLAG);
}
E2promRead(PTL_ADDRESS_OF_WATCH_NO, &FrameBuffer[FRM_ADDR], LEN_OF_WATCH_NO);
//发送数据桢
for(FramePointer=0; FramePointer<FRM_CS; FramePointer++)
{
if(FramePointer>FRM_DATALEN)
FrameBuffer[FramePointer]+=FRAME_DATA_APPENDVALUE;
UartSendByte(FrameBuffer[FramePointer]);
ucCS+=FrameBuffer[FramePointer];
}
//发送校验值
UartSendByte(ucCS);
//发送帧结束标志
UartSendByte(FRAME_END_FLAG);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -