单片机 串行通信练习

单片机 串行通信练习

一、简述

    简单的双单片机间串行通信演示。

    例子中有甲乙两片单片机系统构成一对单片机系统,每片单片机系统有2位数码管用来显示收到的数据,两片单片机系统之间进行串行通信。

甲方发送1,乙方发送2,甲方发送3,乙方发送4……每次加1,直至99。

文件打包:链接: https://pan.baidu.com/s/1er2xDqgrecxuGYeBG-Q0ug 密码: karu

二、效果


三、工程文件

1、Keil文件


2、仿真电路图


四、源文件

SBUF.c文件

#include<reg51.h>
#define uint unsigned int
#define uchar unsigned char
uchar led[10]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f};
uchar num;
//定义引脚变量
sbit P2_0=P2^0;
sbit P2_1=P2^1;
sbit P1_0=P1^0;
/**********************************************************/
//函数名:delay(uint x)
//功能:延时程序	
//调用函数:
//输入参数:x
//输出参数:
//说明:程序的延时时间为x乘以0.5ms
/**********************************************************/
void delay(uchar x)
{
	uchar y,z;
	for(y=x;y>0;y--)
		for(z=250;z>0;z--);//该步运行时间约为0.5ms
}
/**********************************************************/
//函数名:display(uchar num)
//功能:2位数码管显示
//调用函数:delay(uint x)
//输入参数:num
//输出参数:
//说明:P0口做数码管段选,P2口做位选
/**********************************************************/
void display(uchar num)
{	
	P2_0=0;//开十位位选口
	P0=~led[num/10];//P0口输入段选数据
	delay(5);//延时2.5sm
	P2_0=1;//关十位位选口

	P2_1=0;//开个位位选口
	P0=~led[num%10];//P0口输入段选数据
	delay(5);//延时2.5sm
	P2_1=1;//关个位位选口
}
/**********************************************************/
//函数名:TAKE_SBUF(uchar dat)
//功能:串数据发送程序
//调用函数:无
//输入参数:dat
//输出参数:
//说明:dat为要发送的八位串口通讯数据
/**********************************************************/
void TAKE_SBUF(uchar dat)
{
	ES=0;//关串口中断,当一个字节数据被发送成功后,会自动置位TI标志位,如果上一次发送成功之后,
	//会标志为已发送,所以在要发送数据之前先关闭串口中断,再装载要发送的数据,否则可能你还没装载号新的数据,对方就再次请求,然后拿到的还是上一次数据
	SBUF=dat;//将要发送的数据存入SBUF寄存器中,对方会在某一个时刻获取。

	while(~TI);//等待发送结束,验证数据是否发送成功,如果还没发送成功,则CPU进行空循环等待硬件把数据发送完毕。			  
	TI=0;//发送中断标志位置0,清零发送中断标志位,因为数据发送成功后,该标志位会被自动置1,把它清零以免影响误中断。
	ES=1;//开串口中断 ,打开刚才被关闭的串行口中断,等待接收数据。
}
void main()
{
	SCON=0X90;//0x10010000,设置串口通讯为方式2,11位异步串行通信
	EA=1;//开总中断
	ES=1;//开串口中断
	P2=0xff;//数码管位选口初始化 ,全部灭灯
	num=0;//显示值初始化
	if(P1_0==0)
	TAKE_SBUF(num+1);//串口发送数据(num+1)
	while(1)
	{
			
	}//主程序不做任何事情,通过串口中断,进入控制数码管的处理程序
}
/**********************************************************/
//函数名:int0rupt() interrupt 4	
//功能:串口中断响应程序
//调用函数:display(uchar num)
//输入参数:
//输出参数:
//说明:显示接收到的串口数据,将数据加一后通过串口发送
/**********************************************************/
void int0rupt() interrupt 4
{						 
   	uchar i;
	num=SBUF;//从串行口寄存器SBUF中取得数据
	if(num>99)
	{
		num=0;//限定num值范围0到99
	}
	for(i=200;i>0;i--) //因为单片机执行速度很快,所以用一个for循环语句执行多遍目的就是为了让我们看清楚数据这里我们选择了100次
		display(num);//显示收到的串口数据,显示在数码管
	TAKE_SBUF(num+1);//将num值加一后通过串口发送
	RI=0;//接收中断标志位置0 ,	清零接收中断标志位,就是恢复没有中断的状态。
}

五、总结

1、串行通信

        51单片机内部有一个可编程的全双工串行通信电路。通过引脚RXD(P3.0串行数据接收端)和引脚TXD(P3.1串行数据发送端)与外界通信。

        内部通信电路中有一个SBUF串行口缓冲寄存器,它既是发送寄存器也是接收寄存器。发送与接收数据就是通过该寄存器实现的。通信编程的关键是对寄存器的一些设置,在编程中需要用到有几个寄存器。

       1)数据缓冲寄存器SBUF

            当需要发送数据时,只要把被发送的数据写入该寄存器,当需要接收数据时,只需从此寄存器读取数据。

       2)串行口控制与状态寄存器SCON


51单片机全双工串行口具有4种工作方式。

方式0:为移位寄存器输入/输出方式
方式1:为波特率由T1控制的10位异步通信方式
方式2:为固定波特率的11位异步通信方式
方式3:为波特率由T1控制的11位异步通信方式

总结:方式0通常用于扩展I/O,实现串行与并行的相互转换。方式1用于单片机的双机通信中用得比较常见;方式2和方式3由于多了第9位可以实现多机通信,经常在主从单片机系统中得到应用。

2、波特率

        在串行通信中,收发双方的数据传输速度要有一定约定,不然双方速度不一样就会导致收到乱码的数据。

    方式0的波特率是固定的主振频率的1/12。
方式2的波特率由PCON中的选择位SMOD来决定,其计算公式:
波特率=(2SMOD/64)*fosc

方式1和方式3的波特率也受PCON中的选择位SMOD影响,其计算公式:



猜你喜欢

转载自blog.csdn.net/nanfeibuyi/article/details/80630622