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

📄 ircomm.c

📁 一个电表的程序
💻 C
📖 第 1 页 / 共 3 页
字号:
/*===========================================================================
* Copyright (c) 2004,三星科技有限公司 
* All rights reserved.
* 
* 文件名称:IRCOMM.C
* 文件标识:
* 摘    要:DDS188
*          
* 
* 当前版本:V 1.0
* 作    者:叶孟军
* 修改内容:
* 开始日期:2005年7月25日


==============================================================================*/
#include	<machine.h>
#include 	<stdio.h>
#include    "iodefine.h"
#include 	"extern.h"
/******************************************************************************/
#define		Re_Te			(IO.PDR4.BIT.B0)				//控制RS485发送/接收
/*******************************************************************************/
void   BroChkEng_frost(void);

/**********************************************************
	        通讯缓冲区绕尾处理
	        说明:只要有头尾指针加操作的地方一定要进行绕尾处理
***********************************************************/
unsigned char *Bufferl_Tail_OP(unsigned char  *Temp)
{
  if(Temp > &BufferInOut_Comm[BufferInOutMax_Comm-1]) 
   {
      Temp -= BufferInOutMax_Comm;
    }
  return Temp;
}

/**********************************************************
	        通讯主流程及状态切换
	        与中断接口:void Set_RxState(void);  //发完后开收中断处理(注:可讨论是否在此处理)
	                    void Startup_Send(void); //启动发送处理
***********************************************************/
unsigned char Get_BuffData_Len(void);   //取缓冲区数据的长度          

void Protocel_Main_Comm(void)
{
	//命令续发处理
   while(NeedSign_Comm == 1)			//把读命令续发与发送统一处理,进来后先看是否在续发态
    {
	   if(Get_BuffData_Len() >= 34)		//缓冲区待发数据长度等于或超过34个字节,则退出
	    {
		   break;
         }
	   else								//缓冲区待发数据长度未超过34个字节,则继续填待发数据
	    {
		   DataHold_Comm_DLT645(); 		//续发态,向缓冲区继续塞数处理
         }
	}
	//收 态
   if((RxTxState_Comm == AtRxState_Comm) && (system_timer_in_13ms - TxRxTime_Comm) > 30)	//命令缓冲区从串口收到的命令并且解析完成,SIO 收发标志置为收  38 = 500ms/13.3ms
	{
	   if (BufferHead_Comm!=BufferTail_Comm)		//收发缓冲区头尾指针是否相等
       	{
           BufferHead_Comm = BufferTail_Comm;	//若不等令头尾指针相等	
           Set_RxState();						//开收接收中断
       	 }
      else
	    {
//		  IENR1.BYTE |= 0x01;							//开启红外接收中断
		  Sci_Define();
//		  Tx_Flg = 0x00;
//         CKSTPR2.BYTE &=0xfd;				//关闭红外调制信号
         }
	 }
	//(待)发 态
   if(RxTxState_Comm==AtTxState_Comm && (system_timer_in_13ms-TxRxTime_Comm)>90)			//2 = 2个char发时间/13.3ms*2
	{
	   if(BufferHead_Comm == BufferTail_Comm) 
		{	
           Set_RxState();      							//开收接收中断
		 }//发送完状态关闭发送标志位,
	   else
		{
		   
           TxRxTime_Comm= 0x00;
           system_timer_in_13ms = 0x00;
	   	   Startup_Send();     //启动发送处理	
		 }
	 }
	//既非收态也非发态
   if(RxTxState_Comm!=AtRxState_Comm && RxTxState_Comm!=AtTxState_Comm)//
	{
	   RxTxState_Comm = AtRxState_Comm;
       BufferHead_Comm = BufferTail_Comm;
       Set_RxState();      								//开收接收中断
	 }
 }
//取缓冲区数据的长度
unsigned char Get_BuffData_Len(void)
{
   unsigned char len;
   len = BufferTail_Comm - BufferHead_Comm;
   if(len > BufferInOutMax_Comm)			 //尾指针地址小于头指针地址
    {
	   len += BufferInOutMax_Comm;
     }
   return len;
 }				


void Set_RxState(void)
{
  unsigned char i;
  BufferHead_Comm = BufferInOut_Comm;			//外部UART1接收定义
  BufferTail_Comm = BufferInOut_Comm;
  for(i=0;i<BufferInOutMax_Comm;i++)
   {
     BufferInOut_Comm[i] = 0x00;
    }
  Re_Te = 1;									//RS485的控制位处接收状态
  //SCI3.SCR3.BYTE   = 0x50;			//接收中断使能
  Sci_Define();
  IENR1.BYTE |= 0x01;							//开启红外接收中断
  Rx_Command_Flg.BYTE = 0x00;
  RxTxState_Comm = AtRxState_Comm;				//处于接收状态		
  Tx_Flg = 0x00;
  CKSTPR2.BYTE &=0xfd;				//关闭红外调制信号
 }

void  Startup_Send(void)
{
   RxTxState_Comm = AtTxState_Comm;
   if(Tx_Txd_Comm_Flg == 0x33)					//表示解析成功的接收数据为红外接收而得,发送须为红外发送
    {
	   Tx_Flg = 0x68;
       TxData_state.BYTE = 0x01;					//红外发送字节初始状态
       TMRF.TCFL = 0x00;							//定时器FL计数器清零

     }
   else if(Tx_Txd_Comm_Flg == 0x55)					//表示解析成功的接收数据为RS485接收而得,发送须为RS485发送
    {
       Txd_Flg = 0x68;
       SCI3.SCR3.BYTE =0xa0;						//SCI处于发送状态
	   SCI3.TDR = 0xfe;
//	   SCI3.SSR.BYTE = 0x00;
//       SCI3.SCR3.BYTE =0xa0;						//SCI处于发送状态
     }  
 } 

/**********************************************************
	        通讯协议解析
	        说明:
***********************************************************/
void F_ProtocolResolve_Comm(void)
{
   unsigned char  *Temp1_Pointer,*Temp2_Pointer,i,j,len,cs;
   ErrByte_Comm.BYTE = 0x00;             					//清错误信息字
   if (RxTxState_Comm == AtTxState_Comm) 					//在发状态吗?
    {
	   return;
     }
   if(Get_BuffData_Len() < 12)		      					//**是否到最小解析长度 
    {
	   return;
     }
   Temp1_Pointer = BufferHead_Comm;
   if(*Temp1_Pointer == 0x68)             					//**第1个为68H吗
	{
	   Temp1_Pointer += 7;
	   Temp1_Pointer = Bufferl_Tail_OP(Temp1_Pointer);
	   if(*Temp1_Pointer == 0x68)         //**第7个为68H吗
	    {
	       Temp2_Pointer = RMtNo_Dtr;
	       j = 0;
	       Temp1_Pointer = BufferHead_Comm;
	       for(i=0; i<6; i++)             //广播地址判断
	        {
	           Temp1_Pointer += 1;
	           Temp1_Pointer = Bufferl_Tail_OP(Temp1_Pointer);
	           if(*Temp1_Pointer != 0x99)
	            {
			       break;
                  }   
	           j += 1;    
	         }
	       if(j != 6)
	        {	
	           j=0;
	           Temp1_Pointer = BufferHead_Comm;
	           for(i=0; i<6; i++)         //本机地址判断
	        	{
	               Temp1_Pointer += 1;
	               Temp1_Pointer = Bufferl_Tail_OP(Temp1_Pointer);
	           	   if((*Temp1_Pointer!=0xAA) && (*Temp1_Pointer!=*Temp2_Pointer))
	                {
				       break;
                     }
	               j++;
	               Temp2_Pointer += 1;        
	        	 }
	         }	
	       if (j == 6)		               //**广播或本机地址正确
	        {
	           Temp1_Pointer += 3;
	           Temp1_Pointer = Bufferl_Tail_OP(Temp1_Pointer);
	           if(Get_BuffData_Len() != (*Temp1_Pointer+12)) //**接收长度到吗
	            {
			       return;
                 }
	           len = *Temp1_Pointer;//数据域长度
	           Temp1_Pointer = BufferHead_Comm;
	           cs=0;
	           for(i=0;i<(len+10);i++)   //计算cs
	            {
	               cs += *Temp1_Pointer;
	               Temp1_Pointer++;
	               Temp1_Pointer = Bufferl_Tail_OP(Temp1_Pointer);    
	             }
	           if(cs == *Temp1_Pointer)   //**cs正确吗
	            {
	               Temp1_Pointer++;
	               Temp1_Pointer = Bufferl_Tail_OP(Temp1_Pointer);
	               if(*Temp1_Pointer == 0x16)   //**16H正确吗 
	                {
	                   BufferHead_Comm += 8;
	                   BufferHead_Comm = Bufferl_Tail_OP(BufferHead_Comm);
	                   CommandByte_Comm = *BufferHead_Comm;//控制码
	                   CommandDataLength_Comm = len;       //数据域长度
	                   BufferHead_Comm += 2;
	                   BufferHead_Comm = Bufferl_Tail_OP(BufferHead_Comm);
	                   CommandDataPointer_Comm = BufferHead_Comm;//数据域首址指针
	                   BufferHead_Comm = BufferTail_Comm;  //协议解析成功令头尾指针相等
	                   IrComm_Disp = 1;
                       Jump_OP_Comm();//协议解析成功转到执行跳转程序
	                   return;//解析正确退出      
	                 }   
	             }
	         }
	     }
	 }
   CommandDataPointer_Comm = 0;           //上述任一条件错误,数据帧丢掉一个字节
   BufferHead_Comm++;
   BufferHead_Comm = Bufferl_Tail_OP(BufferHead_Comm); 
 }
/**************************************************************/
void ClrDate_Comm(void)
{
   unsigned char i;
   Hello_Flg = 0x38;
   if ( !Progrm_Disp)      //**编程开关打在编程禁止
    {
	   return;   
	 }
   if((*CommandDataPointer_Comm == 0x48) && (*(++CommandDataPointer_Comm) == 0x49))	//系统复位
	{
	   CommandDataPointer_Comm++;
	   for(i=0;i<CommandDataLength_Comm;i++)   //取出数据域数据
    	{ 
	       Temp_WrtDt_Comm[i] = *CommandDataPointer_Comm-0x33; 
	       CommandDataPointer_Comm++;
	       CommandDataPointer_Comm = Bufferl_Tail_OP(CommandDataPointer_Comm);        
         } 
       if(Judge_BCD() == 1)                    //非法数据
    	{
           ErrByte_Comm.BYTE |= 0x01; 
           Abn_Answer();                          //异常应答处理子程序
    	   return;
    	 }
       if(Compare_sub_code() == 1)                //密码错
        {  
           ErrByte_Comm.BYTE |= 0x04; 
           Abn_Answer();                          //异常应答处理子程序
           return;
         }   
           
       WatchDog_Set();
       Reset_Data();
	   while(1)
	    {
	       NOP;
         }
     }
     
   else if ((*CommandDataPointer_Comm == 0x47) && (*(++CommandDataPointer_Comm) == 0x49))	//历史数据清零
   	{
   	   CommandDataPointer_Comm++;
       for(i=0;i<CommandDataLength_Comm;i++)   //取出数据域数据
      	{ 
	       Temp_WrtDt_Comm[i] = *CommandDataPointer_Comm-0x33; 
	       CommandDataPointer_Comm++;
	       CommandDataPointer_Comm = Bufferl_Tail_OP(CommandDataPointer_Comm);        
         } 
       if(Judge_BCD() == 1)                    //非法数据
     	{
           ErrByte_Comm.BYTE |= 0x01; 
           Abn_Answer();                          //异常应答处理子程序
           return;
         }
       if(Compare_sub_code() == 1)                //密码错
        {  
           ErrByte_Comm.BYTE |= 0x04;
           Abn_Answer();                          //异常应答处理子程序
           return;
         }   
       WatchDog_Set();
       EngerData_Clr();
	   while(1)
	    {
	       NOP;
         }
     }
 } 

/**********************************************************
	        通讯执行跳转程序
***********************************************************/
void Jump_OP_Comm(void)
{
   if (CommandDataPointer_Comm == 0)    
    {
       return;
     }
   switch (CommandByte_Comm)
    {
       case 0x01:
           ReadOrder_Comm();     //一、请求读数据处理;
    	   break;
       case 0x04:
    	   WriteOrder_Comm();    //二、主站向从站请求设置数据(或编程)处理;
    	   break;
       case 0x08:
    	   CheckTime_Comm();     //三、强制从站与主站时间同步,即广播校时处理;
    	   break;
       case 0x0a:
    	   WirteDevcNo_Comm();   //四、写设备地址,即设置某从站的地址码处理
    	   break;
       case 0x0f:
    	   AmendCode_Comm();     //五、写密码处理;
    	   break;
       case 0x13:
    	   ClrDate_Comm();       //七、内存数据复位,内存电量清零
    	   break;
       case 0x19:				 //电量冻结命令
	       BroChkEng_frost();	//广播冻结电量命令
       default:
    	   NeedSign_Comm = 0;
    	   CommandByte_Comm = 0;
//    	   Error_Trig=1;		//无此命令;显示Error
           Error_Flg = 0x38;
    	   break;
     }
   CommandDataPointer_Comm = 0; //通讯结束,清相关变量
   CommandByte_Comm = 0;
   CommandDataLength_Comm = 0;
   return;
 }

/**********************************************************
	        一、请求读数据处理
***********************************************************/
void ReadOrder_Comm(void)
{
   unsigned int  length,temp3;
   unsigned char  temp1,temp2,Pointer;
   unsigned char i,*p;		
   Hello_Flg = 0x38;						//通信协议解析成功;触发 Hello 显示
   temp1 = *CommandDataPointer_Comm - 0x33;//将数据域数据进行减0x33操作
   CommandDataPointer_Comm++;
   CommandDataPointer_Comm = Bufferl_Tail_OP(CommandDataPointer_Comm);
   temp2 = *CommandDataPointer_Comm - 0x33; //将数据域数据进行减0x33操作
   DI1DI0_Comm = ((unsigned int)temp2*256) + ((unsigned int)temp1); //**得到标识	
   CoutSign_Len = 0;		//number 默认为0
	
	
	if((DI1DI0_Comm <= 0x941f) && (DI1DI0_Comm >= 0x9410))	//上月正向有功
	{
		DI1DI0_Comm +=0x4f00;
	}
	
	if((DI1DI0_Comm <= 0x981f) && (DI1DI0_Comm >= 0x9810))	//上上月正向有功
	{
		DI1DI0_Comm +=0x4b10;
	}
	
	if((DI1DI0_Comm <= 0xe3cf) && (DI1DI0_Comm >= 0xe310))//对历史电量的标识进行修正
	{
		if(F_BlckRead_Eeprm(HstryEngy_Pter,&Pointer,1))//取出历史电量偏移量
		{
			RMtWd_Dtr[0] &= 0xfd;	//存储芯片无错
		}
		else
		{
			RMtWd_Dtr[0] |= 0x02;	//存储芯片出错
		}
		if((DI1DI0_Comm + (Pointer * 0x0010)) > 0xe3cf)
		{
			DI1DI0_Comm = DI1DI0_Comm + Pointer * 0x0010 - 0x00c0;
		}
		else
		{
			DI1DI0_Comm = DI1DI0_Comm + Pointer * 0x0010;
		}
	}
	
	
	if((DI1DI0_Comm <= 0xe219) && (DI1DI0_Comm >= 0xe210))//对电流反向事件标识进行修正
	{
		if(F_BlckRead_Eeprm(CrntRvrs_Pter,&Pointer,1))//取出电流反向事件偏移量
		{
			RMtWd_Dtr[0] &= 0xfd;	//存储芯片无错
		}
		else
		{
			RMtWd_Dtr[0] |= 0x02;	//存储芯片出错
		}
		if((DI1DI0_Comm + Pointer) > 0xe219)
		{
			DI1DI0_Comm = DI1DI0_Comm + Pointer - 0x0a;
		}
		else
		{
			DI1DI0_Comm = DI1DI0_Comm + Pointer;
		}
	}
	
	
	if((DI1DI0_Comm <= 0xe229) && (DI1DI0_Comm >= 0xe220))//对停电事件标识进行修正
	{
		if(F_BlckRead_Eeprm(PDRcd_Pter,&Pointer,1))//取出停电事件偏移量
		{
			RMtWd_Dtr[0] &= 0xfd;	//存储芯片无错
		}
		else
		{
			RMtWd_Dtr[0] |= 0x02;	//存储芯片出错
		}
		if((DI1DI0_Comm + Pointer) > 0xe229)
		{
			DI1DI0_Comm = DI1DI0_Comm + Pointer - 0x0a;
		}
		else
		{
			DI1DI0_Comm = DI1DI0_Comm + Pointer;
		}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -