Skip to content

过采样

过程是全自动的(硬件完成),但模式是可以配置的(软件选择)。

对于绝大多数应用场景,你甚至 完全不需要管它,直接使用默认配置即可。

1. 为什么要过采样?

因为 UART 是异步的(没有时钟线),接收方并不知道发送方发来的这一位数据是从哪一微秒准确开始的,也没法保证双方的时钟完全一致(可能有 1-2% 的误差)。

2. 寻找起始位:防抖动 (Start Bit Detection)

当接收引脚(RX)检测到一个 下降沿(电平从 1 变 0)时,硬件不会马上相信“数据来了”,它怀疑这可能是个静电干扰或尖峰噪声。

STM32 的处理逻辑(以 16x 采样为例):

  1. 检测到下降沿

  2. 硬件开始计数。

  3. 它会去检查第 3、5、7 次采样点(检查前半段)。

  4. 判断规则: 如果这 3 次采样中,大部是 0(低电平),硬件才确认:“好,这是真的起始位,不是噪声,准备接收数据!”

    • 如果这几次采样里发现还是高电平,硬件就会认为这是噪声,直接忽略,回到空闲状态

3. 读取数据:取中间值 (Data Sampling)

一旦确认了起始位(起始位只确认一次 3.5.7),硬件就要找 最稳定的地方读取数据。哪里最稳定?当然是 正中间

两边(第1份和第16份)靠近电平跳变沿,信号可能还没升上去或者刚降下来,容易出错。

所以,硬件会锁定中间的 第 8、9、10 次采样点

4. 少数服从多数:噪音检测 (Noise Detection)

即使选了中间的 8、9、10 三个点,硬件还是很谨慎。它会采用 “三票两胜” (Majority Vote) 的逻辑。

举个例子: 假设发送方发的是高电平(1),但因为线路干扰,中间出现了一个短暂的波动:

  • 第 8 次采样:1
  • 第 9 次采样:0 (干扰!)
  • 第 10 次采样:1

硬件的判决:

  1. 判定结果: 因为有两个 1,一个 0,所以 最终结果判定为 1
  2. 副作用: 虽然读到了数据,但硬件发现这 3 个值不一致,它会悄悄把寄存器里的 NE (Noise Error) 标志位置 1。
    • 这就告诉程序:“数据我帮你尽力还原了,但是刚才信号有点脏,你自己注意一下。”
txt
Tick: | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |10 |11 |12 |13 |14 |15 |16 |
      |---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
动作:            ^       ^       ^   ^   ^   ^
确认起始位           读取数据位
(避免假触发)         (取中间值投票)

这就是为什么串口在环境很差、波特率有点偏差的情况下,依然能稳定工作的原因——它不是看一眼就定生死,而是看了好几眼,还搞了个投票。