【实例73】单片机间双机通信
#include
#define uchar unsigned char
#define uint unsigned int
uchar buf[16];
uchar chksum;
/*校验和*/
(1)串口初始化子程序void init ()
void init(void)
{
TMOD = 0x20;
TH1 = 0xFD;
/*设定波特率*/
TL1 = 0xFD;
PCON = 0X00;
SCON = 0X50;
/*串行口工作在方式1,允许接收*/
}
(2)甲机发送子程序void send ()
void send( void )
{
uchar i;
do
{
SBUF = 0XAA;
/*发送联络信号 "0xAA" */
while( TI==0 );
/*等待发送结束*/
TI = 0;
while(RI ==0 );
/*等待乙响应*/
RI = 0;
} while( ( SBUF^0XDD)!=0); /*乙未准备好,继续联络*/
do
{
chksum = 0;
for(i=0; i<16; i++)
{
SBUF = buf[i];
chksum += buf[i];
/*求校验和*/
while( TI == 0);
TI = 0;
}
SBUF = chksum;
/*发送校验和*/
while( TI == 0 );
TI = 0;
while( RI == 0 );
/*等待乙响应*/
RI = 0;
} while(SBUF!=0X00);
/*出错则出重发*/
}
(3)乙机接收程序void recv()
void recv( void )
{
uchar i;
while(1)
{
while(RI==0);
/* 等待接收数据 */
RI = 0;
if (SBUF^0XAA!=0)
/* 如果收到的不是0xAA */
{
SBUF = 0XFF;
while( TI == 0 );
TI=0;
}
else
/*收到的是0xAA*/
{
break;
}
}
while(1)
{
chksum = 0;
for(i=0; i<16; i++)
{
while(RI==0);
RI = 0;
buf[i] = SBUF;
/*接受一个数据*/
chksum += buf[i];
/*计算校验和*/
}
while( RI==0);
/*接收校验和*/
RI = 0;
if( (SBUF^chksum) == 0 )
/*比较校验和*/
{
SBUF = 0X00;
/*校验和相同则发0x00 */
while(TI==0);
TI =0;
break;
}
else
{
SBUF = 0XFF;
/*出错则发0xFF,重新接收*/
while( TI == 0);
TI = 0;
}
}
}
【实例74】单片机间多机通信方法之一
主机的相关程序如下:
#include
#include
#define BUF_MAX_LEN 3
#define ADDR_ACK 0x1A
#define DATA_ACK 0x2A
unsigned char send_buf[BUF_MAX_LEN];
/* 发送数据缓冲 */
void serial_init( void );
/* 串口初始化 */
void send_addrframe( unsigned char addr );
/* 发送地址帧 */
void send_data_frame( void);
/* 发送数据帧 */
主函数main()程序代码如下:
void main( void )
{
unsigned char recv_tmp=0;
send_buf[0]=1;
/* 发送数据缓冲,这里以1,2,4为例说明 */
send_buf[1]=2;
send_buf[2]=3;
serial_init();
while( recv_tmp!= ADDR_ACK )
{
send_addrframe( 0x05 );
/*发送从机地址client_addr*/
RI = 0;
while(!RI);
/*接收从机发送的地址确认*/
RI = 0;
recv_tmp = SBUF;
}
while( recv_tmp != DATA_ACK )
{
send_data_frame();
RI =0;
while(!RI);
RI = 0;
recv_tmp = SBUF;
}
/*其他程序等 */
}
(1)串行口初始化程序serial_init()
void serial_init( void )
{
TMOD= 0x20 ;
TH1
= 0xFD ;
TL1
= 0xFD ;
EA = 0;
ET0
= 0;
ES
= 0;
SCON= 0xD0 ;
PCON= 0x00 ;
TR1 =1;
}
(2)发送地址帧函数send_addrframe()
void send_addrframe( unsigned char addr )
{
TB8 = 1;
/*址帧 标志*/
SBUF= addr;
while( !TI );
/*待数据发送完成*/
TI = 0;
TB8 = 0;
}
(3)发送数据帧函数send_addr_frame()
void send_data_frame( void )
{
unsigned char i;
unsigned char check_sum=0;
for( i=0;i
#include
/*伪定义*/
#define BUF_MAX_LEN 10
/*缓冲区的最大长度*/
#define ADDR_ACK 0x1A
#define DATA_ACK 0x2A
#define DATA_ERR 0x3A
unsigned char recv_buf[BUF_MAX_LEN+1];
/*函数声明*/
unsigned char recv_data_frame( void );
/*接收数据帧*/
void send_ack( unsigned char ack );
/*发送应答信息*/
void recv_addrframe( void );
/*接收地址帧*/
void serial_init( void );
/*串口初始化*/
主程序中serial_init()函数初始化完毕串行口后,等待主机发送的地址字节,若接收到与本机相同的地址字节,发送地址收到应答,然后再接收数据字节,接收完毕后对数据字节进行校验,校验正确则向主机发送数据正确数据,否则发送数据错误数据。程序代码如下:
void main( void )
{
unsigned char recv_tmp=0;
serial_init();
while( 1 )
{
recv_addrframe();
/*接收主机发送的地址帧*/
send_ack( ADDR_ACK );
/*发送地址收到应答*/
if( recv_data_frame() == DATA_ACK )
{
send_ack( DATA_ACK );
}
else if (recv_data_frame == DATA_ERR )
{
send_ack( DATA_ERR );
}
}
}
(1)接收地址帧函数recv_data_frame()
unsigned char recv_data_frame( void )
{
unsigned char i;
unsigned char check_sum=0;
SM2= 0;
for( i=0;i
#include
#define uchar unsigned char
#define uint unsigned int
#define CHK_OK 0X01
#define CHK_ERR 0XFF
#define CLIENT 0X0F
#define HOST 0XF0
#define SYN 0XAA
#define FIN 0XDD
#define RECV_DATA_STAT 0x01
#define RECV_HDR_STAT 0X02
#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_buf[ recv_counter]=recv_tmp;
recv_counter ++;
if( recv_counter == recv_buf[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) )
{
return CHK_ERR;
}
chksum2 = 0;
for( i=0; i>8 );
/* 表号高8位 */
send_buf[2] = (unsigned char )(meter_id&0xff);
/* 表号低8位 */
send_buf[3] = (unsigned char )(room_id >>8 );
/* 房间号高8位 */
send_buf[4] = (unsigned char )(room_id &0xff);
/* 房间号低8位 */
send_buf[5] = cmd;
/* 命令字节 */
send_buf[6] = data_len;
/* 数据域的长度 */
for( i=0;i
本文档为【51单片机应用开发范例代码10】,请使用软件OFFICE或WPS软件打开。作品中的文字与图均可以修改和编辑,
图片更改请在作品中右键图片并更换,文字修改请直接点击文字进行修改,也可以新增和删除文档中的内容。
该文档来自用户分享,如有侵权行为请发邮件ishare@vip.sina.com联系网站客服,我们会及时删除。
[版权声明] 本站所有资料为用户分享产生,若发现您的权利被侵害,请联系客服邮件isharekefu@iask.cn,我们尽快处理。
本作品所展示的图片、画像、字体、音乐的版权可能需版权方额外授权,请谨慎使用。
网站提供的党政主题相关内容(国旗、国徽、党徽..)目的在于配合国家政策宣传,仅限个人学习分享使用,禁止用于任何广告和商用目的。