51单片机练习:串口通信篇(C语言)
题目
在上位机上用串口调试助手发送一个字符X,单片机收到字符后返回给上位机“I get X”,串口波特率设为9600bps。(来自郭天祥老师的51单片机练习)
代码
初始化函数:
void Init()
{
//T1设置
TMOD = 0x20;//T1设置为工作方式2
TH1 = 0xfd;
TL0 = 0xfd;
TR1 = 1;//启动T1
//串口设置
SM0 = 0;
SM1 = 1;//串口工作方式1
REN = 1;//允许串行接收
EA = 1;//打开总中断
ES = 1;//打开串口中断
}
串口中断函数:
void Serial() interrupt 4
{
RI = 0;//串口的接收中断标志位置0
res = SBUF;//读取接收缓冲区的数据
flag = 1;//标志位置1,标志接收到数据
}
整个项目代码:
#include <reg52.h>
//【例6.5.1】在上位机上用串口调试助手发送一个字符X,单片机收到字符后返回给上位机“I get X”,串口波特率设为9600bps。
//晶振频率:11.0529MHz
#define uint unsigned int
#define uchar unsigned char
uchar flag,res,i;
uchar code resCode[] = "I get ";
void Init();
void main()
{
Init();
while(1)
{
//如果接收到数据
if(flag == 1)
{
ES = 0;//关闭串口中断
for(i = 0;i < 6;i++)
{
SBUF = resCode[i];//发送缓冲区读取要发送的数据
while(!TI);//等待数据是否发送完毕
TI = 0;//发送中断标志位置0
}
SBUF = res;
while(!TI);//等待数据是否发送完毕
TI = 0;//发送中断标志位置0
ES = 1;//打开串口中断
flag = 0;//标志位置0
}
}
}
//初始化函数
void Init()
{
//T1设置
TMOD = 0x20;//T1设置为工作方式2
TH1 = 0xfd;
TL0 = 0xfd;
TR1 = 1;//启动T1
//串口设置
SM0 = 0;
SM1 = 1;//串口工作方式1
REN = 1;//允许串行接收
EA = 1;//打开总中断
ES = 1;//打开串口中断
}
//串口中断函数
void Serial() interrupt 4
{
RI = 0;//串口的接收中断标志位置0
res = SBUF;//读取接收缓冲区的数据
flag = 1;//标志位置1,标志接收到数据
}
实验结果
串口助手实验结果图:
定时器TH1和TL1的计算
本题T1的TH1和TL1的计算过程如下:
心得/经验分享
- 这次实验,更进一步理解了定时器/计数器加1的意义,加1指的是加一个机器周期,而一个机器周期等于12倍的时钟/振荡周期,一个时钟周期就是单片机晶振频率的倒数。
- 一开始不理解为什么串口的实验要用到定时器,后来才知道,因为串口在收发数据的时候,按照一定的波特率传输数据,而这个波特率需要定时器去定时,才会有溢出率,从而得到波特率。
- 当单片机要发送多个数据给串口助手时,要一个一个发送,单片机发送完数据之后,会将发送中断标志位TI置1,之后要注意给TI清0,便于下一次的串口数据发送。
- 本实验中没有写定时器1的中断语句,因为定时器1在工作方式2的情况下时8位自动重装方式,故不需手动打开T1的中断,也无需写T1的中断程序。
- 在主函数中,检测到flag为1时,将串口中断ES清0,避免发送完一个数据后,程序又进入串口中断将flag置1,导致进入死循环。(串口的收发数据和中断不是一定要一起的,串口可以执行收发数据功能,但是不进入中断,进入中断就是增加了一个功能,让串口可以停在中断中做其它事情)
- 本实验中串口中断程序和主函数中的SBUF不是一个东西,它们是共用一个地址的两个独立的寄存器,单片机识别操作哪个寄存器看程序的语句,“res = SBUF”操作的是接受缓冲寄存器,“SBUF = res”操作的是发送缓冲寄存器。