从单片机基础到程序框架(全集 2019pdf版).pdf - 第750页
上图 12 7.5.1 灌入式驱动 8 个 LED 程序功能如 下: 波特率 96 00, 校验位 NONE (无) , 数据 位 8, 停止 位 1。 在上 位机的串口 助手里, 发送 一个十六进 制 (HEX 模式) 的 01, 让单片机的一颗 LED “亮” 。 发送一个十 六进制 (HEX 模式 ) 的 0 0, 让单片机的 一颗 LED “灭” 。 上位机的串 口助手的使用, 请参考前面 第 11 节的相 关内容, 或者自己在…

硬件串口接收完一个字节的数据之后,会及时产生一个串口中断去通知单片机接收数据。单片机在串口
中断函数里直接读取“串口专用缓存寄存器”SBUF 的数据,就可以直接获得一个完整的 8 位宽度的数据,省
去了繁琐的驱动时序底层。
串口的中断函数跟定时器的中断函数很类似,只不过中断号不一样而已,比如我们前面章节用的定时器
0 的中断号是“1”,而本节串口的中断号是“4”。这些其实是 C 编译器定的游戏规则,我们只要根据它提供
的数据手册遵守它的游戏规则就好了。串口中断函数里还有一个地方要注意,硬件串口“接收完一个字节”
的数据后产生一次中断,而硬件串口“发送完一个字节”的数据后也产生一次中断,这两个一“收”一“发”
的中断都是共用中断号为“4”的中断函数,因此,我们必须在中断函数里通过判断寄存器的 RI 和 TI 的标
志位来判断到底是“收”的中断,还是“发”的中断,并且软件上要及时把 RI 或者 TI 及时清零,避免不断
进入中断的情况。参考代码如下:
unsigned char Gu8ReceiveData=0; //接收到一个字节的数据
void usart(void) interrupt 4 //串口接发的中断,中断号为 4
{
if(1==RI) //接收完一个字节后引起的中断
{
RI = 0; //及时清零,避免一直无缘无故的进入中断。
Gu8ReceiveData=SBUF; //直接读取“串口专用缓存寄存器”SBUF 的 8 位数据。
}
else //发送数据引起的中断
{
TI = 0; //及时清除发送中断的标志,避免一直无缘无故的进入中断。
//以下可以添加一个全局变量的标志位的相关代码,通知主函数已经发送完一个字节的数据了。
}
}
【127.5 上位机与单片机的串口通信例程。】

上图 127.5.1 灌入式驱动 8 个 LED
程序功能如下:
波特率 9600,校验位 NONE(无),数据位 8,停止位 1。在上位机的串口助手里,发送一个十六进制(HEX
模式)的 01,让单片机的一颗 LED“亮”。发送一个十六进制(HEX 模式)的 00,让单片机的一颗 LED“灭”。
上位机的串口助手的使用,请参考前面第 11 节的相关内容,或者自己在网上查找串口助手软件的使用方法,
串口助手软件网上很多,我们的使用要求不高,随便选用一家都可以。代码如下:
#include "REG52.H"
void usart(void);
sbit P0_0=P0^0; //一颗 LED 灯
unsigned char Gu8ReceiveData=0; //接收到一个字节的数据
void main()
{
unsigned char u8_TMOD_Temp=0;
P0_0=1; //LED 灭。1 代表 LED 灭, 0 代表亮
//串口的波特率与内置的定时器 1 直接相关,因此配置此定时器 1 就等效于配置波特率。
u8_TMOD_Temp=0x20; //即将把定时器 1 设置为:工作方式 2,初值自动重装的 8 位定时器。
TMOD=TMOD&0x0f; //此寄存器低 4 位是跟定时器 0 相关,高 4 位是跟定时器 1 相关。先清零定时器 1。
TMOD=TMOD|u8_TMOD_Temp; //把高 4 位的定时器 1 填入 0x2,低 4 位的定时器 0 保持不变。
TH1=256-(11059200L/12/32/9600); //波特率为 9600。11059200 代表晶振 11.0592MHz,
TL1=256-(11059200L/12/32/9600); //L 代表 long 的长类型数据。根据芯片手册提供的计算公式。
TR1=1; //开启定时器 1

SM0=0;
SM1=1; //SM0 与 SM1 的设置:选择 10 位异步通信,波特率根据定时器 1 可变
REN=1; //允许串口接收数据
//为了保证串口中断接收的数据不丢失,必须设置 IP = 0x10,相当于把串口中断设置为最高优先级,
//这个时候,串口中断可以打断任何其他的中断服务函数实现嵌套,
IP =0x10; //把串口中断设置为最高优先级,必须的。
ES=1; //允许串口中断
EA=1; //允许总中断
while(1) //主循环
{
}
}
void usart(void) interrupt 4 //串口接发的中断函数,中断号为 4
{
if(1==RI) //接收完一个字节后引起的中断
{
RI = 0; //及时清零,避免一直无缘无故的进入中断。
Gu8ReceiveData=SBUF; //直接读取“串口专用缓存寄存器”SBUF 的 8 位数据。
if(0x01==Gu8ReceiveData)
{
P0_0=0; //LED 亮。1 代表 LED 灭, 0 代表亮
}
else
{
P0_0=1; //LED 灭。1 代表 LED 灭, 0 代表亮
}
}
else //发送数据引起的中断
{
TI = 0; //及时清除发送中断的标志,避免一直无缘无故的进入中断。
//以下可以添加一个全局变量的标志位的相关代码,通知主函数已经发送完一个字节的数据了。
}
}
【127.6 单片机串口电路的简易分析。】