📄 comm.c
字号:
typedef struct
{
unsigned int ComID;
unsigned char *Addr;
unsigned int Info;
}COMINFO;
const COMINFO ComInfo[] =
{
//************************************************************
// 电能数据
//************************************************************
// 正向有功
//------------------- 当 前 --------------------
0x9010, SM.CMon.Fee[0], 4 +RS_TP_Norm,
0x9011, SM.CMon.Fee[1], 4 +RS_TP_Norm,
0x9012, SM.CMon.Fee[2], 4 +RS_TP_Norm,
0x9013, SM.CMon.Fee[3], 4 +RS_TP_Norm,
0x9014, SM.CMon.Fee[4], 4 +RS_TP_Norm,
0x901F, SM.CMon.Fee[0], 4*5 +RS_TP_Norm,
//------------------- 上 月 --------------------
0x9410, SM.LMon.Fee[0], 4 +RS_TP_Norm,
0x9411, SM.LMon.Fee[1], 4 +RS_TP_Norm,
0x9412, SM.LMon.Fee[2], 4 +RS_TP_Norm,
0x9413, SM.LMon.Fee[3], 4 +RS_TP_Norm,
0x9414, SM.LMon.Fee[4], 4 +RS_TP_Norm,
0x941F, SM.LMon.Fee[0], 4*5 +RS_TP_Norm,
//------------------- 上 上 月 --------------------
0x9810, SM.LMon.Fee[0], 4 +RS_TP_Norm,
0x9811, SM.LMon.Fee[1], 4 +RS_TP_Norm,
0x9812, SM.LMon.Fee[2], 4 +RS_TP_Norm,
0x9813, SM.LMon.Fee[3], 4 +RS_TP_Norm,
0x9814, SM.LMon.Fee[4], 4 +RS_TP_Norm,
0x981F, SM.LMon.Fee[0], 4*5 +RS_TP_Norm,
// 反向累计电能
0x9020, SM.CMon.RevEC, 4 +RS_TP_Norm,
// 历史数据
0xD120, SM.LMon.Fee[0], 4*5 +RS_TP_LMon,
0xD121, SM.LMon.Fee[0], 4*5 +RS_TP_LMon,
0xD122, SM.LMon.Fee[0], 4*5 +RS_TP_LMon,
0xD123, SM.LMon.Fee[0], 4*5 +RS_TP_LMon,
0xD124, SM.LMon.Fee[0], 4*5 +RS_TP_LMon,
0xD125, SM.LMon.Fee[0], 4*5 +RS_TP_LMon,
0xD126, SM.LMon.Fee[0], 4*5 +RS_TP_LMon,
0xD127, SM.LMon.Fee[0], 4*5 +RS_TP_LMon,
0xD128, SM.LMon.Fee[0], 4*5 +RS_TP_LMon,
0xD129, SM.LMon.Fee[0], 4*5 +RS_TP_LMon,
//************************************************************
// 电表配置数据
//************************************************************
0xB020, SM.Cfg.IRevTmr, 4 +RS_TP_Norm, // 最近一次反向起启时间
0xB021, SM.Cfg.IRevAllTmr, 3 +RS_TP_Norm, // 反向累计总时间
0xB210, SM.Cfg.ProgDT, 4 +RS_TP_Norm, // 最近一次编程时间
0xB212, SM.Cfg.ProgTms, 2 +RS_TP_Norm, // 编程次数
//************************************************************
// 其它参数
//************************************************************
0xC010, SM.Clk.Week, 4 +RS_TP_Clk +RS_TP_wr, // 电表日期
0xC011, SM.Clk.Sec, 3 +RS_TP_Clk +RS_TP_wr, // 电表时间
0xC01F, SM.Clk.Sec, 7 +RS_TP_Clk +RS_TP_wr, // 自定义
0xC020, SM.Cfg.MetStatus, 1 +RS_TP_Norm +RS_TP_wr, // 电表状态
0xC030, SM.Cfg.MetConst, 3 +RS_TP_Norm +RS_TP_wr, // 电表常数
0xC032, SM.Cfg.MetID, 6 +RS_TP_Norm +RS_TP_wr, // 电表号
0xC033, SM.Cfg.CustID, 6 +RS_TP_Norm +RS_TP_wr, // 用户号
0xC115, (unsigned char*)&SM.Cfg.LcdCtl.Reg, 3 +RS_TP_Norm +RS_TP_wr, // 显示控制
0xC117, SM.Cfg.BillDay, 2 +RS_TP_Norm +RS_TP_wr, // 结算日
0xC119, SM.CMon.Fee[0], 4 +RS_TP_Norm +RS_TP_wr, // 表清零(使用清零密码)
0xC212, SM.Cfg.Pswd[1], 4 +RS_TP_Norm +RS_TP_wr, // 密码
0xC33F, (unsigned char*)&SM.Cfg.TariList[0], 3*8 +RS_TP_Tariff +RS_TP_wr, // 费率表
0xE010, SM.Cfg.UnCover.Tmr[0], 4 +RS_TP_Norm +RS_TP_wr, // 最近一次开盖时间
0xE011, SM.Cfg.UnCover.Tmr[1], 4 +RS_TP_Norm +RS_TP_wr, // 最近上一次开盖时间
0xE012, SM.Cfg.UnCover.Tms, 2 +RS_TP_Norm +RS_TP_wr, // 开盖次数
//************************************************************
// 继电器控制
//************************************************************
0xE431, (unsigned char *)0x200, 0,
0xE431, (unsigned char *)0x200, 0,
};
const int ComInfoNum = sizeof(ComInfo)/sizeof(COMINFO);
void TimeAInit(void)
{
CCR0 = 0x8000;
CCTL0 |= CCIE;
CCR1 = 0;
TACTL = TASSEL0|TACLR; // 0x104;
TACTL |= MC1;
}
void CapStart(void)
{
RS485_CON_OUT |= RS485_CON_BIT; //Added by ZhaoZhendong 2006.01.18
RS485_IR_RX_DIR &= ~RS485_IR_RX_BIT;
RS485_IR_RX_SEL |= RS485_IR_RX_BIT;
CCTL1 &= ~CCIFG;
CCTL1 |= (CAP+CM1+SCS+CCIE);
}
void RXRst(void)
{
ComFlagRAM &=~D_Comm;
#ifndef DATA_IN_LCDMEM
DM.Flgs &=~F_RS;
#else
DM1.Flgs &=~F_RS;
#endif
RS485_CON_OUT |= RS485_CON_BIT; //Added by ZhaoZhendong 2006.01.18
RS485_IR_RX_DIR &= ~RS485_IR_RX_BIT;
RS485_IR_RX_SEL |= RS485_IR_RX_BIT;
CCTL1 &= ~CCIFG;
CCTL1 |= (CAP+CM1+SCS+CCIE);
}
void SendStart(void)
{
#ifndef DATA_IN_LCDMEM
DM.Flgs |= F_RS; // 开始发送
#else
DM1.Flgs |= F_RS; // 开始发送
#endif
DM.RS.ComBit=0;
DM.RS.ComPtr =0;
DM.RS.ByteCS=0;
IR_TX_OUT &= ~IR_TX_BIT;
IR_TX_DIR |= IR_TX_BIT;
IR_TX_SEL &= ~IR_TX_BIT;
CCR1 =TAR+300;
CCTL1 &= ~(CAP+CM1+CCIFG);
CCTL1 |= (SCS+CCIE);
}
const unsigned char SendComOffset[]=
{
27,27,28,27,27,28,27,27,28,27,27,250
};
void ProcSend( void )
{
CCR1=CCR1+SendComOffset[DM.RS.ComBit];
switch(DM.RS.ComBit)
{
case 0:
DM.RS.ComTmr=6; // 启动600ms的发送超时
RS485_CON_OUT &=~RS485_CON_BIT;
_NOP();
IR_TX_OUT |= IR_TX_BIT; // open 38k
RS485_TX_OUT &= ~RS485_TX_BIT; // open 38k
IR_TX_SEL |= IR_TX_BIT;
DM.RS.hByte = DM.RS.ComBuf[DM.RS.ComPtr];
DM.RS.ByteCS=0;
break;
case 9:
if ((DM.RS.ByteCS&1)==1)
{
IR_TX_SEL &= ~IR_TX_BIT;
IR_TX_OUT &= ~IR_TX_BIT;
RS485_TX_OUT |= RS485_TX_BIT;
} // close 38k
else
{
IR_TX_OUT |= IR_TX_BIT;
IR_TX_SEL |= IR_TX_BIT;
RS485_TX_OUT &= ~RS485_TX_BIT;
}
break;
case 10:
IR_TX_OUT &= ~IR_TX_BIT; // close 38k
IR_TX_SEL &= ~IR_TX_BIT;
RS485_TX_OUT |= RS485_TX_BIT; // close 38k
break;
case 11:
IR_TX_OUT &= ~IR_TX_BIT; // close 38k
IR_TX_SEL &= ~IR_TX_BIT;
RS485_TX_OUT |= RS485_TX_BIT; // close 38k
_NOP();
RS485_CON_DIR |= RS485_CON_BIT; //Removed by ZhaoZhendong 2006.01.18
DM.RS.ComTmr=6; // 启动600ms的发送超时
DM.RS.ComBit=0;
DM.RS.ComPtr++; // 字节加 '1'
goto loopbyte;
default:
if ((DM.RS.hByte &1)==1)
{
IR_TX_SEL &= ~IR_TX_BIT;
IR_TX_OUT &= ~IR_TX_BIT;
DM.RS.ByteCS++;
RS485_TX_OUT |= RS485_TX_BIT; // close 38k
}
else
{
IR_TX_OUT |= IR_TX_BIT;
IR_TX_SEL |= IR_TX_BIT;
RS485_TX_OUT &= ~RS485_TX_BIT; // open 38k
}
DM.RS.hByte >>=1;
break;
}
DM.RS.ComBit++;
return;
loopbyte:
if (DM.RS.ComPtr>RS_Len+11)
{
ComFlagRAM &=~D_Comm;
#ifndef DATA_IN_LCDMEM
DM.Flgs &=~F_RS;
#else
DM1.Flgs &=~F_RS;
#endif
RS485_CON_OUT |= RS485_CON_BIT; //Added by ZhaoZhendong 2006.01.18
RS485_IR_RX_DIR &= ~RS485_IR_RX_BIT;
RS485_IR_RX_SEL |= RS485_IR_RX_BIT;
CCTL1 &= ~CCIFG;
CCTL1 |= (CAP+CM1+SCS+CCIE);
DM.RS.ComPtr=0;
DM.RS.ComTmr=0; // 停止发送超时
}
}
//*****************************************************************
// Calculate the CRC
//*****************************************************************
unsigned char ComCRC( void )
{
unsigned char iii,Sum;
Sum=0;
iii=0;
while( iii<(RS_Len+RS_CmdPtr) )
{
Sum+=DM.RS.ComBuf[iii];
iii++;
}
return Sum;
}
//*****************************************************************
// main communication program
//*****************************************************************
void ProcCom(void)
{
unsigned int Cmd;
unsigned char *Buf;
unsigned char Ptr,Tmp;
DM.Tsk.Req.Com=0;
if( RS_Head!=0x68 || RS_Head0!=0x68 || RS_End!=0x16 ) goto LoopComExit;
if( RS_CRC!=ComCRC() ) goto LoopComExit;
if( RS_Ctl!=RS_CTL_MetID && RS_Ctl!=RS_CTL_Time)
{
for( Ptr=0,Buf=&RS_Addr;Ptr<6;Ptr++,Buf++ )
{
if( Ptr==0 && *Buf==0xAA ) goto LoopComExit;
if( *Buf!=SM.Cfg.MetID[Ptr] && *Buf!=0xAA ) goto LoopComExit;
}
}
if( RS_Len>30 ) goto LoopComExit;
for( Ptr=0,Buf=&RS_Cmd;Ptr<RS_Len;Ptr++,Buf++ ) *Buf-=0x33;
switch ( RS_Ctl )
{
case RS_CTL_Read:
Cmd=((unsigned int)RS_CmdH<<8)+RS_CmdL;
Ptr=0;
for( Ptr=0;Ptr<ComInfoNum;Ptr++ )
{
if( ComInfo[Ptr].ComID==Cmd ) break;
}
if( Ptr>=ComInfoNum ) goto ReadLoop1;
RS_Len=(ComInfo[Ptr].Info&0xFF)+2;
switch( ComInfo[Ptr].Info&RS_TP )
{
case RS_TP_Norm:
case RS_TP_Clk:
MemCopy( &RS_Data, ComInfo[Ptr].Addr, ComInfo[Ptr].Info&0xFF);
break;
case RS_TP_LMon:
Tmp=Cmd&0x000f;
GetI2CData( DM.Reg.b,E2PG2,ECPtr,1 );
GetI2CData( (unsigned char*)&SM.LMon,E2PG2,LMonAddr[Ptr>=Tmp?Ptr-Tmp:Ptr+10-Tmp],sizeof(LMONBLK)+2 );
MemCopy( &RS_Data, ComInfo[Ptr].Addr, ComInfo[Ptr].Info&0xFF);
break;
case RS_TP_Tariff:
for(Ptr=0,Ptr=0;Ptr<8;Ptr++,Tmp+=3)
{
DM.RS.ComBuf[Tmp+12]=SM.Cfg.TariList[Ptr].FeeNo+1;
DM.RS.ComBuf[Tmp+13]=SM.Cfg.TariList[Ptr].Tmr&0xff;
DM.RS.ComBuf[Tmp+14]=SM.Cfg.TariList[Ptr].Tmr>>8;
}
break;
default:
goto ReadLoop1;
}
SM.Cfg.ReadDT[0]=SM.Clk.Min[0];
SM.Cfg.ReadDT[1]=SM.Clk.Hour[0];
SM.Cfg.ReadDT[2]=SM.Clk.Day[0];
SM.Cfg.ReadDT[3]=SM.Clk.Mon[0];
goto ReadLoop2;
ReadLoop1:
RS_Ctl|=0x40;
RS_Len=1;
RS_Cmd=1;
ReadLoop2:
break;
case RS_CTL_Write:
if( !((KEY_PROG_IN & KEY_PROG_BIT)==0) ) goto LoopComExit;
if( RS_Data>1 ) goto WriteLoop1;
for(Ptr=0,Buf=&RS_Data; Ptr<=3; Ptr++,Buf++)
{
if( (*Buf)!=SM.Cfg.Pswd[1][Ptr]) goto WriteLoop1;
}
Cmd=((unsigned int)RS_CmdH<<8)+RS_CmdL;
Ptr=0;
for( Ptr=0;Ptr<ComInfoNum;Ptr++ )
{
if( ComInfo[Ptr].ComID==Cmd ) break;
}
if( Ptr>=ComInfoNum || RS_Len!=((ComInfo[Ptr].Info&0xFF)+6) ) goto WriteLoop1;
if( (ComInfo[Ptr].Info&RS_TP_wr)==0 ) goto WriteLoop1;
switch( ComInfo[Ptr].Info&RS_TP )
{
case RS_TP_Norm:
MemCopy( ComInfo[Ptr].Addr, &RS_Data+4, ComInfo[Ptr].Info&0xFF);
break;
case RS_TP_Clk:
MemCopy( ComInfo[Ptr].Addr, &RS_Data+4, ComInfo[Ptr].Info&0xFF);
SM.ClkChk=ChkSum( SM.Clk.Sec, sizeof(RTC) );
break;
case RS_TP_Tariff:
for(Ptr=0,Tmp=0;Ptr<8;Ptr++,Tmp+=3)
{
SM.Cfg.TariList[Ptr].FeeNo=DM.RS.ComBuf[Tmp+16]-1;
SM.Cfg.TariList[Ptr].Tmr=(DM.RS.ComBuf[Tmp+18]<<8)+DM.RS.ComBuf[Tmp+17];
}
break;
default:
goto WriteLoop1;
}
SM.Cfg.ProgDT[0]=SM.Clk.Min[0];
SM.Cfg.ProgDT[1]=SM.Clk.Hour[0];
SM.Cfg.ProgDT[2]=SM.Clk.Day[0];
SM.Cfg.ProgDT[3]=SM.Clk.Mon[0];
SM.CfgChk=ChkSum((unsigned char *)&SM.Cfg, sizeof(CFGGRP));
SM.CMonChk=ChkSum(SM.CMon.Fee[0], sizeof(CMONBLK));
SM.E2Flgs |= S_E2CFGGRP;
SM.E2Flgs |= S_E2CMONGRP;
DM.Tsk.Req.I2C=1;
RS_Len=0;
goto WriteLoop2;
WriteLoop1:
RS_Ctl|=0x40;
RS_Len=1;
RS_Cmd=1;
WriteLoop2:
break;
case RS_CTL_MetID:
if( !((KEY_PROG_IN & KEY_PROG_BIT)==0) )
goto LoopComExit;
MemCopy( SM.Cfg.MetID, &RS_Cmd, 6 );
RS_Len=0;
break;
case RS_CTL_Time:
if( !((KEY_PROG_IN & KEY_PROG_BIT)==0) )
{
unsigned char TMP1;
signed char TMP2;
if(SM.Cfg.MetStatus[0] & M_CHKCLK) goto LoopComExit;
Ptr=DM.RS.ComBuf[12];
if(SM.Clk.Hour[0]>Ptr)
{
TMP1=BCD2Byte(SM.Clk.Min[0])+60;
Ptr = BCD2Byte(DM.RS.ComBuf[11]);
}
if(SM.Clk.Hour[0]<Ptr)
{
TMP1=BCD2Byte(SM.Clk.Min[0]);
Ptr = BCD2Byte(DM.RS.ComBuf[11])+60;
}
if(SM.Clk.Hour[0]=Ptr)
{
TMP1=BCD2Byte(SM.Clk.Min[0]);
Ptr = BCD2Byte(DM.RS.ComBuf[11]);
}
TMP2=(signed char)TMP1-Ptr;
if( TMP2>5 || TMP2<-5 )
{
goto LoopComExit;
}
SM.Cfg.MetStatus[0] |= M_CHKCLK;
}
else
{
MemCopy( SM.Clk.Day, &RS_Cmd+3, 3 );
}
MemCopy( SM.Clk.Sec, &RS_Cmd, 3 );
SM.ClkChk=ChkSum( SM.Clk.Sec, sizeof(RTC) );
goto LoopComExit;
case RS_CTL_Pswd:
if( !((KEY_PROG_IN & KEY_PROG_BIT)==0) )
{
Buf=&DM.RS.ComBuf[RS_CmdPtr];
for(Ptr=0,Buf=&RS_Data; Ptr<=3; Ptr++,Buf++)
if( (*Buf)!=SM.Cfg.Pswd[0][Ptr]) goto LoopComExit;
}
Ptr=DM.RS.ComBuf[RS_CmdPtr+4];
if( Ptr>1 ) goto LoopComExit;
MemCopy( SM.Cfg.Pswd[Ptr], &DM.RS.ComBuf[RS_CmdPtr+4], 4 );
RS_Len=4;
break;
default:
goto LoopComExit;
}
SM.CfgChk=ChkSum( (unsigned char *)&SM.Cfg, sizeof(CFGGRP) );
RS_Ctl|=0x80;
if( RS_Len>30 ) goto LoopComExit;
for( Ptr=0,Buf=&RS_Cmd;Ptr<RS_Len;Ptr++,Buf++ ) *Buf+=0x33;
RS_CRC=ComCRC();
RS_End=0x16;
DM.RS.ComPtr=1;
SendStart();
_NOP();
return;
LoopComExit:
_NOP();
RXRst();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -