1.串口介绍
串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。
单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。
51单片机内部自带UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),可实现单片机的串口通信。
UART(Universal Asynchronous Receiver Transmitter,通用异步收发器),与传统8051单片机的串口完全兼容。设有2个互相独立的接收、发送缓冲器,可以同时发送和接收数据。发送缓冲器只能写入而不能读出,接收缓冲器只能读出而不能写入,因而两个缓冲器可以共用一一个地址码(99H)。两个缓冲器统称串行通信特殊功能寄存器SBUF。
管脚:STC89C52系列单片机串行口对应的硬件部分对应的管脚是P3.0/RxD和P3.1/TxD。
串口通信优点:STC89C52系列单片机的串行通信口,除用于数据通信外,还可方便地构成一一个或多个并行I/O口,或作串一并转换,或用于扩展串行外设等。·
2.硬件电路
简单双向串口通信有两根通信线(发送端TXD和接收端RXD)
TXD与RXD要交叉连接
当只需单向的数据传输时,可以直接一根通信线
当电平标准不一致时,需要加电平转换芯片
下图是以前的投影仪的插口线脚分布图,可以看的也用了TXD来发送数据,RXD来接受数据
3.电平标准
电平标准是数据1和数据0的表达方式,是传输线缆中人为规定的电压与数据的对应关系,串口常用的电平标准有如下三种:
TTL电平:+5V表示1,0V表示0
RS232电平:-3~-15V表示1,+3~+15V表示0
RS485电平:两线压差+2~+6V表示1,-2~-6V表示0(差分信号)
注意这里单片机用的是TTL电平,而计算机用的是RS232电平,所以在单片机与电脑进行串口通信的时候要加电平转换芯片
4.常见通讯接口比较
全双工:通信双方可以在同一时刻互相传输数据
半双工:通信双方可以互相传输数据,但必须分时复用一根数据线
单工:通信只能有一方发送到另一方,不能反向传输
异步:通信双方各自约定通信速率
同步:通信双方靠一根时钟线来约定通信速率
总线:连接各个设备的数据传输线路(类似于一条马路,把路边各住户连接起来,使住户可以相互交流)
5.UART的四种工作模式
串行通信设有4种工作方式,其中两种方式的波特率是可变的,另两种是固定的,以供不同应用场合选用。波特率由内部定时器/计数器产生,用软件设置不同的波特率和选择不同的工作方式。主机可通过查询或中断方式对接收/发送进行程序处理,使用十分灵活。
模式0:同步移位寄存器
模式1:8位UART,波特率可变(常用)
模式2:9位UART,波特率固定
模式3:9位UART,波特率可变
6.串口参数及时序图
波特率:串口通信的速率(发送和接收各数据位的间隔时间)
检验位:用于数据验证(九位数据模式时的最后一位,RB8/TB8)
停止位:用于数据帧间隔
检验位:常用的有奇校验,偶校验。通常来判断发送的数据的正确性,是否有丢帧的情况
以偶校验举例说明
发送一段数据 0000 0011 1 这里最后一位1表示前面8位数据有偶数个1
0000 0001 0 这里最后一位0表示前面8位数据有奇数个1
但是如果说发送 0000 0011 1 接收到的是0000 0101 1,可以发现偶校验正确,这也就是奇偶校验的弊端,即不能判断出每一位的数据是否发生改变,只能判断1的位数是否为偶数,所以说在一定程度上是有检验作用的,但是不是非常精确。
7.串口通信流程图
看串口模式图我们软件在进行编程的时候要注意:
SUBF(数据缓存器),TI(数据发送标志位),RI(数据接受标志位)的配置要求
以及T1溢出率的配置(TH1,TL1初值),SMOD置0时为正常波特率,置1时波特率加倍
将数据写入SBUF时,就进行发送,我们这里不管是如何一位一位的发送的,只将数据写入SUBF中即可。
8.串口相关寄存器
这里还是为了尽可能的全面,所以在手册截的图。
9.定时器模式选择
10.中断模式选择
11.波特率的计算方法:
A.
在图上的寄存器SCON的配置中也可以看出来。1,是看SMOD的配置为1那么波特率加倍。2,其次是定时器1的溢出率,计算方法是周期的倒数。
下面举波特率为4800的计算方法(也是我们下面的代码里面的定时器1配置的)
设T=13us(12MHZ下13us溢出一次),定时器1的溢出率=1/T=0.0769230769230769,为使定时器误差小,这里的SMOD的配置为1,所以最后,波特率=(1/T)x(1/16)x1000000=4,807.692307692308 约等于4800
中断模式以及寄存器的配置
串口中断位要打开,而定时器1的中断就不用开了(溢出后不用进行中断执行其他操作,计时器只是提供稳定的波特率)
B.
以初始值 TL1 = 0xF3; TH1 = 0xF3; 计数13个数就会溢出(256-243)
而12MHZ单片机,即1微秒就会计数一次,溢出就是13微秒
波特率 = 1÷ 13us ÷ 16 = 4807.69 HZ
所以赋 初始值 TL1 = 0xF3; TH1 = 0xF3;波特率就是 4800HZ
此时误差率为: 7.69 ÷ 4800 = 0.16%
12.代码示例(串口与电脑互发数据)
主函数:
#include <REGX52.H>
#include "UART.h"
unsigned char Sec;
void main()
{
UART_Init(); //串口初始化
while(1)
{
}
}
void UART_Routine() interrupt 4
{
if(RI==1) //如果接收到数据,硬件自动将标志位RI置1,表示接收到了电脑发送的数据
{
P2=SBUF; //读取SBUF数据,取反后输出到LED
UART_SendByte(SBUF);//将受到的数据发回串口(实现单片机向电脑发送数据)
RI=0; //按照手册RI需要手动置0
}
}
SUBF输入函数:
#include <REGX52.H>
void UART_Init()
{
SCON = 0x50; //工作方式1,其中的REN为1,允许接收
PCON |= 0x80; //为了减少误差波特率加倍
TMOD &= 0x0F; //设置定时器1模式
TMOD |= 0x20; //设置定时器1模式
TL1 = 0xF3; //设定定时初值
TH1 = 0xF3; //设定定时器重装值
ET1 = 0; //禁止定时器1中断
TR1 = 1; //启动定时器1
ES=1; //设置接收发送中断
EA=1;
}
void UART_SendByte(unsigned char Byte)
{
SBUF=Byte; //将SBUF数据赋值
while(TI==0);//if(TI==1) {TI=0;}在停止位后硬件自动将TI置1,按照手册,这里要手动置0
TI=0;
}