什么是串口
串行接口(Serial Interface)简称串口,也称串行通讯接口(通常指COM接口),是采用串行通信方式的扩展接口。串口通讯时数据是一位一位地顺序传送, 因此其优点是通信线路简单,只要一对传输线就可以实现双向通信,从而大大降低了成本,特别适用于远距离通信,通讯距离可以从几米到几千米,缺点是传送速度较慢。
与串口有关的寄存器
51单片机与串口有关的有8个寄存器,我们需要用到的寄存器有SCON、SBUF、PCON。
SBUF寄存器
51单片机的说明书介绍了很多,也可能看不懂,我们只需要学会怎么用就好了。
char data_msg = 'a';
SBUF = data_msg;
用起来非常简单,定义一个字符变量,把字符传给SBUF就行了。这个寄存器不需要去配置,直接使用就好了。
SCON寄存器
SCON寄存器有8个位,它的作用是用来配置波特率的模式、是否接收使能和串口中断之类的。我们暂时不关心串口中断和接收使能,主要是配置波特率模式,主要看SM0和SM1两个位。我们选择方式一 ,也就是0100 0000,转换16进制就是0x40。
SCON = 0x40;
PCON寄存器
PCON寄存器比较简单,我们只需要关心SMOD和SMOD0这两个位就好了。但是这个资料有个错误的地方,SMOD置0时, 资料说的是波特率工作模式加倍,但事实上SMOD置0并没有加倍。
我们选择波特率不加倍,也就是SMOD置0,因为51单片机的寄存器默认8位都为0,再加上也不需要使用SMOD0寄存器,所以我们可以不配置PCON寄存器。
什么是波特率
在信息传输通道中,携带数据信息的信号单元叫码元,单位时间内通过信道传输的码元数称为码元传输速率,简称波特率,其单位是波特(Baud,symbol/s),波特率是传输通道频宽的指标。“波特”(Baud)本身已是速率,所以不需要写成 Baud Rate(Rate是赘字)。虽然单位“波特”本身就已经是代表每秒的调制数,以“波特每秒”为单位是一种常见的错误,但是在一般中文口语化的沟通上还是常以“波特率”来描述“波特”(Baud)。
波特率的计算
定时器的配置
如图可知,波特率我们需要用定时器1来计算,这时我们就需要配置TMOD寄存器。
TMOD寄存器的配置,我们选择8位自动重载载定定时器这个模式,也就是把M1和M0配置为10。也就是0010 0000,转换为16进制是0x20。
TMOD &= 0x0F; //高4为清零,低4位不变
TMOD |= 0x20; //设定位8位重装模式
波特率计算
我们选择的是工作方式一,然后以12T的模式来计算。SYSclk指的是晶振的频率,我这块51单片机晶振的频率是11.0592MHz。
假设,我们想要的波特率位9600,那么可以推导出一个公式。
9600 = (2^SMOD / 32) * 11059200 / 12 / (256 - TH1)
在这个式子当中,SMOD是已知的,因为我们在PCON并没有配置它,所以SMOD为0。接下来只要求出TH1的值,在加上TH1的值和TL1的值是一样的,所以我们就可以配置波特率了。公式推导为:
9600 = (1 / 32) * 921600 / (256 - TH1)
9600 = 28800 / (256 - TH1)
TH1的值为253,转换为16进制是0xFD。所以,定时器1的TH1 = 0xFD,TL1 = 0xFD。
void UartInit(void) //9600bps@11.0592MHz
{
SCON = 0x40; //配置串口工作方式1,REN不使能
TMOD &= 0x0F;
TMOD |= 0x20;//定时器1工作方式为8位自动重载
TH1 = 0xFD;
TL1 = 0xFD;//9600波特率初值
TR1 = 1; //开始计时
}
当然,如果想要配置115200的波特率也可以自己推导。
总代码
#include "reg52.h"
void Delay1000ms() //@11.0592MHz
{
unsigned char i, j, k;
i = 43;
j = 6;
k = 203;
do
{
do
{
while (--k);
} while (--j);
} while (--i);
}
void UartInit(void) //9600bps@11.0592MHz
{
SCON = 0x40; //配置串口工作方式1,REN不使能
TMOD &= 0x0F;
TMOD |= 0x20;//定时器1工作方式为8位自动重载
TH1 = 0xFD;
TL1 = 0xFD;//9600波特率初值
TR1 = 1; //开始计时
}
void main()
{
char data_msg = 'a';
UartInit();
while(1)
{
Delay1000ms();
SBUF = data_msg;
}
}