前言
在我们配置51系列单片机的串口时,涉及到定时器寄存器、中断寄存器、串口寄存器等多个寄存器,且在厂家的芯片手册中处于分散的位置,查阅不便,因此本文将51单片机中UART-串口通讯的配置过程进行了归纳汇总,方便学习和配置。
一、配置流程
在51单片机上,集成了串口通讯的功能,我们通过配置相关寄存器的参数就可以使用串口通讯功能。具体的配置流程如下:
第一步:配置定时器1
通过选定的波特率 、晶振频率 、单片机的机器周期 等信息计算定时器的初值;
TMOD寄存器选择定时器的工作模式---一般使用8位自动重装模式;
将计算好的初值装入到TH1和TL1寄存器中;
启动定时器1
第二步:配置中断
打开总中断允许位 EA
打开串口中断 ES
第三步:配置串口寄存器
配置SCON寄存器,选择串口的工作模式---通常采用模式1
配置PCON寄存器,选择是否倍频--这里的配置会影响到波特率的计算
二、定时器寄存器的配置
(1)波特率的计算
51单片机的模式1和模式3是可以通过定时器1的溢出率来调整波特率的,我们常用的波特率有2400、4800、9600、19200等。
本次我们波特率采用9600、晶振频率11.0592MHz、不倍频(SMOD为0)。
根据芯片的技术手册提供的计算公式:

公式中的fosc = 11.0592MHz,转换为Hz:11059200
公式中的SMOD = 0
公式中的n = 8(采用的是8位重装模式),因此2的8次方就是 256
波特率选定为9600
求初值a =256 - 11059200 / 32 / 12 /9600 = 253
(2)定时器1寄存器的配置
以下三张图是从芯片的手册中截取的定时器1的寄存器信息:



定时器工作模式选择8位自动重装,由于TMOD寄存器不可位寻址,因此我们需要通过位运算将寄存器中的M1和M0改成1和0,其余位保持不变,代码如下:
TMOD &= 0X0F;//将定时器1的寄存器(BIT4-BIT7)复位 TMOD |= 0X20;//将定时器1的M1置1 TH1 = 0XFD;//装自动重装值 TL1 = 0XFD;//装初值 TR1 = 1;//打开定时器1,开始计数
三、串口寄存器的配置
芯片手册中与串口相关的寄存器截图如下:


我们的需求是:使用串口模式1、发送和接受数据、不倍频
因此寄存器的设置应为:
SCON寄存器内的值设置为:0101 0000 转换为十六进制:0X50
PCON:0000 0000
串口寄存器设置的代码为:
SCON = 0X50; PCON = 0X00;
四、中断寄存器的配置
最后,如果希望使用中断的方式接受串口的数据,需要配置中断寄存器:
1.开启总中断
2.开启串口中断
代码如下:
EA = 1;//开总中断 ES = 1;//开串口中断
五、 串口初始化函数
将代码汇总,即可构成一个串口初始化代码:
cpp
void UART_Init(void)
{
//定时器配置
TMOD &= 0X0F;//将定时器1的寄存器(BIT4-BIT7)复位
TMOD |= 0X20;//将定时器1的M1置1
TH1 = 0XFD;//装自动重装值
TL1 = 0XFD;//装初值
TR1 = 1;//打开定时器1,开始计数
//串口配置
SCON = 0X50;//串口工作模式1
PCON = 0X00;//不倍频
//中断配置
EA = 1;//开总中断
ES = 1;//开串口中断
}
六、 特别注意
在完成上述的配置后,就可以使用51单片机的串口发送和接收数据了,但是需要注意的是:
- 单片机在发送和接收完一次数据后,都会产生中断,进入中断服务函数;
- 需要在中断服务函数中进行判断是发送完成产生的中断还是接收完成产生的中断;
- 发送完成后TI会置1
- 接收完成后RI会置1
- 在处理完后将中断标志位清零,否则无法再次进入中断函数。
示例:
cpp
void UART_Interrupt(void) interrupt 4
{
if(RI == 1)
{
//处理逻辑
}
if(TI == 1)
{
//处理逻辑
}
}
//注意:在中断服务函数中,需要尽量缩短代码的执行任务,以免本次执行还未结束,下次中断已经开始,导致程序混乱。