请大家解释一下这是一个主机发往从机地址0x10发送数据0x12 ,0x34功能字节为0X55,
数据帧中以8位为数据单位,采用16进制; 功能:数据字节的功能,若无数据字节,功能字节就为0X00,采用压缩BCD数据格式?功能码采用压缩BCD数据格式?
帧长度:数据字节的长度
例如主机向地址为0X10的从机发送数据0X12,0X34,功能字节为0X55,则发送的一帧数据如图
#include<string.h>
#include<reg52.h>
#define uchar unsigned char
#define uint unsigned int
#define CHK_OK 0X01//为什么是0x01
#define CHK_ERR 0XFF
#define CLIENT 0X0F
#define HOST 0XF0
#define SYN 0XAA
#define FIN 0XDD
#define RECV_DATA_STAT 0x01//为什么是0x01
#define RECV_HDR_STAT 0X02//为什么是02
#define MAX_RECV_NUM 50//??????????
#define MAX_SEND_NUM 50//????????
/*相关全局变量定义*/
uchar data client_addr;
uchar data recv_tmp;
uchar data recv_status;
uchar data recv_counter;
uchar idata recv_buf[ MAX_RECV_NUM ];
uchar idata send_buf[ MAX_SEND_NUM ];
bit recv_frame_ok;
uchar calc_chksum( void );
void seri_init( void );
void seri_send( uchar *p,uchar data_len);
void get_client_addr( void );
(1)串行中断服务子程序void seri_isr()
void seri_isr( void ) interrupt 4 using 1
{
if(1==TI)
{
TI=0;
}
if(0==RI)
{
return;
}
recv_tmp = SBUF;
switch( recv_status )
{
case RECV_DATA_STAT://为什么要比较RECV_DATA_STAT
{
recv_buf[ recv_counter]=recv_tmp;
recv_counter ++;
if( recv_counter == recv_buf[4] )//为什么是4
{
recv_status = RECV_HDR_STAT;
}
else
{
return;
}
break;
}
case RECV_HDR_STAT:
{
if( recv_tmp == SYN )
/* 如果是开始字节 */
{
recv_buf[ recv_counter ] = recv_tmp;
recv_counter ++;
if( 6 == recv_counter )
{
recv_status = RECV_DATA_STAT;
}
}
else if( recv_tmp == FIN )
/* 如果是结束字节 */
{
recv_buf[ recv_counter ] = recv_tmp;
recv_counter ++;
if( ( CHK_OK == calc_chksum() ) &&
( recv_buf[5] == client_addr ) )
{
recv_frame_ok = 1;
}
else
{
recv_counter = 0;
recv_status = RECV_HDR_STAT;
}
}
else
{
recv_counter = 0;
recv_status = RECV_HDR_STAT;
}
break;
}
default:
{
recv_status = RECV_HDR_STAT;
memset(recv_buf,0x00,MAX_RECV_NUM);
recv_counter = 0;
break;
}
}
}
(2)主程序void main()
void main( void )
{
seri_init();
get_client_addr();
seri_send("test",4);
if( 1 == recv_frame_ok )
/* 接收到数据 */
{
/* 对接收到数据进行处理 */
}
/* 其他代码等 */
}
(3)计算校验和子程序uchar calc_chksum()
uchar calc_chksum( void )
{
uchar i;
uchar chksum2;
if( ( recv_counter == 0 )||
( recv_buf[4] != recv_counter) )//recv_buf[4]??
{
return CHK_ERR;
}
chksum2 = 0;
for( i=0; i<recv_counter; i++)
{
if( i!= 3)
/* 跳过校验和部分 */
{
chksum2 += recv_buf;
}
}
if( chksum2 == recv_buf[3] )
{
return CHK_OK;
}
else
{
return CHK_ERR;
}
}
(4) 串行口发送子程序void seri_send()
void seri_send( uchar *p,uchar data_len )
{
uchar i;
uchar chksum=0;
/* 准备数据帧头 */
send_buf[0] = SYN;
send_buf[1] = CLIENT;
send_buf[2] = 0x00;
/*功能字节假设为0x55 */
send_buf[3] = 0x00;//已经假设为55为什么要存0x00?
send_buf[4] = data_len+7;
send_buf[5] = client_addr;
send_buf[ data_len ] = FIN;
for( i=0; i< data_len; i++)
{
send_buf[i+6] = *p;
p++;
}
for( i=0;i<(data_len + 7); i++)
{
chksum +=send_buf;
}
send_buf[3] = chksum;
/* 数据帧准备完毕,下一步是发送 */
for( i=0;i<(data_len + 7); i++)
{
SBUF = send_buf;
while( TI == 0 );
TI = 0;
}
}
(5) 串口初始化子程序void seri_init()
void seri_init( void )
{
recv_status = RECV_HDR_STAT;
recv_counter = 0;
recv_frame_ok = 0;
memset( recv_buf,0x00,MAX_RECV_NUM);
memset( send_buf,0x00,MAX_SEND_NUM);
TMOD = 0X20;
TH1 = 0XFD;
/* 波特率为9600bit/s */
TL1 = 0XFD;
EA = 1;
ET0 = 0;
ES = 1;
SCON = 0X50;
/* 串行口工作在方式1,允许接收 */
PCON = 0X00;
TR1 = 1;
}
(6) 读取数据子程序void get_client_addr()
void get_client_addr( void )
{
client_addr = P1;
}
|