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 + -
显示快捷键?