韦东山开发手册阅读笔记(二)

35 阅读17分钟

补充:寄存器

🔑 一、寄存器到底是什么?

寄存器 = CPU/外设的「控制面板」
通过读写特定的内存地址,就能控制硬件的行为(比如点亮LED、配置串口、读取按键)
嵌入式系统 = CPU + 内存映射的寄存器 + 外设硬件

🎯 二、嵌入式中最常接触的3类寄存器

1️⃣ CPU内核寄存器(了解即可)

  • R0~R15、CPSR 等(ARM架构)
  • 用途:函数传参、保存状态、程序计数
  • 初期不用深究,编译器会帮你处理好

2️⃣ 外设控制寄存器(⭐ 重点!天天用)

这是你操作硬件的核心,比如:

外设典型寄存器作用
GPIOGPXCON, GPXDAT, GPXUP配置引脚方向/输出值/上拉
UARTULCON, UCON, UTXH, URXH配置串口/收发数据
TimerTCFG0, TCON, TCNTB配置定时器/计数/中断
InterruptSRCPND, INTMOD, INTMSK管理中断源/使能/屏蔽

3️⃣ 系统控制寄存器(进阶用)

  • 时钟配置、电源管理、看门狗等

🛠️ 三、实操:如何操作寄存器?(3种主流方式)

方式1:直接指针操作(最底层,理解原理必学)

// 假设GPIOB的第5号引脚控制LED
#define GPIOB_CON  (*(volatile unsigned int *)0x56000010)
#define GPIOB_DAT  (*(volatile unsigned int *)0x56000014)

// 配置为输出模式
GPIOB_CON = (GPIOB_CON & ~(0xF << 20)) | (0x1 << 20);  // 清0后设1
// 输出高电平点亮LED
GPIOB_DAT |= (1 << 5);

方式2:寄存器结构体映射(工程常用,可读性好)

// 定义GPIO寄存器组结构体(参考芯片手册)
typedef struct {
    volatile unsigned int CON;
    volatile unsigned int DAT;
    volatile unsigned int UP;
} gpio_reg_t;

// 映射到物理地址
#define GPIOB_BASE  ((gpio_reg_t *)0x56000010)

// 使用
GPIOB_BASE->CON = ...;
GPIOB_BASE->DAT |= (1 << 5);

方式3:调用厂商/内核提供的API(Linux驱动开发主流)

// Linux内核中(不直接操作寄存器!)
#include <linux/gpio.h>
gpio_request(LED_PIN, "led");
gpio_direction_output(LED_PIN, 1);  // 输出高电平

// 或设备树 + pinctrl + gpio子系统(现代做法)

第九章 中断体系结构

9.1 ARM 体系 CPU 的 7 种工作模式

  1. 用户模式(usr):ARM 处理器正常的程序执行状态。
  2. 快速中断模式(fiq):用于高速数据传输或通道处理。
  3. 中断模式(irq):用于通用的中断处理。
  4. 管理模式(svc):操作系统使用的保护模式。
  5. 数据访问终止模式(abt):当数据或指令预取终止时进入该模式,可用于虚拟存储及 存储保护。
  6. 系统模式(sys):运行具有特权的操作系统任务。
  7. 未定义指令中止模式(und):当未定义的指令执行时进入该模式,可用于支持硬件协 处理器的软件仿真

可以通过软件来进行模式切换,或者发生各类中断、异常时 CPU 自动进入相应的模式。 除用户模式外,其他 6 种工作模式都属于特权模式。 大多数程序运行于用户模式,进入特权模式是为了处理中断、异常,或者访问被保护的系统资源。

精髓: 为什么你的 C 语言程序崩溃了(段错误),整个 Ubuntu 系统不会死机?因为你的程序跑在 User 模式,被关在笼子里;而操作系统跑在 SVC 模式,掌握着生杀大权。

9.2 中断控制器

9.2.1 为什么不用查询,要用中断?

CPU 运行过程中,如何知道各类外设发生了某些不预期的事件,比如串口接收到了新数 据、USB 接口中插入了设备、按下了某个按键等。主要有以下两个方法。

  1. 查询方式:程序循环地查询各设备的状态并作出相应反应。它实现简单,常用在功 能相对单一的系统中,比如在一个温控系统中可以使用查询方式不断检测温度的变化。缺点 是占用 CPU 资源过高,不适用于多任务系统。
  2. 中断方式:当某事件发生时,硬件会设置某个寄存器;CPU 在每执行完一个指令时, 通过硬件查看这个寄存器,如果发现所关注的事件发生了,则中断当前程序流程,跳转到一 个固定的地址处理这事件,最后返回继续执行被中断的程序。它的实现相对复杂,但是效率 很高,是常用的方法

工程师视角:中断的核心价值是 「事件驱动」。CPU 不再主动轮询,而是被动响应。

中断的本质是「异步事件通知机制」
硬件负责可靠通知(寄存器状态 + 信号线),软件负责高效响应(最小化中断占用 + 合理拆分任务)。

9.2.2 通用中断处理链路(所有芯片通用):

image.png

外设 → 中断控制器 → CPU → 保存上下文 → 执行ISR → 恢复上下文
这是所有嵌入式中断体系的通用模型,无论ARM9还是Cortex-M33/RISC-V都遵循这个流程。

  1. 中断控制器汇集各类外设发出的中断信号,然后告诉 CPU。
  2. CPU 保存当前程序的运行环境(各个寄存器等),调用中断服务程序(ISR,Interrupt Service Routine)来处理这些中断。
  3. 在 ISR 中通过读取中断控制器、外设的相关寄存器来识别这是哪个中断,并进行相 应的处理。
  4. 清除中断:通过读写中断控制器和外设的相关寄存器来实现。
  5. 最后恢复被中断程序的运行环境(即上面保存的各个寄存器等),继续执行
中断处理流程(专业通用模型)
阶段一:中断信号产生与采集(外设 → 中断控制器)
外设事件(按键按下/串口收到数据/定时器溢出)
    │
    ▼
┌─────────────────────────────────┐
│ 外设内部逻辑                      │
│ • 状态寄存器置位 (Status Register) │
│ • 中断请求信号拉高 (IRQ Line ↑)    │
└────────┬────────────────────────┘
         │ 物理信号线 (IRQn)
         ▼
┌─────────────────────────────────┐
│ 中断控制器 (Interrupt Controller) │
│ 现代芯片多为 GIC (Generic Interrupt Controller) │
│                                 │
│ ① 中断采集 (Collect)             │
│    • SPI: 外设中断 (Shared Peripheral Interrupt) │
│    • PPI: 私有外设中断 (Private Peripheral Interrupt) │
│    • SGI: 软件触发中断 (Software Generated Interrupt) │
│                                 │
│ ② 中断 pending (待处理)          │
│    • 对应位在中断挂起寄存器置 1    │
│    • 例: GICD_ISPENDR[n]         │
│                                 │
│ ③ 中断屏蔽 (Mask)                │
│    • 检查中断使能寄存器 (GICD_ISENABLER) │
│    • 检查 CPU 全局中断开关 (CPSR.I/F) │
│                                 │
│ ④ 优先级仲裁 (Arbitration)       │
│    • 比较 Priority Register     │
│    • 支持抢占 (Preemption)       │
│                                 │
│ ⑤ 路由 (Routing)                │
│    • 指定目标 CPU 核 (Affinity)  │
│    • 指定安全世界 (Secure/Non-secure) │
└────────┬────────────────────────┘
         │ IRQ/FIQ 信号线
         ▼
🔹 阶段二:CPU 响应与上下文切换(硬件自动 + 软件协作)
CPU 检测到中断信号 (每指令周期采样)
    │
    ▼
┌─────────────────────────────────┐
│ 硬件自动执行 (不可跳过)            │
│ ① 完成当前指令 (Instruction Boundary) │
│ ② 保存关键上下文:                 │
│    • PC → LR_irq (返回地址)       │
│    • CPSR → SPSR_irq (状态寄存器)  │
│ ③ 切换处理器模式:                 │
│    • User → IRQ/FIQ Mode         │
│    • 切换银行寄存器 (Banked Registers) │
│ ④ 禁用同级中断:                   │
│    • CPSR.I = 1 (屏蔽 IRQ)        │
│ ⑤ 跳转到异常向量表:                │
│    • IRQ Vector: 0x18 (或 VTOR 配置) │
└────────┬────────────────────────┘
         │
         ▼
┌─────────────────────────────────┐
│ 软件执行 (异常入口汇编 + C 函数)    │
│ ① 保存完整上下文 (通用寄存器 R0-R12) │
│    • stmdb sp!, {r0-r12, lr}     │
│ ② 读取中断号:                     │
│    • GIC: GICC_IAR (Interrupt Acknowledge Register) │
│    • 提取 IRQ Number             │
│ ③ 清除中断挂起 (Acknowledge)     │
│    • 写 GICC_EOIR (End of Interrupt) │
│    • ⚠️ 顺序很重要: 先外设后控制器  │
│ ④ 调用注册的中断处理函数 (Handler) │
│    • Linux: request_irq() 注册的函数 │
│    • RTOS: ISR 回调函数           │
└────────┬────────────────────────┘
         │
         ▼
┌─────────────────────────────────┐
│ 中断返回 (硬件 + 软件协作)          │
│ ① 恢复通用寄存器:                 │
│    • ldmia sp!, {r0-r12, pc}^    │
│    • ^ 表示同时恢复 CPSR = SPSR  │
│ ② 硬件自动:                      │
│    • LR_irq → PC (返回断点)       │
│    • SPSR_irq → CPSR (恢复状态)   │
│    • 重新使能中断 (CPSR.I = 0)    │
└─────────────────────────────────┘

9.2.3 软件流程:中断服务程序 (ISR) 要做什么?

标准 ISR 执行四步曲:
  1. 保护现场 (Save Context)

    • 为什么:中断可能发生在任何指令执行过程中,寄存器里的数据很重要。
    • 怎么做:把 R0~R12, LR 等压栈(文中汇编 stmdb sp! 就是在做这个)。
    • 现代:内核入口代码自动完成。
  2. 识别中断源 (Identify)

    • 为什么:可能多个设备共享中断。
    • 怎么做:读中断控制器的状态寄存器(文中 INTPNDINTOFFSET)。
  3. 处理业务 (Handle)

    • 怎么做:读串口数据、清零按键标志、翻转 LED 等。
    • 原则越快越好! 中断里不能睡大觉(不能延时、不能等待锁)。
  4. 清除中断 (Ack/Clear)最关键!

    • 为什么:如果不告诉硬件「我处理完了」,硬件会认为事件还在,会无限重复进入中断,导致系统死机。
    • 怎么做:文中提到的 INTPND = INTPND(写 1 清零)。
    • 顺序:通常先清外设中断,再清中断控制器中断(具体看芯片手册)。
  5. 恢复现场 (Restore Context)

    • 怎么做:出栈,恢复寄存器,返回断点继续执行(文中 ldmia sp!, {r0-r12, pc}^

第十章 系统时钟和定时器

10.1 系统时钟

通用时钟树模型

外部晶振 (12MHz/24MHz 唯一物理时钟源 )


    
    
┌─────────────────┐
 PLL (频率合成器)   核心!把低频晶振倍频到高频
  输入: Fin      
  输出: Fout = Fin × M / (P × 2^S) 
  作用: 产生系统主频               
└────────┬────────┘
         
         
┌─────────────────┐
 时钟分频器(Divider)         按需分配不同频率
  FCLK: CPU    
  HCLK: 总线用   
  PCLK: 外设用   
  分频比可配置    
└────────┬────────┘
         
         
┌─────────────────┐
 时钟门控 (Gate)    省电关键!
  不用的外设时钟关掉 
  动态功耗管理     
└─────────────────┘
总线示意:
┌─────────┐      ┌─────────────────────────────┐      ┌─────────┐
│   CPU   │◄────►│        AHB 高速总线          │◄────►│  内存   │
│ (400MHz)│      │  (Advanced High-performance  │      │(100MHz) │
└─────────┘      │          Bus)                │      └─────────┘
                 │  • 32/64位宽(一次传更多数据)  │
                 │  • 流水线传输                  │
                 │  • 多主设备仲裁                │
                 └─────────────┬───────────────┘
                               │
                 ┌─────────────┴───────────────┐
                 │        APB 桥接器            │  ← 速度转换 + 协议转换
                 │   (AHB-to-APB Bridge)        │
                 └─────────────┬───────────────┘
                               │
                 ┌─────────────┴───────────────┐
                 │        APB 低速总线          │
                 │  (Advanced Peripheral Bus)   │
                 │  • 16/32位宽                 │
                 │  • 简单协议,省电             │
                 │  • 适合慢速设备               │
                 └──────┬────────┬────────┬────┘
                        │        │        │
                    ┌────┘   ┌────┘   ┌────┘
                    ↓        ↓        ↓
                ┌──────┐ ┌──────┐ ┌──────┐
                │ UART │ │ Timer│ │  GPIO│
                │(50MHz)│ │(50MHz)│ │(50MHz)│
                └──────┘ └──────┘ └──────┘

📌 一句话:时钟树就是「频率分配网络」,只需要知道「我要给某个外设多少频率」,具体路由由硬件/框架完成。

9.2 定时器和PWM

核心思想:时钟树决定「频率从哪来」,定时器决定「时间怎么数」,PWM决定「波形怎么出」

9.2.1 定时器(Timer)

┌─────────────────────────────────────────┐
│ 定时器核心流水线(5步)                   │
├─────────────────────────────────────────┤
│ ① 时钟源选择                             │
│    • 通常来自PCLK或独立低速晶振           │
│    • 现代芯片支持多路时钟源动态切换        │
│                                          │
│ ② 预分频 (Prescaler)                     │
│    • 8/16位寄存器,把高频时钟降下来        │
│    • 公式: f_pre = f_in / (prescale+1)  │
│                                          │
│ ③ 主分频 (Divider)                       │
│    • 固定分频:2/4/8/16倍                 │
│    • 公式: f_timer = f_pre / divider    │
│                                          │
│ ④ 计数 + 比较 (Counter + Compare)        │
│    • TCNT: 递减计数器,每个时钟周期 -1     │
│    • TCMP: 比较值,相等时触发事件          │
│    • 事件: 输出翻转 / 产生中断 / 触发DMA  │
│                                          │
│ ⑤ 自动重载 (Auto-reload)                 │
│    • 计数到0后,自动从重载寄存器恢复       │
│    • 实现周期性定时,无需软件干预          │
└─────────────────────────────────────────┘
计数 + 比较 (Counter + Compare)
┌─────────────────────────────────────────────────────────┐
│              时钟输入(来自时钟树,如 100MHz)              │
│                    ↓                                      │
│              ┌─────────┐                                 │
│              │  预分频器 │  ← 可选,降低计数频率            │
│              │  /N     │                                 │
│              └────┬────┘                                 │
│                   ↓                                       │
│              ┌─────────┐                                 │
│              │ Counter │  ← 核心:每个时钟周期 +1           │
│              │  计数器  │    (通常 16/32/64 位,可上/下计数) │
│              │   0→N   │                                 │
│              └────┬────┘                                 │
│                   │                                       │
│                   ↓ 比较                                  │
│              ┌─────────┐                                 │
│              │ Compare │  ← 匹配值(软件写入)              │
│              │  寄存器  │                                 │
│              │   = M   │                                 │
│              └────┬────┘                                 │
│                   │                                       │
│              Counter == Compare?                          │
│                   │                                       │
│              ┌────┴────┐                                 │
│              │  是 → 触发事件:                            │
│              │  • 产生中断(IRQ)                           │
│              │  • 翻转 GPIO(PWM 输出)                     │
│              │  • 启动 ADC 采样                            │
│              │  • 重置 Counter(周期性)或停止(单次)       │
│              │  • 加载新的 Compare 值(链式触发)          │
│              └─────────┘                                 │
└─────────────────────────────────────────────────────────┘

模式 A:单次触发(One-shot)
Counter:  012 → ... → 9991000(Compare) → 触发 → 停止
          ↑_________________________________________|
                          10ms 后执行一次动作

应用:延时启动、超时检测、单次采样



模式 B:周期性(Periodic / Auto-reload)
Counter:  0 → ... → 9991000(Compare) → 触发 → 自动重置为 0
                              ↓                    ↓
                           翻转 PWM              继续计数
                           触发中断              循环往复
                           
          ┌────┐      ┌────┐      ┌────┐
          │    │      │    │      │    │
──────┘    └────┘    └────┘    └────┘────
          <─ 1ms ─><─ 1ms ─><─ 1ms ─>

应用:系统 tick、PWM 波形、定时采样

定时器工作频率 = 时钟源 / (预分频+1) / 主分频

定时周期(秒) = (预分频+1) × 主分频 × 计数值 / 时钟源频率

9.2.2 PWM定时器:用「数字开关」模拟「模拟信号」

PWM通用原理
┌─────────────────────────────────────────┐
│ PWM = Pulse Width Modulation(脉冲宽度调制)│
├─────────────────────────────────────────┤
│ 核心思想:固定周期,改变高电平时间 → 改变平均电压  │
│                                          │
│ 周期 (Period) = 高电平 + 低电平时间        │
│ 占空比 (Duty) = 高电平时间 / 周期 × 100%  │
│                                          │
│ 输出波形示例(周期1ms,占空比30%):        │
│                                          │
│ 高电平 ████████░░░░░░░░░░░░░░░░░░░░ 300μs  │
│ 低电平 ░░░░░░░░░░███████████████████ 700μs  │
│         ↑                               ↑  │
│       周期开始                         周期结束│
│                                          │
│ 应用:                                  │
│ • LED亮度调节(0~100%无级调光)           │
│ • 电机速度控制(直流/步进/伺服)          │
│ • 蜂鸣器音调(频率+占空比控制音量)        │
│ • 电源管理(DC-DC控制器反馈)             │
└─────────────────────────────────────────┘
PWM 的本质:双 Compare 机制
┌─────────────────────────────────────────────────────────┐
│                    双 Compare 架构                        │
├─────────────────────────────────────────────────────────┤
│                                                         │
│   Counter:  0 ─────────────────────────────────────→   │
│                    ↑                    ↑               │
│                    │                    │               │
│              Compare A              Compare B            │
│             (Duty 点)              (Period 点)            │
│                    │                    │               │
│                    ↓                    ↓               │
│              输出翻转 ↑              输出翻转 ↓ + 重置    │
│                                                         │
│   波形生成过程:                                          │
│                                                         │
│   时刻:    0        D        P        D        P         │
│            │<─────>|<──────>|<─────>|<──────>|          │
│            │        │        │        │        │         │
│   Counter: 0───────D───────P───────D───────P───────     │
│            ↑       ↑       ↑       ↑       ↑            │
│            │       │       │       │       │            │
│   输出:    ┌───────┐       ┌───────┐       ┌───────     │
│            │       │       │       │       │            │
│        ────┘       └───────┘       └───────┘            │
│            ↑       ↑       ↑       ↑                    │
│            └高电平─┘       └低电平─┘                     │
│                                                         │
│   关键动作:                                              │
│   • 0 时刻:Counter 启动,输出强制拉高(或拉低,可配置)    │
│   • 到达 Compare A (D):输出翻转 → 变低                   │
│   • 到达 Compare B (P):输出翻转 → 变高 + Counter 清零    │
│   • 循环往复                                              │
│                                                         │
└─────────────────────────────────────────────────────────┘
  1. 分离"时间流逝"与"事件触发"
    Counter:客观时间的度量(与软件无关)
    Compare:主观关注的时刻(软件配置)
  2. 硬件确定性 vs 软件灵活性
    硬件保证:Compare 匹配在时钟周期级精度
    软件负责:决定 Compare 值和响应动作

9.3 WATCHDOG 喂狗机制

Watchdog 的本质: 它也是一个倒数定时器。但它减到 0 时,不会触发普通中断,而是直接拉低芯片的 RESET 引脚,强制整个系统硬重启!

核心机制
┌─────────────────────────────────────────────────────────┐
│                    Watchdog 架构                          │
├─────────────────────────────────────────────────────────┤
│                                                         │
│   独立时钟源(关键!)                                     │
│   ↓                                                     │
│   ┌─────────┐    ┌─────────┐    ┌─────────┐             │
│   │  Counter │ ← │  预分频  │ ← │  OSC/RTC │             │
│   │  递减计数 │    │         │    │  独立晶振 │             │
│   │   N→0   │    └─────────┘    └─────────┘             │
│   └────┬────┘                                           │
│        │                                                │
│        ↓ 计数到 0 超时时间=计数器从「初始值」减到「0」的时间                                        │
│   ┌─────────┐                                           │
│   │  超时?  │── 是 ──→ 触发复位/中断                    │
│   │         │                                           │
│   │  喂狗?  │── 是 ──→ 重载计数器,继续运行             │
│   │  (Reload)│                                           │
│   └─────────┘                                           │
│                                                  │
│   关键特性:                                              │
│   • 独立时钟:主 CPU 死机时仍能计数                        │
│   • 不可屏蔽:一旦启动,软件无法禁用(部分设计)              │
│   • 窗口机制:喂狗太早或太晚都触发复位(高级设计)            │
│                                                         │
└─────────────────────────────────────────────────────────┘
两种工作模式
模式 1:超时复位(Reset Mode)⭐ 核心功能
┌─────────────────────────────────────────┐
│ 流程:                                  │
│ ① 启动看门狗                            │
│ ② 程序正常运行 → 定期喂狗               │
│ ③ 程序死机/跑飞 → 无法喂狗              │
│ ④ 计数器归零 → 硬件复位信号触发          │
│ ⑤ 系统重启 → 恢复正常运行               │
└─────────────────────────────────────────┘

✅ 应用场景:
• 无人值守设备(基站、监控)
• 安全关键系统(汽车刹车控制)
• 死机后必须自愈的场景

⚠️ 注意:
• 复位后系统会丢失当前数据(RAM 内容清空)
• 需配合日志记录复位原因(看门狗复位标志位)
模式 2:超时中断(Interrupt Mode)🔔 预警功能
┌─────────────────────────────────────────┐
│ 流程:                                  │
│ ① 计数器归零前 → 先触发中断              │
│ ② 中断服务程序尝试恢复系统               │
│    • 打印错误日志                        │
│    • 重启关键任务                        │
│    • 上报云端                            │
│ ③ 如果恢复失败 → 继续计数 → 触发复位     │
└─────────────────────────────────────────┘

✅ 应用场景:
• 需要保存现场数据的场景
• 尝试软件自愈,避免硬重启
• 调试阶段定位死机原因

💡 现代实现:
• 两级看门狗:第一级中断警告,第二级复位
• Linux 内核:watchdog_ping() 失败后先 panic() 再重启
模式对比表
特性超时复位超时中断
触发条件计数器归零计数器归零(或预警告值)
动作硬件复位信号触发 IRQ 中断
可恢复性❌ 不可恢复(重启)✅ 可尝试软件恢复
用途最终保护预警/调试/日志
配置位WTCON[0] (Reset Enable)WTCON[1] (Interrupt Enable)

第11章 通用异步收发器 UART (Universal Asynchronous Receiver/Transmitter)

并行数据(Parallel) (老技术,逐渐淘汰)

  • 多根线同时传多个位
  • CPU与内存总线(内部短距离仍用并行)

串行数据(Serial) (现代主流)

  • 一根线一位一位传
  • USB(通用串行总线)
  • SATA(串口硬盘,取代IDE)
  • PCIe(串口扩展总线,取代PCI)
  • 以太网(网线)
  • I2C、SPI、UART、CAN(嵌入式常用)
  • HDMI、DisplayPort(视频接口)

它用来传输串行数据:

  1. 发送数据时,CPU将并行数据写入UART,UART按照一定的格式在一根电 线上串行发出;
  2. 接收数据时,UART检测另一根电线上的信号,将串行收集放在缓冲区中, CPU即可读取UART获得这些数据。

11.1、 UART 协议物理层:没有“时钟线”的默契

在数字电路中,通常需要一根“时钟线(Clock)”来告诉对方什么时候读数据(比如 I2C 和 SPI)。但 UART 只有两根线:TX(发)RX(收) 。UART 之所以叫“异步(Asynchronous)”,是因为发送方和接收方之间没有共同的时钟线。 为了能对上节拍,双方必须提前约定好“潜规则(波特率)”,这就是所谓的 8N1 标准(最常用):

  • 空闲状态 (Idle):高电平 (1) 为什么不设为 0?因为高电平代表电路连通。如果线断了,电平掉到 0,接收方能立刻感应到异常
  • 起始位 (Start Bit): 逻辑 0。当 TX 引脚从 1 掉到 0 时,接收方的时钟立刻被唤醒,开始按照预定的波特率倒计时采样。
  • 数据位 (Data Bits): 通常是 8 位(正好一个字节)。
  • 校验位 (Parity Bit): 选配(N 代表 None,即不使用)。用于检查传输是否出错。
  • 停止位 (Stop Bit): 逻辑 1。代表一个字节传输结束。

波特率 (Baud Rate): 每秒传输的位数。常见的有 1152009600

### 物理连接(最小系统)
CPU (TX) ────────────────> 设备 (RX)
CPU (RX) <──────────────── 设备 (TX)
CPU (GND) ─────────────── 设备 (GND)

⚠️ 关键:TX 接 RX,RX 接 TX(交叉连接),共地(GND)必须连通。

物理电平:TTL vs RS-232

标准逻辑 1逻辑 0用途
TTL3.3V/5V0V芯片间通信(CPU 到模块)
RS232-3~-12V+3~+12VPC 串口(需要电平转换芯片)
USB差分信号差分信号现代 PC 主流(需 USB 转串口模块)

💡 工程经验:开发板通常是 TTL 电平,连接电脑需要 USB 转 TTL 模块(如 CH340/CP2102),直接接 RS232 会烧芯片

11.2 UART 控制器架构

┌─────────────────────────────────────────┐
│ UART 控制器内部结构                      │
├─────────────────────────────────────────┤
│                                          │
│  发送方向 (TX):                          │
│  CPU → 发送 FIFO → 发送移位器 → TX 引脚   │
│                                          │
│  接收方向 (RX):                          │
│  RX 引脚 → 接收移位器 → 接收 FIFO → CPU   │
│                                          │
│  关键组件:                              │
│  • 波特率发生器:根据系统时钟分频产生采样时钟│
│  • FIFO 缓冲区:缓解 CPU 压力,减少中断次数  │
│  • 控制逻辑:中断/DMA/流控管理            │
└─────────────────────────────────────────┘
### 1.发送流程 (TX)

1. CPU 检查发送 FIFO 是否满
   • 满:等待(查询)或 停止写入(中断/DMA)
   • 空:继续

2. CPU 写入数据到发送保持寄存器(THR/FIFO)

3. 硬件自动处理:
   • 添加起始位、停止位、校验位
   • 移位器串行输出到 TX 引脚

4. 发送完成中断(可选):
   • FIFO 空或移位器空时触发,通知 CPU 发下一个
### 2. 接收流程 (RX)
1. 硬件检测 RX 引脚起始位

2. 按波特率采样,串行转并行

3. 存入接收 FIFO

4. 接收中断触发:
   • FIFO 数据达到阈值 或 超时
   • CPU 读取数据寄存器(RDR/FIFO)

11.3 三种工作模式对比

1. 查询模式 (Polling)

  • 原理:CPU 循环检查状态寄存器(while(!TX_READY)
  • 优点:简单,无需中断配置
  • 缺点占用 CPU 100% ,无法处理其他任务
  • 适用:早期裸机、极简系统、调试打印(printf 底层)

2. 中断模式 (Interrupt) ⭐ 主流

  • 原理:数据准备好后触发中断,CPU 在中断里读写
  • 优点:CPU 利用率高,实时性好
  • 缺点:大量数据时中断频繁,上下文切换开销大
  • 适用:交互式命令、中等数据量、Linux 控制台

3. DMA 模式 (Direct Memory Access)

  • 原理:DMA 控制器直接在内存和 UART FIFO 间搬运数据
  • 优点CPU 完全不参与,适合大数据流
  • 缺点:配置复杂,延迟略高
  • 适用:高速日志、文件传输、GPS 数据流