com_prc.c

来自「楼宇对讲系统里用的文字信息接收。用可视对讲话机的TFT屏可看到从管理中心发过来的」· C语言 代码 · 共 493 行

C
493
字号
/***********************************************************/
/*							                               */
/*                CPU:AT89c55   20MHZ                      */
/*                Copyright  2004.09  Comelit              */
/*                AUTHOR:  LV_XIAO_LU                      */
/*                                                         */
/***********************************************************/

/********************************************************/
/*                                                      */
/*     通讯波特率:4800bps或9600bps                     */
/*     数据帧格式:                                     */
/*                起动位  1BIT                          */
/*                数据位  8BIT                          */
/*                停止位  1BIT                          */
/*      一帧通讯共39字节     暂用4800bps                */
/********************************************************/
#include "reg52.h"
#include "define.h"
#include "variable.h"
#include "typedef.h"
#include "function.h"
#include "intrins.h"

#define CD_STX 0x7f                   //PC-->终端话机通讯起始码
#define CD_STX_P 0x81                 //终端-->PC响应时通讯起始码

/*PC-->终端 群发信息时*/
#define CD_STX_SEND0_NEXT      0x20   //第一次起始群发信息,还有后续帧
#define CD_STX_SEND0_OVER      0x21   //第一次起始群发信息,无后续帧


#define CD_STX_SEND1_NEXT      0x40   //第二次起始群发信息,还有后续帧
#define CD_STX_SEND1_OVER      0x41   //第二次起始群发信息,无后续帧


#define CD_STX_SEND2_NEXT      0x60   //第三次起始群发信息,还有后续帧
#define CD_STX_SEND2_OVER      0x61   //第三次起始群发信息,无后续帧


/*PC--》终端 单发信息时*/
#define CD_SSEND_NEXT          0x80   //起始单发信息,还有后续帧
#define CD_SSEND_OVER          0x81   //起始单发信息,无后续帧

/*终端-->PC  */
#define CD_RECEIVE_OK          0xa0    // 终端发送回接收正常信息经PC机

#define CD_SET_ADDR            0xb0    //PC机向终端发送地址信息

/*串口工作方式:方式1*/
/* SMOD = 0 OSC:11.0592MHZ*/
//#define BPS9600  0xfd
//#define BPS4800  0xfa 

/* SMOD = 0 OSC:20MHZ*/
#define BPS9600  0xfd
#define BPS4800  0xf5 //0xf6 

#define MODE_0 0x00
#define MODE_1 0x40
#define MODE_2 0x80
#define MODE_3 0xc0 

#define T1_MOD2 0x20

#define FULL   (-1)
#define EMPTY  (-1)

#define  HRX_SIZE 120
#define  HTX_SIZE 7

#define		COM_ERROR		-1
#define		NORMAL_END		0
#define		NOW_COMMUNI		1

#define  ENABLE_TX 0
#define  DIS_TX 1
sbit DE = P1^5;     //active:  high


void Hsio_init(unsigned char baud_rate);
void Hsio_prc(void);
void Command_hd(void);
unsigned char xdata* Store_to_mesdata( register unsigned char xdata *src_p,unsigned char xdata *dst_p,register unsigned char num);
void Trm_hd(void);
void Err_prc(void);
unsigned char	Tget_data(void);
unsigned char xdata *Hrxst_adr( void );
unsigned char  Hget( void );
unsigned char xdata *Hrxrd_adr( void );
void Htx_st(void);
void Htx_prc(void);
/***********************************************/
/***********************************************/           
void Hsio_init(unsigned char baud_rate)
{

    hrx_str = hrx_buff;
	hrx_rd = hrx_buff;
	TMOD |= T1_MOD2 ;
	TH1 = baud_rate;
	TL1 = baud_rate;
	SCON = MODE_1 ;
	PCON = 0x00;
	TI=0;
    RI=0; 
	TR1 = 1 ;
	REN = 1;
    ES=1;
	DE = DIS_TX ;         //enable receive
    com_cnt = 3;

}


/***********************************************/
/***********************************************/  
void Hsio_prc(void) interrupt 4
{
   register unsigned char receive_data;
   register char xdata *next;

   if(TI == 1)   
   {
      TI = 0;
	  htx_cnt++;
	  if(htx_cnt<7)
	     SBUF = htx_buff[htx_cnt];
	  else
	  {
		 _nop_();
		 _nop_();
		 DE = DIS_TX ;
	  }
   }
   else if(RI == 1)          //接收产生的中断
   {
      
	  receive_data = SBUF;   //保存数据
	  RI = 0 ;
	  if((receive_step == 0)&&(receive_data == CD_STX))
     
      {
	      if( (int)(next = Hrxst_adr()) != FULL )
          {
	         *hrx_str = receive_data ;
	          hrx_str = next ;
	          receive_step++;
			  time_out = TM100MS;         //超时等待
	      }	
		  
      }	
	  else if((receive_step != 0)&&(time_out != 0))
//	  else if(receive_step != 0)
	  {
	     if( (int)(next = Hrxst_adr()) != FULL )
          {
	         *hrx_str = receive_data ;
	          hrx_str = next ;
	          receive_step++;
	      }	
		 		  		  
	  }
      else if((receive_step != 0)&&(time_out == 0))      //超时处理
	  {
	      while(receive_step-- != 0)  //退回到起先存贮的位置
		  {
		      hrx_str--;
			  if(hrx_str == (unsigned char xdata*)((unsigned int)hrx_buff - 1) )  //退到顶了,就返回到底部
		          hrx_str = (unsigned  char xdata*)hrx_buff + HRX_SIZE - 1 ;                    
	      }
		  if(receive_data == CD_STX)        //超时后接收到的第一个字节是CD_STX吗?
		  {
		     if( (int)(next = Hrxst_adr()) != FULL )
             {
	             *hrx_str = receive_data ;
	              hrx_str = next ;
	              receive_step++;
			      time_out = TM100MS;         //超时等待
	         }
	 	  }
	  }
			       
      if((receive_step == 39)&&(time_out != 0))
//	  if(receive_step == 39)
	  {
	      receive_step = 0;
		  one_frame_F = 1;
	  }
	  
   }
}
	 		            		  
/****************************************************************/
/****************************************************************/
	     



/* 由于一帧信息共有39个字节,所以当接收到所有39个字节时才进入该函数处理*/
/*对于4800BPS时,大概要81.25ms才需处理一次*/

/****************************************************************/
/****************************************************************/

void Command_hd(void)
{
//    unsigned char parity; 
//	unsigned char xdata *htx_p = htx_buff;

	switch(rx_prc_buff[1]&0xe0)         //先判高3位
	 {
	      case 0x20:                    //第一次群发
          case 0x40:                    //第二次群发
		  case 0x60:                    //第三次群发
		              if( 0 == send_all_suc_F )
		              {
					       if(((rx_prc_buff[1]&0x1e)>>1)== rx_screen_cnt) //只有发送屏数和接收屏数相
					       {                                  //等才能继续处理
						       send_all_suc_F = 1;
					           if(rx_screen_cnt == 0)          //第一屏,初始化信息数据指针
						            mes_data_p = mes_data;
                         
						        mes_data_p = Store_to_mesdata(&rx_prc_buff[2],mes_data_p,36);
						        rx_screen_cnt++;		  										  
					            if((rx_prc_buff[1]&0x01)== 1 )
					  	        {
				 	                received_mes_F = 1;
							  		rx_screen_cnt = 0;
					  		  		*mes_data_p = '\0';         //放信息结束标志
						 		}
						    }

					  }

					  if(0x60 == (rx_prc_buff[1]&0xe0))        //第三次重发时
					  {    
					       if(send_all_suc_F == 1)
						       send_all_suc_F = 0;
						   else 
						       rx_screen_cnt = 0;
					  }

					  break;						          						        
         
		                            
		  case 0x80:    //PC单发
		          if(((rx_prc_buff[1]&0x1e)>>1) == rx_screen_cnt)   //同样只有二者相等时才能继续处理
				  {
		            if((rx_prc_buff[3] == local_adr2)&&(rx_prc_buff[4] == local_adr3)
				        &&(rx_prc_buff[5] == local_adr4))          //如果接收地址符合本机地址
                       {
					        Htx_prc();                             //先发送接收正常信息给PC机
	                        if(rx_screen_cnt == 0)
						           mes_data_p = mes_data;
						    mes_data_p = Store_to_mesdata(&rx_prc_buff[6],mes_data_p,32);
							rx_screen_cnt++;	   
					        if((rx_prc_buff[1]&0x01)== 1 )
					  	    {
				 	           received_mes_F = 1;
							   rx_screen_cnt = 0;
					  		   *mes_data_p = '\0';
						    }
                       }
				  }
				  else if(((rx_prc_buff[1]&0x1e)>>1) == (rx_screen_cnt-1) ) //接收正常,但可能是我的确认信息对方没收到而重发
				  {
				     if((rx_prc_buff[3] == local_adr2)&&(rx_prc_buff[4] == local_adr3)
				        &&(rx_prc_buff[5] == local_adr4))      //如果接收地址符合本机地址
				         
                         Htx_prc();
				  }
				  else 
				       rx_screen_cnt = 0 ;
				       

				  break;
	   case 0xc0:                              //PC机向话机发送地址
	               if(work_F == 1)             //只有处于设置本机地址状态才能继续处理
				   {
				        local_adr1 = rx_prc_buff[2];
						local_adr2 = rx_prc_buff[3];
						local_adr3 = rx_prc_buff[4];
						local_adr4 = rx_prc_buff[5];
						Htx_prc();
//					    work_F = 0;
						//以下函数用于保存刚才收到的地址
						Write_sector((unsigned char xdata*)(0x1000),(unsigned char xdata*)0x00);
				   }
				   
				   break;				       
	   default:
	              break;
	}
 
}

/*********************************************************************/
/* 功能:将收到的信息贮存到mes_data[]中                               */
/*num 表示要存贮多少个字节,*src_p表示源信息的地址,*dst_p表示目的地址*/
/*********************************************************************/ 

unsigned char xdata* Store_to_mesdata( register unsigned char xdata *src_p, register unsigned char xdata *dst_p,unsigned char num)
 {
//    while((num--)&&(dst_p <= (&mes_data[0]+510)))
  while(num--)
	{
	   *dst_p = *src_p ;
	   dst_p++;
	   src_p++;
	}
	return(dst_p);
 }
     
/****************************************************************/
/*          10ms执行一次                                        */            
/****************************************************************/  
void	Trm_hd(void)
{
	unsigned char  c;
	if((COMERR_F == 0)&&(one_frame_F == 1))   
	{
	    one_frame_F = 0 ;
		c = Tget_data();							
		if(c == NORMAL_END)                         /*NORMAL_END define 0*/
		{
			Command_hd();			
		}
	}
	if(COMERR_F == 1)                              /* if communication is err */
	{                
		Err_prc();
		COMERR_F = 0;
	}

}              
/***********************************************************************/
/* rx_screen_cnt 表示现在接收到的是信息中的第几屏,它要和信息发送过来  
   的屏数相比较,只有一条信息的每帧全部相等时才能把信息存贮            */                                                       
/***********************************************************************/


void Err_prc(void)
{
   rx_screen_cnt = 0;              //由于出错,所以重新将接收屏数清0
   mes_data_p = mes_data ;        //重新指向mes_data的起始位置
}
/***********************************************************************/
/***********************************************************************/

unsigned char  Tget_data(void)
{
         
	register unsigned char parity,rx_data;
	register unsigned char	i;
	while(((rx_data = Hget()) != -1 ) && ( rx_byte_cnt < 39 ))
	{
		if((rx_byte_cnt == 0) && (rx_data != CD_STX))   
		{
		    continue ;
		}
		else
		{			                                      
				if( rx_byte_cnt == 0)               
				{                                  
					if(rx_data == CD_STX )
					{
						rx_prc_buff[0] = CD_STX;
						rx_byte_cnt++;
					}
				}
				else
				{
				 	rx_prc_buff[rx_byte_cnt] = rx_data;
					rx_byte_cnt++;
				}
		}
	}

	if( rx_byte_cnt == 39)
	{
		rx_byte_cnt = 0;
		parity = 0xff;
		for(i = 0 ; i < 38 ; i++)
		{
			parity ^= rx_prc_buff[i];
		}
		if(parity == rx_prc_buff[38])
		{
			com_cnt = 3          ;		//有效的通信次数为3次
			return((int)NORMAL_END);    //define NORMAL_END 0
		}
		else
		    com_cnt--;		
	}
	if(com_cnt == 0)   
	{					
		rx_byte_cnt = 0;
		COMERR_F = 1 ;
		return((int)COM_ERROR);       //define COM_ERROR -1
	}
	return((int)NOW_COMMUNI);    
}

/*********************************************/
/*********************************************/
unsigned char xdata	*Hrxst_adr( void )
{
    register unsigned char  xdata *next ;
	next = hrx_str + 1 ;
//	if((unsigned int)next == ((unsigned int)&hrx_buff[0] + HRX_SIZE) )
	if(next == (unsigned char xdata*)((unsigned int)hrx_buff + HRX_SIZE) )
		next = (unsigned  char xdata*)hrx_buff ;                    
	if( next == hrx_rd )
		return( (unsigned char xdata*)FULL );
	else
		return( next ) ;
}


/*********************************************/
/*********************************************/
unsigned char  Hget( void )
{

	register unsigned char xdata *next ;
	register unsigned char rx_data ;

	if( (int)(next = Hrxrd_adr()) != EMPTY )
	{
		EA = 0 ;
        rx_data = *hrx_rd;
		hrx_rd = next ;
		EA = 1 ;	
		return( rx_data ) ;
	}
    else
	    return( (char)EMPTY ) ;
}

/*********************************************/
/*********************************************/	

unsigned char xdata *Hrxrd_adr( void )
{
    ES = 0;
	if( hrx_rd == hrx_str )
	{
	   ES = 1;
	   return( (unsigned char xdata *)EMPTY );
	}
	
	if( (unsigned int)hrx_rd == (unsigned int)((unsigned int)&hrx_buff[0] + HRX_SIZE - 1) )
	{
	   ES = 1;
	  return( (unsigned char xdata *)hrx_buff ) ;
	 }
	else
	{
	    ES = 1;
		return(hrx_rd + 1) ;
	}
}
  

/*********************************************/
/*********************************************/	

void Htx_st(void)
{
   DE = ENABLE_TX;
   _nop_();
   _nop_();
   htx_cnt=0;
   TI = 0;
   SBUF = htx_buff[0];    //启动发送
}

/*********************************************/
/*********************************************/	
void Htx_prc(void)
{
    register unsigned char xdata *htx_p = htx_buff;
    *htx_p = CD_STX_P;
   	*(htx_p+1)= CD_RECEIVE_OK ;        //功能特征码
	*(htx_p+2) = local_adr1;
	*(htx_p+3) = local_adr2;
    *(htx_p+4) = local_adr3;
	*(htx_p+5) = local_adr4;
	*(htx_p+6) = CD_STX_P^CD_RECEIVE_OK^local_adr1^local_adr2^local_adr3^local_adr4;
	Htx_st();
}

⌨️ 快捷键说明

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