#51单片机# UART串口通信的基本应用、模块介绍和串口程序

UART串口通信的基本应用

通信的三种基本类型:

单工通信:值允许一方向另一方传送星系,另一方不能回传信息。例:电视遥控器、收音机广播

半双工通信:数据可在双方之间相互传播,但同一时刻只能一方传给另一方。例:对讲机

全双工通信:发送数据的同时也可接收数据,两者同步进行。例:电话

UART模块介绍

通常情况下,我们关心的是通信的结果而非过程。51单片机内部存在UART模块,可自动接收数据,接收完毕,会发出通知信号。要使用这个模块,需要配置对应的具有特殊功能的寄存器。

51单片机的UART串口结构由串行口控制寄存器SCON、发送和接收电路三部分构成。

先来了解串口控制寄存器SCON

SCON——串行控制寄存器的位分配(地址0X98、可位寻址)

76543210
符号SM0SM1SM2RENTB8RB8TIRI
复位值00000000

SCON——串行控制寄存器的位描述

符号描述
7SM0SM0和SM1两位共同决定了串口通信的模式0~模式3共4种模式。最常用的是模式1,即SM0=0,SM1=1。下面重点讲模式1,其他模式从略。
6SM1SM0和SM1两位共同决定了串口通信的模式0~模式3共4种模式。最常用的是模式1,即SM0=0,SM1=1。下面重点讲模式1,其他模式从略。
5SM2多机通信控制位(极少用),模式1直接清零。
4REN使能串口接收。由软件置位使能接收,软件清零则禁止接收。
3TB8模式2和3中要发送的第9位数据(很少用)。
2RB8模式2和3中要接收的第9位数据(很少用),模式1用来接收停止位。
1TI发送中断标志位,当发送电路发送到停止位的中间位置时,TI由硬件置1,必须通过软件清零。
0RI接收中断标志位,当接收电路接收到停止位的中间位置时,RI由硬件置1,必须通过软件清零。

对于串口的四种模式,模式1是最常用的,就是前面提到的1位起始位,8位数据位和1位停止位。 下面讲详细介绍模式1的工作细节和使用方法(其他3种模式与模式1大同小异,要用的时候自行查阅资料既可)。

在硬件模块中,有一个专门的波特率发生器用来控制发送和接收数据的速度。对于STC89C52单片机来说,这个波特率只能由定时器T1或定时器T2产生。这与模拟的通信概念完全不同。默认使用定时器T1(定时器T2需要额外配置的寄存器)。

下面主要就使用T1作为波特率发生器来讲解,方式1下的波特率发生器必须使用T1的模式2,也就是自动重装载模式。

定时器的重载值计算公式为:TH1 = TL1 = 256-晶振值/12/2/16/波特率

这里介绍一个与波特率有关的另一个计算器:电源管理寄存器PCON,他的最高位可以把波特率提高一倍,也就是如果写PCON |= 0X80以后,计算公式就成了:TH1 = TL1 = 256-晶振值/12/16/波特率

公式中数字的含义解释如下:
256——8位定时器的溢出值,1TL1的溢出值。
晶振值——在开发板上是11059200
12——1个机器周期等于12个时钟周期
16——将一位信号采集16次(IO口模拟串口通信接收数据时采集的是这位数据的中间位置,而实际串口模块比模拟的要复杂和精确一些。它采取的方式是把一位信号采集16次,其中7,8,9次取出来,如果这三次中有两次是高电平,就认为这个数据是1,如果有两次是低电平,就认为这个数据是0,这样即使是受到干扰导致数据读错,仍可保证最终数据的正确性)

了解了串口采集模式,这里可以思考一个问题。“晶振值/12/2/16/波特率”计算出的值有没有可能是小数?把这里理解了也就解释了晶振为何使用11059200。 因为11059200可以被常见的波特率整除。

串口通信的发送和接收电路在物理上有两个名字相同的SBUF寄存器,它们的地址相同都是0X99。 这两个寄存器一个用来发送缓冲,一个用来接收缓冲,实现了UART的全双工通信,互相不干扰。操作SBUF,单片机会自动判断并决定选择接收SBUF还是发送SBUF。

UART串口程序

一般情况下,串口通信程序的编写步骤如下:

1)配置串口为模式1

2)配置定时器T1为模式2(自动重装模式)

3)根据波特率计算TH1和TL1的初值,如果有需要可以使用PCON进行波特率加倍。

4)打开定时器控制寄存器TR1,让定时器跑起来。

注意:使用T1时,即在使用T1做波特率发生器,千万不能再使能T1中断。

以下是一段演示代码

 #include <reg52.h>

 void ConfigUART(unsigned int baud);//串口配置函数,baud——通信波特率

 void main()
 {
 	ConfigUART(9600);	 //配置波特率为9600

	while(1)
	{
		while(!RI); 	//等待接收完成
		RI = 0;			//清零接收中断标志
		SBUF = SBUF + 1;//接收到的数据+1后,发送回去
		while(!TI);		//等待发送完成
		TI = 0;			//清零发送中断标志位
	}
 }


 void ConfigUART(unsigned int baud)
 {
 	SCON = 0X50;						//配置串口为模式1
	TMOD &= 0X0F;						//清零T1的控制位
	TMOD |= 0X20;						//配置T1为模式2
	TH1 = 256 - (11059200/12/32)/baud;	//计算T1重载值
	TL1 = TH1;							//初值等于重载值
	ES = 0;								//禁止T1中断
	TR1 = 1;							//启动T1
 }

注意:实际工程开发中,并不会这样编写这段代码,因为这段代码在主循环里等待接收中断标志位和发送中断标志位,占据了大量程序内存。实际使用串口时常用到串口中断。

以下是串口中断的演示代码

 #include <reg52.h>

 void ConfigUART(unsigned int baud);//串口配置函数,baud——通信波特率

 void main()
 {
 	EA = 1;				//使能总中断
 	ConfigUART(9600);   //配置波特率为9600
	while(1);
}


 void ConfigUART(unsigned int baud)
 {
 	SCON = 0X50;						//配置串口为模式1
	TMOD &= 0X0F;						//清零T1的控制位
	TMOD |= 0X20;						//配置T1为模式2
	TH1 = 256 - (11059200/12/32)/baud;	//计算T1重载值
	TL1 = TH1;							//初值等于重载值
	ET1 = 1;							//禁止T1中断
	ES = 1;								//使能串口中断
	TR1 = 1;							//启动T1
 }

 //UART中断服务函数
 void InterruptUART() interrupt 4
 {
 	if(RI)				   				//接收到字节
	{
		RI = 0;			  				//手动清零接收中断标志
		SBUF = SBUF + 1;   				//接收到的数据+1后发回,左边是发送SBUF,右边是接收SBUF
	}
	if(TI)				  				//字节发送完毕
	{
		TI = 0;			   				//手动清零发送中断标志位
	}
 }
  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值