⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 comm.c

📁 MSP430F413单相电表DEMO(编译器IAR 3.42A)
💻 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 + -