每日一言
那些让你喘不过气的日子,正是蜕变的开始。
串口编程寄存器分析(红色框里面的这个是串口助手里面生成的波特率初始化函数哈)
我们就根据以上的寄存器分析,因为这个是配置波特率的需要的寄存器
PCON
smod= 0 就是PCON的bit 7 这个位置为0 也就是 我们用8421法可以推算出 0x7F 为 0111 1111 ,那么&上个0x7F那么就会等于 &上一个0111 1111 那么我们smod这个位置就会为0 ,那么我们的波特率就不会加倍
SCON
SCON寄存器的话是控制串口工作的模式 有4种方式 ,然后这个TH1也是通过这个SCON寄存器里面的讲解来算的
先介绍一下8 位 UART 的含义
在串口工作模式 1(你代码中使用的模式)中,“8 位 UART” 指:
- 数据位为 8 位:每次传输 1 个字节(8 位)的数据,例如 ASCII 字符(如'A'对应二进制0100 0001)。
- 无第 9 位:与模式 2/3(9 位 UART)不同,模式 1 不使用 TB8/RB8 位,适合简单的数据传输(如发送文本、传感器数据等)。
TMOD
这个就是老朋友了,定时器的工作模式
我们一般用按位与和按位或来设置
我们对于串口通信的定时器的模式的话我们就设置为8位的自动重装载模式
波特率的计算和定时器不可分家
TL1 和TH1 这个啊就是定时器1的两个8位寄存器
在串口通信中啊,一般使用的是8位自动重载的模式,这个模式是什么意思呢,就是为了计算波特率的准确度,在TL1溢出的时候,TH1会自动将自身的值给TL1,这样就不会有误差,精度更高,所以在配置串口通信的时候,我们会将TH1和TL1的值设置成相同的,就是为了计算波特率的精准度高。
Tips:这个scon的8位UART和TMOD 8位自动装载的这个是没有一点关系的,不要以为都是8就有什么关系,他们的功能都是独立的!!!
但实际应用中,模式 1(8 位 UART)+ 定时器 1 模式 2 是最常用的组合,因为:
- 8 位数据格式满足大多数场景(如 ASCII、传感器数据)。
- 定时器模式 2 的自动重装机制简化了波特率控制。
5. 关键区别总结
参数 | 8 位 UART(SCON) | 8 位自动重装(Timer1) |
作用 | 定义串口数据帧格式 | 生成稳定的波特率时钟 |
相关位 | SM0=0, SM1=1 (模式 1) | TMOD.6=1, TMOD.5=0 (模式 2) |
数据位数 | 每帧 8 位数据 | 与数据位无关 |
波特率控制 | 依赖定时器溢出率 | 直接决定溢出率 |
总结
- 8 位 UART(SCON)和定时器 1 模式 2(8 位自动重装)是串口通信的黄金组合,但两者功能独立。
讲完这个寄存器那我们就要根据这个寄存器为什么要这样配置我们要搞懂原理
PCON为什么配置PCON &=0x7F?
这行代码使用了按位与操作 。0x7F 转换为二进制是 0111 1111 ,PCON 寄存器与 0x7F 按位与,会将 PCON 寄存器的最高位(即 SMOD 位 )清零,其他位保持不变 ,从而确保 SMOD = 0,使串口波特率不加倍 。
SCON为什么配置成0x50??
因为0x50相当于 0101 0000 就是我不用后面的四位不用的位都上0,就是TB8 RB8 TI RI,然后用8421法算出来就是0x50,那为什么是前面4位都是0101呢 因为和他们的工作方式有关,这边我们选择是是8位UART 所以SM0是0,SM1是1,还有我们运行串口通信所以REN要设为1,所以就是0101 0000 转换为0x50
TMOD为什么设置为TMOD &= 0x0F; TMOD |= 0x20;????
因为我们定时器用的是定时器1,所以只用定时器1,定时器0不变,然后定时器1我们还要设置其为8位的自动重装载模式,所以先定时器M1M0的位置要为1、0,也说明了这个模式的作用,所以我们先TMOD &= 0x0F; 0x0F是00001111 &上这个之后 定时器0不变,定时器1清0,因为这个是按位&,后面TMOD |= 0x20就是让M1M0的位置要为1、0 所以就是 0010 0000 | 上这个之后定时器1有1为1全0为0 ,所以此时定时器就算设置好了 然后这个0010 0000利用8421法就直接变成 0x20
TL1 TH1为什么设置为 0xFD ????
首先是定时器1,1的来头
其次要搞清楚为什么相同为什么都是一样的值
- 因为是我们的TMOD设置的是8位自动重装载模式,为什么要设置的是8位自动重装载模式,因为这个模式的特性是 TL1当溢出时将TH1存放的值自动重装入TL1.这样有利于我们计算波特率的精准度高,所以我们要设置成一样的初始值。
这些配完就 TR1(运行控制位)=1启动定时就可以了
别忘了AUXR这个寄存器,这个寄存器的话reg52.h里面是没有定义的,所以我们用芯片手册查出来用法为
就直接先sfr AUXR=0x8E先声明一下 后面在初始里面加入 AUXR=0x01就好了