目录
串口通信
串口介绍
串口是一种应用十分广泛的通讯接口,串口成本低、容易使用、通信线路简单,可实现两个设备的互相通信。单片机的串口可以使单片机与单片机、单片机与电脑、单片机与各式各样的模块互相通信,极大的扩展了单片机的应用范围,增强了单片机系统的硬件实力。
51单片机内部自带UART (Universal Asynchronous ReceiverTransmitter,通用异步收发器),可实现单片机的串口通信
硬件电路
TXD:transmit exchange data
RXD:receive exchange data
要交叉连接,原因很简单:一端发送数据时,另一端就要接收,若非如此无法实现信息的传输
电平标准
这里的负电压,可以通过例如将电池正极接在GND上,则电池的负极即为负压的方式来实现
常见通信接口比较
全双工:通信双方可以在同一时刻互相传输数据
半双工:通信双方可以互相传输数据,但必须分时复用一根数据线
单工: 通信只能有一方发送到另一方,不能反向传输
异步:通信双方各自约定通信速率
同步: 通信双方靠一根时钟线来约定通信速率
总线: 连接各个设备的数据传输线路(类似于一条马路,把路边各住户连接起来,使住户可以相互交流
通信速率:可以理解为数据传输/接收的快慢,即发送端以一定的频率发送数据,接收端也以一定的频率进行接收,二者的频率可能是各自决定也可能共同约定,可能相同也可能不同(数据的发送与接收一般以比特为单位)
51单片机的UART
STC89C52有1个UART
STC89C52的UART有四种工作模式
模式0:同步移位寄存器
模式1:8位UART,波特率可变(常用)
模式2:9位UART,波特率固定
模式3:9位UART,波特率可变
对TXD/RXD进行操作时,不会影响P3,反之亦然
串口参数及时序图
波特率:串口通信的速率(发送和接收各数据位的间隔时间)
检验位:用于数据验证
停止位:用于数据帧间隔
8位数据格式:每八位组成一个数据单位,传入寄存器或从寄存器中一起被取出
9位数据格式:多了一个检验位,此位的数据代表了检验方式,如给1时为奇校验,给0时为偶校验
串口模式图
SBUF:串口数据缓存寄存器,物理上是两个独立的寄存器,但占用相同的地址(图中为0x99H)。写操作时,写入的是发送寄存器,读操作时,读出的是接收寄存器
此处定时器(TH1、TL1)的作用为:控制数据传输和接收的频率,与波特率的大小相关
发送控制器/接收控制器:在中断系统中的操作,分别控制着数据的发送与接收
移位寄存器:将从RXD接收到的数据进行划分,每次只将一个比特位的数据传到SBUF中暂存
串口与中断系统
可以看到,发送中断TI和接收中断RI所对应的中断为同一个,由于串口的一端不会发送和接收同时进行,且也不一定都会进入中断系统,故二者并不冲突
不过主机响应中断时事先并不知道是TI还是RI请求的中断,故须在软件中进行判断,以进行对应操作
ES和EA即使能端,PS的值对应着优先级的高低
数据显示模式
串行口控制寄存器
STC89C52系列单片机的串行口有两个控制寄存器:
串行控制寄存器SCON(可位寻址):
SM0/FE:当PCON寄存器中的SMOD0/PCON.6位为1时,该位用于帧错误检测。当检测到一个无效停止位时,通过UART接收器设置该位。它必须由软件清零
当PCON寄存器中的SMOD0/PCON.6位为0时,该位和SM1一起指定串行通信的工作方式,如下表所示:
最常用的方式1:SM0=1 SM1=0。
SM2:允许方式2或方式3多机通信控制位。在方式2或方式3时,如SM2位为1,REN位为1,则从机处于只有接收到RB8位为1(地址)时才激活中断请求标志位RI为1,并向主机请求中断处理。被确认为寻址的从机则复位SM2位为0,从而才接收RB8为0的数据顿。在方式1时,如果SM2位为1,则只有在接收到有效的停止位时才置位中断请求标志位RI为1:在方式0时,SM2 应为0。
REN:允许/禁止串行接收控制位。由软件置位REN,即REN=1为允许串行接收状态,可启动串行接收器RxD,开始接收信息。软件复位REN,即REN=0,则禁止接收。(receive enable)
TB8:在方式2或方式3,它为要发送的第9位数据,按需要由软件置位或清0。例如,可用作数据的校验位或多机通信中表示地址帧/数据帧的标志位。
RB8:在方式2或方式3,是接收到的第9位数据。在方式1,若SM2=0,则RB8是接收到的停止位。方式0不用RB8。
由于目前只研究方式1,故SM2、TB8、RB8均置0
TI:发送中断请求标志位。在方式0,当串行发送数据第8位结束时,由内部硬件自动置位,即TI=1,向主机请求中断,响应中断后必须用软件复位,即TI=0。在其他方式中,则在停止位开始发送时由内部硬件置位,必须用软件复位。
RI:接收中断请求标志位。在方式0,当串行接收到第8位结束时由内部硬件自动置位RI=1,向主机请求中断,响应中断后必须用软件复位,即RI=0。在其他方式中,串行接收到停止位的中间时刻由内部硬件置位,即RI=1(例外情况见SM2说明),必须由软件复位,即RI=0。
若想进行复位,全部置0
波特率选择特殊功能PCON(不可位寻址):
SMOD:波特率选择位。当用软件置位SMOD,即SMOD=1,则使串行通信方式1、2、3的波特率加倍:SMOD=0,则各工作方式的波特率加倍。复位时SMOD=0。
SMOD0:帧错误检测有效控制位。当SMODO=1,SCON寄存器中的SMO/FE位用于FE(错误检测)功能;当SMODO=0,SCON寄存器中的SMO/FE位用于SMO功能,和SM1一起指定串行口的工作方式。复位时SMODO=0
相关定时器
STC89C52单片机在串口通信中,须用定时器1的8位自动重装模式,定时器的配置此文中不再赘述 只解释溢出率和波特率的关系
波特率的计算
由于定时器1用的是8位自动重装,所以相比较于之前用到16位,溢出变成了每到256溢出一次而非65535。溢出率的计算比较简单,用256减去初始值所得数值即为溢出率大小(+MHz),而后根据SMOD的值再*1或/2,所得值再/16,再将MHz转换成Hz,所得值即波特率大小
由于晶振的固有频率,导致波特率的最小跨度是一定的,要产生在最小跨度之间的波特率就会出现误差
数据传输模式
HEX模式/六进制模式/二进制模式:以原始数据的形式显示
文本模式/字符模式:以原始数据编码后的形式显示
具体配置
void Uart1_Init(void) //4800bps@12.000MHz
{
PCON &= 0x7F; //波特率不倍速
SCON = 0x50; //8位数据,可变波特率
AUXR &= 0xBF; //定时器时钟12T模式
AUXR &= 0xFE; //串口1选择定时器1为波特率发生器
//AUXR不存在于STC89C52单片机中,因为定时器时钟只有12T模式,波特率发生器也只能用定时器1,故实际使用时应删掉这两句
TMOD &= 0x0F; //设置定时器模式
TMOD |= 0x20; //设置定时器模式
TL1 = 0xF9; //设置定时初始值
TH1 = 0xF9; //设置定时重载值
ET1 = 0; //禁止定时器中断
TR1 = 1; //定时器1开始计时
}
串口定时向电脑发送数据
#include <REGX52.H>
#include "Delay.h"
void Uart1_Init(void)
{
PCON &= 0x7F;
SCON = 0x50;
TMOD &= 0x0F;
TMOD |= 0x20;
TL1 = 0xF9;
TH1 = 0xF9;
ET1 = 0;
TR1 = 1;
}
void UART_SendByte(unsigned char Byte)
{
SBUF=Byte;
while(TI==0);
TI=0;
}
unsigned char Sec;
void main()
{
UART_Init();
while(1)
{
UART_SendByte(Sec);
Sec++;
Delay(1000);
//利用延时函数实现每秒发送一次
}
}
电脑通过串口控制LED
#include <REGX52.H>
#include "Delay.h"
void Uart1_Init(void)
{
PCON &= 0x7F;
SCON = 0x50;
TMOD &= 0x0F;
TMOD |= 0x20;
TL1 = 0xF9;
TH1 = 0xF9;
ET1 = 0;
TR1 = 1;
EA=1;
ES=1;
}
void main()
{
UART_Init();
}
void UART_Routine() interrupt 4
{
if(RI==1)
{
P2=SBUF;
UART_SendByte(SBUF);
RI=0;
}
}
注意:
这次用到了串口中断(interrupt 4),故初始化中须加上中断使能的语句EA=1 ES=1
在中断中先判断是否为接收端发出的中断申请,若是,则进行取值,将SBUF寄存器中的暂存值赋给P2控制LED并利用SendByte函数发回给电脑,具有检验的功效
UART_SendByte函数不能同时在main函数和中断中使用,会导致数据错乱,互相破坏