本文主要参考资料:
马淑华、高 军、蔡凌.单片机原理与接口技术(第三版).北京:北京邮电大学出版社,2018.6
①全双工通信
通信双方可同时进行数据收发的工作方式。51单片机的串行口是全双工传输方式。
②半双工通信
通信双方交替进行双向数据传输,但两个方向的传输不能同时进行。
③单工通信
数据只能单方向传输。
SBUF物理地址为99H,但实际是对应两个缓冲器(一收一发)
SM0和SM1:工作方式选择位,模式选择如下表
SM2:多机通信选择。当SM2=0时,单机对单机通信;当SM2=1时,多机对多机通信。
REN:串行接收允许位,REN=1 允许接收数据,手动控制;
RB8 :在模式 2、3 时为第 9 个接收位;
TB8:在模式 2、3 时为第 9 个发送位;
RI:串口接收完成中断标志位(即RI=1),需要手动清0;
TI:串口发送完成中断标志位(即TI=1),需要手动清0;
SMOD:波特率加倍控制位。在模式1、2、3下,当SMOD=0时,波特率不加倍;当SMOD=1时,波特率加倍。
其他位暂不做详解
与串行中断相关的两个位:
EA:总中断控制位,EA=1时允许中断,EA=0时禁止中断
ES:串行口中断允许位,ES=1时允许串行口中断,ES=0时禁止串行口中断。
波特率的计算方法:
1 .模式 0 的波特率波特率固定:每个机器周期产生一个移位时钟,可发送或接收一位数据。且不受SMOD位的影响。即
模式0的波特率=/12
2 .模式 2 的波特率由系统的振荡频率fosc和SMOD共同确定,即
模式2的波特率=·/64
3 .模式 1 和模式 3 的波特率模式1和模式3的移位时钟由定时器T1的溢出率决定,故波特率由T1的溢出率与SMOD值共同决定,即
模式1和模式3的波特率= ·T1的溢出率/32
4. 波特率设计
当定时器T1做波特率发生器使用时,最典型的用法是使T1工作在模式2(初值自动加载),若计数初值为X,则每经过“256-X”个机器周期。定时器T1就会产生一次溢出,溢出周期为:
溢出率为溢出周期的倒数,所以波特率为:
从上式解出定时器的初值X:
(1)设置方式
当SM0=0,SM1=0,SM2=0时使用模式0
(2)模式特点
(3) 数据传输过程
发送过程:
将数据写入SBUF时启动发送,串行口即将8位数据以/ 12的波特率从RxD输出(从低位到高位),发送完中断标志TI置"1”,TxD管脚输出同步移位脉冲。
在再次发送数据前,必须用软件将TI清0。.
接收过程:
接收时,将接收中断标志RI=0, 设置REN=1允许接收,启动串接收过程。启动接收过程后,RxD为串行输入端,TxD为同步脉冲输出端。串行接收的波特率为/12。
当接收完成数据(8位)后,控制信号复位,中断标志RI被置”1”,呈中断申请状态。
当再次接收时,必须通过软件将RI清0。
(1)设置方式
当SM0=0,SM1=1时,使用模式1
(2)模式特点
(3)数据传输过程
发送过程:
数据由串行发送端TXD输出。将数据写入SBUF时启动发送,写“SBUF”信号还把“1”装入发送移位寄存器的第9位,并通知TX控制单元开始发送。
发送完成后,硬件置位中断请求位Tl,即TI=1,向主机请求中断处理。
再次发送需要将TI置0。
接收过程
当允许接收位REN=1时,启动接收。
接收完成之后,置位中断请求位RI,即RI=1,向主机请求中断处理。
再次接收需要手动将RI置0。
模式2: 9位UART,波特率固定
模式3: 9位UART,波特率可变
(1)设置方式
SM0=1,SM1=0设置为模式2;
SM0=1,SM1=1设置为模式3;
(2)模式特点
(3)数据传输过程
发送过程:
将数据写入SBUF后立即启动发送。
发送完成后,硬件置位中断请求位Tl,即TI=1,向主机请求中断处理。
再次发送需要手动将TI置0。
接收过程:
当允许接收位REN=1时,启动接收。
接收完成之后,置位中断请求位RI,即RI=1,向主机请求中断处理。
再次接收需要手动将RI置0。
模式1是串口最常用的方式,所以重点讲模式1的应用。
实例所使用的单片机是 亚博智能mini51开发板,编程开发环境为keil5
步骤:
1、初始化串口
设置工作模式:
由于我们使用的是模式1,所以设置SM0=0,SM1=0,直接赋值SCON=0x40;
配置波特率:
配置波特率要设置定时器的工作模式及计算定时器的初值。这里选择定时器T1模式2,8位自动重装方式,然后计算初值。波特率选择不加倍。
初值X的计算公式已经给出。
为了省事,可以直接使用下表经过计算后的值:
查表可知,9600波特率的TH1初值X为0XFD,波特率不加倍。
代码如下:
//串口初始化函数
void UartInit() //9600bps@11.0592MHz
{SCON = 0x40; //0100 0000 串口工作模式1TMOD &= 0x0F; //清空TMOD中定时器1相关TMOD |= 0X20; //设置定时器1工作模式2:8位自动重载TH1 = 0xFD; //设定定时初值TL1 = 0XFD;TR1 = 1; //启动定时器1
}
2、编写发送字符的函数
当寄存器SBUF被赋值时,启动发送。在这个发送字符的函数中,只需要写出被赋值语句即可。
void send_char(unsigned char m)
{SBUF=m;
}
完整代码:
#include <REGX52.H>
//串口初始化函数
void UartInit() //9600bps@11.0592MHz
{SCON = 0x40; //0100 0000 串口工作模式1TMOD &= 0x0F; //清空TMOD中定时器1相关TMOD |= 0X20; //设置定时器1工作模式2:8位自动重载TH1 = 0xFD; //设定定时初值TL1 = 0XFD;TR1 = 1; //启动定时器1
}//字符发送函数
void send_char(unsigned char m)
{SBUF=m;
}
//延时约1s的程序
void delay()
{unsigned char i, j, k;i = 8;j = 1;k = 243;do{do{while (--k);} while (--j);} while (--i);
}
//主函数
void main()
{UartInit();//调用串口初始化函数while(1){send_char('p');//调用发送一个字符的函数delay();//调用延时1S的函数}
}
将程序烧录到单片机后,打开串口助手即可查看串口收到的单片机信息。
(串口调试助手操作)
(串口接受到了字符)
类似于发送单个字符的步骤
步骤:
第一步已经介绍过,下面介绍编写发送字符串的函数。
编写发送字符串的函数:
void send_string(unsigned char str[])
{unsigned char i=0;while(str[i]!='