首页 / 资讯中心 / 文章详情

STM32寄存器编程实战:中断、定时器、ADC与串口排错指南

STM32寄存器编程实战:中断、定时器、ADC与串口排错指南 ★ FEATURED ARTICLE
很多人以为会写几句库里函数调用就算会 STM32 了结果一到产品现场就抓瞎串口偶尔丢字节、定时器捕获频率跳来跳去、ADC 切通道后采到一堆废数。原因其实很简单库函数帮你把寄存器操作藏得太深了一旦出问题你连去哪个地址看一眼都不知道。寄存器编程不是炫技它是排查问题时的最后一道保险。这章我就用大白话把 STM32 寄存器手册里最常用的几个模块讲透重点放在中断、定时器、ADC、串口和几个容易踩坑的外设寄存器上适合已经在用标准库或 HAL 库、但想往底层再走一步的朋友。1. 先聊清楚为什么“寄存器版”还能打1.1 三层抽象下寄存器才是唯一的真现在 STM32 开发的主流方式大体分三层第一层是 CubeMX 生成的 HAL 库点几下鼠标就能外设初始化第二层是标准外设库函数名清清楚楚适合学习第三层就是直接操作寄存器也是传统“寄存器版”玩家天天干的事。很多新手觉得寄存器版是古董其实这是个误解。不管上面包了多少层库最终芯片能看到的只有寄存器的 0 和 1。库函数怎么工作本质上就是往地址空间里写特定数值。HAL 库里的 HAL_GPIO_WritePin 干的事无非是操作 ODR 或 BSRR。寄存器版的优势不是“显得厉害”而是让你对芯片行为有精确到位的预判尤其在对性能要求苛刻、要用到某些怪异外设特性、或者芯片发生死机复位后需要快速排查的场景寄存器方式往往比一层层追库函数源码更直接。另外我不建议一上来就全寄存器最好先写一阵子标准库再对照数据手册自己重写一遍。当你把 GPIO、串口、定时器这些常用外设用寄存器重写一遍之后再看 HAL 库生成的初始化代码基本就是“翻译成人话”了这时候调试问题的能力会明显上一个台阶。1.2 这一章到底讲什么适合谁读标题里写了“第三章”按我写系列的习惯前两章会先讲整体寻址思路和 GPIO、串口这类最基础的模块这一章就往进阶走重点覆盖四个方向中断与优先级、定时器捕获与 PWM、ADC 多通道切换、通信模块的寄存器排错。阅读本章前建议你已经清楚了至少一个 GPIO 口的开启时钟、配置输入输出、设置电平等操作知道 RCC 是什么也大概见过 R32位寄存器映射的写法。如果这些还比较生直接读本章会很吃力建议先把 GPIO 寄存器部分翻熟再回来。1.3 从“读手册”到“读寄存器”的思路转变很多人拿着参考手册不知道怎么用就从头第一页开始啃。我的习惯是倒着用先定外设再看寄存器的功能描述最后再看框图的整体流向。比如你想用 TIM2 做输入捕获直接翻到 TIM2 寄存器描述找捕获/比较寄存器 CCRx、状态寄存器 SR、控制寄存器 CR1/CR2再反推时钟源怎么选择这样最快。2. 第三章必过的基础门时钟与地址2.1 把脑子里的映射表建立起来STM32 的寄存器本质上就是一块内存映射地址。以 STM32F103 为例GPIOA 的基地址是 0x40010800GPIOB 是 0x40010C00串口1 的基地址是 0x40013800。每个外设基地址加上偏移量就对应到具体的寄存器。不少人问我总不能每个偏移量都死记吧我的办法是只记基地址偏移量靠参考手册查。比如 GPIOA 的配置寄存器 CRL 偏移是 0x00CRH 偏移是 0x04IDR 输入数据寄存器偏移 0x08ODR 输出数据寄存器偏移 0x0CBSRR 偏移 0x10。实际写代码时多用宏定义理清楚“基地址偏移量”的思路就足够日常使用。2.2 RCC 时钟门控忘记开时钟的经典症状寄存器开发最常见的第一坑寄存器地址明明写对了写进去却没有任何效果。九成原因是这个外设的时钟根本没打开。STM32 为了省电几乎所有外设的时钟默认都是关闭的。你要用 GPIOA得先把 RCC-APB2ENR 里对应位打开要用串口1除了 GPIOA 的时钟还得打开 USART1 的时钟要用 ADC1则要开 APB2ENR 里的 ADC1 使能位还要记得打开 ADC 的时钟分频配置。我刚开始写寄存器代码时在这里卡了一个下午。GPIO 配置函数翻来覆去没问题但点灯就是不亮。后来打开调试器读 RCC-APB2ENR才发现对应位是 0。从那以后我形成一个习惯任何一个外设初始化先写一行开时钟再写外设配置顺序固定下来就不会漏。2.3 GPIO 复用功能的寄存器配置寄存器版配置复用功能比 HAL 库多一步但一点都不复杂。STM32F1 的 GPIO 配置主要是 CRL/CRH 里的 CNF 和 MODE 位。MODE 设置输入还是输出以及输出速度CNF 设置模拟输入、浮空输入、推挽输出、开漏输出、复用推挽这些模式。比如串口 TX 引脚要配置成复用推挽输出RX 引脚配置成浮空输入或上拉输入这个细节写错了串口大概率只能发不能收。到了 STM32F4 系列情况稍有变化GPIO 复用功能要额外写 AFRL/AFRH 寄存器选择该引脚复用到的具体外设功能。比如 PA9 做 USART1_TXAFR 里的值不是随便给的不同的复用索引对应不同外设。操作时先打开 GPIO 时钟再配置 MODER、OTYPER、OSPEEDR、PUPDR最后把复用索引写进 AFR。很多人用 F4 寄存器版的时候最常忘记的就是最后一步 AFR导致功能完全不对。调试时可以用调试器读一下 AFR 寄存器确认数值对不对。3. 抢占与优先级中断部分的寄存器操作3.1 NVIC 和中断向量表中断这件事光会写中断服务函数还不够你得知道是谁在管理优先级、谁在响应中断。Cortex-M3 内核里有个嵌套向量中断控制器叫 NVIC它就是所有中断入口的大总管。你要使能一个外设中断需要在外设自己的寄存器里打开中断使能位比如串口接收中断要置 USART_CR1 的 RXNEIE同时还要在 NVIC 里使能对应的 IRQ 通道。NVIC 相关寄存器实际上是一组地址固定的内存映射寄存器名字形如 NVIC_ISER、NVIC_ICER、NVIC_ISPR、NVIC_IPR。ISER 就是中断使能寄存器写 1 使能对应编号的中断。IPR 是优先级寄存器每个字节对应一个中断通道的优先级。日常编程中很少有人手写 NVIC 寄存器几乎都直接用 CMSIS 提供的 NVIC_EnableIRQ、NVIC_SetPriority 这些函数。它们本质上也是操作上述寄存器只是帮你算好了位移。优先级设置有个最常见的坑STM32F1 的优先级分为抢占优先级和子优先级配置 NVIC_PriorityGroupConfig 后抢占优先级决定“正在执行高优先级中断时能不能被另一个中断打断”子优先级决定“抢占优先级相同的时候谁先执行”。很多人误以为优先级数值小的占优先级高容易搞反。注意 STM32 里数字越小优先级越高。3.2 SysTick 定时器延时函数卡死的元凶之一很多人在做延时函数的时候碰到过“卡死在延时里”的诡异现象尤其是用 HAL_Delay 或者自写 delay 时越用越不对劲。SysTick 就是那个常被忽视的 24 位倒计时定时器它挂在内核上不需要外部时钟。寄存器版延时核心就是操作 SysTick 的控制寄存器 CTRL、重装载值寄存器 LOAD 和当前值寄存器 VAL。自写阻塞式延时最容易出的问题有两个一个是忘了重装 LOAD 值导致第一次延时正常第二次延时时间变短另一个是临界区里关中断了但 SysTick 中断迟迟得不到处理倒计时变成 0 后控制位没被正确清除程序就停在等待标志的循环里。建议寄存器版写 SysTick 延时的时候始终用“读 CTRL 的 COUNTFLAG 位清标志”配合手动写 VAL 清零并且不要把 SysTick 优先级设得比某些外设还低否则在中断风暴里系统响应会明显变慢。3.3 中断服务函数里的脏活中断服务函数写不好即使初始化全对也照样表现得很怪。一条铁律中断服务函数里不要做耗时操作更不要用非重入函数。串口接收中断里做 GBK 转 UTF8 这种字节流处理时间稍长就会导致 RXNE 标志没及时清除后续字节进不来。哪怕是缓冲区拷贝也要尽量轻量把重活放到主循环里处理。进入中断函数后不少外设需要手动清标志位。比如外部中断 EXTI 的挂起寄存器 PR你在中断里不写 1 去清除退出中断后同一个中断会再次进来这就是明明只按了一次按键却触发多次的原因。串口的 ORE 溢出错误也需要及时读 SR 再读 DR 才能清除否则中断会一直重复触发。这些“清标志”的操作是寄存器手册里最容易被新手忽略的细节。4. 定时器寄存器PWM、输入捕获、编码器三个实战4.1 定时器基本结构六个关键寄存器通用定时器 TIMx 是 STM32 里最灵活的模块之一。它的内部结构可以拆成时钟源、预分频器、计数器、比较/捕获寄存器、自动重装载寄存器这几块。寄存器版最常操作的就是这几个CNT当前计数值读它你能知道定时器走到哪了PSC预分频系数用于把输入时钟降到需要的频率ARR自动重装载值决定计数周期CR1控制寄存器控制计数器使能、方向、对齐方式SR状态寄存器查看更新事件、捕获事件标志CCRx捕获/比较寄存器输入捕获或输出比较的核心寄存器配置定时器的常规顺序是先开时钟然后配置 PSC 和 ARR再配置 CR1 的计数方向和对齐模式接着根据需要配置输出比较或输入捕获模式最后把对应的中断或 DMA 打开。每个配置都对应具体位的操作。比如 TIM2 的向上计数 PWM 输出就是设置 CR1 的 DIR0每来一个时钟脉冲 CNT 加 1到 ARR 值清零并产生更新事件。ARR 和 PSC 的选值就是大家常见的“算定时器频率”的过程。STM32F103 的 TIM2 挂在 APB1 上如果 APB1 分频系数不是 1内部时钟会是 APB1 的两倍。举例系统时钟 72MHzAPB1 预分频为 2TIMx 的输入时钟实际是 72MHz不是 36MHz。很多初学者在这里算错建议看系统时钟框图不要拍脑袋。4.2 用定时器做输入捕获测频率含超声波测距思路输入捕获的原理不难把外部信号接到定时器的某个输入通道上信号跳变沿到来时计数器 CNT 的当前值会被复制到 CCRx。连续捕获两次算一下差值再除以时钟频率就能算出两次跳变的时间间隔也就是信号周期。参考手册里输入捕获配置有一项叫滤波器和极性选择CCER 寄存器控制上升沿还是下降沿捕获CCMR 寄存器控制映射关系和滤波采样。很多新手做输入捕获测频率发现数值在某一两个频率上反复跳不是因为定时器算错了而是没用输入滤波导致噪声信号触发捕获。解决方法是把 CCMR 里的 IC1F 滤波值合理配置比如采样时钟除以 8然后连续采样 4 次都确认了才判定为有效跳变。超声波测距也会用到输入捕获比如 HC-SR04 模块把回波时间通过一个高电平脉冲告诉你你用定时器捕获回波引脚上升沿和下降沿算高电平时间再乘声速除以 2就是距离。注意声速随温度变化如果要做到更准最好加温度补偿25 度时大概 346m/s冬天 0 度只有 331m/s。寄存器版做这个功能不算难核心就是配置好单次捕获、禁止反转极性和掩码无关事件。4.3 PWM 输出控制伺服电机和步进电机的区别输出比较模式最常见的用途是产生 PWM。以 TIM2 的 CH1 为例配置 CCMR1 的 OC1M 为 110PWM 模式 1再设置 CCER 的 CC1E1 使能输出然后 CCR1 写占空比对应值。ARR 决定周期CCR1 决定高电平时间。很多人把 PWM 波形的“频率”和“占空比”混在一起寄存器里分得很清ARR 影响周期CCR1 影响占空比PSC 再细分时钟。说到真实项目伺服电机和步进电机是两类最常见对象。伺服电机通常接收 50Hz 的 PWM 信号通过脉宽范围控制角度比如 0.5ms 对应 0 度2.5ms 对应 180 度。这种对 PWM 频率要求不高但对脉冲宽度的稳定性要求高。上电瞬间如果 PWM 输出一个异常宽脉冲伺服电机容易猛跳一下所以要先用比较值预装载功能让 CCR 更新和更新事件同步而不是立刻更新。寄存器里就是 CR1 的 ARPE 位和 CCER 的预装载使能位的配合。步进电机又是另一个思路。它需要的不是变化占空比而是确定个数的脉冲序列。驱动器每收到一个脉冲电机转一步。所以你要做的不是 PWM而是 GPIO 翻转加精确延时或者用定时器输出比较中断来计数脉冲个数。五线四相步进电机那种老式玩法还需要手动控制四相通断顺序这就更依赖 GPIO 寄存器的快速写操作用 BSRR 置位/复位会比 ODR 整套读改写更快更安全。5. ADC 寄存器切换通道与连续采集5.1 ADC 规则组和注入组STM32 的 ADC 有两种转换通道组规则组和注入组。规则组就是普通多通道轮流转换的意思但每次转换结果只有一个数据寄存器 DR存的是当前最新结果。注入组类似“插入的转换”优先级更高结果可以保存到单独的注入数据寄存器里适合需要紧急采样的场景。理解这个结构后也就理解了为什么那么多人在多通道 ADC 上头疼规则组多通道按顺序转换但你只从 DR 读结果如果没注意转换顺序每次读到的数据并不是你以为的那个通道。所以我一般建议用 ADC 的 DMA 功能让每个通道的转换结果自动搬运到内存的不同变量里而不是在主循环里面不断切换通道、手动读 DR。这样既减少 CPU 开销也不容易读串数据。5.2 多通道切换热词里“adc切换通道”是怎么回事聊到“ADC 切换通道”这是寄存器开发特别典型的问题。ADC 的规则组序列寄存器 SQR1/SQR2/SQR3 定义了转换顺序可以理解为一张“转几号通道”的列表。比如你配置 SQ1 是通道 0SQ2 是通道 1那么启动一次规则组转换后ADC 会先采通道 0再采通道 1。如果你需要在运行过程中动态改通道就得重新配置 SQR3 里对应序列位的值。改完以后还要注意转换触发方式如果是软件触发需要重新启动转换。有人改完通道却发现 DR 里的数据还是旧通道的多半是没有清 EOC 标志也没有等待新的转换完成标志。我的排查步骤是先读 SR 看 EOC 有没有置位再读 DR顺序不要反。凡是用寄存器手动切 ADC 通道的地方这个顺序都值得写进代码注释里。5.3 读取稳定性和误差处理ADC 的稳定性问题比想象中多。第一个是参考电压噪声ADC 本身精度也就 12 位如果你直接拿开关电源给 MCU 供电噪声很容易进到采样值里。寄存器配置里有一个采样时间位 SMPx通道的采样时间越长内部采样电容充电越充分采到的值越稳定。条件允许时把采样时间调到最大能明显减少抖动。另一个常见问题是阻抗问题。信号源内阻太高ADC 内部采样电容一接入电压就会被拉低。处理方式是加运放跟随器或者降低信号源阻抗。寄存器层面能做的调整有限但采样时间选长一点在很多场景下能缓解。还有一个零漂问题。STM32 的 ADC 有校准功能上电以后建议先做一次校准再开始转换。标准外设库里有 ADC_SoftwareStartCalib寄存器版就是操作 ADC_CR2 的 CAL 位连续转换模式不要在校准前打开。这个步骤很多人直接跳过结果读到的值整体偏移几十个 LSB排查到心态爆炸。6. 通信接口寄存器的坑UART、CAN、SWD 与 JTAG6.1 UART 状态寄存器和 printf 重定向串口是调试的命根子。UART 寄存器版核心就是 USART_SR、USART_DR、USART_BRR、USART_CR1 这几个。状态寄存器 SR 里的 TXE 表示发送数据寄存器空TC 表示发送完成RXNE 表示接收数据寄存器非空。写发送数据前要先等 TXE 置 1再去写 DR读接收数据前先等 RXNE 置 1再去读 DR。很多人问 printf 重定向到串口怎么用寄存器实现。本质就是重写一个 fputc 函数或者用现成的半主机模式消除然后把底层发送函数替换成自己的寄存器发送逻辑。最要命的坑是重定向后没有处理串口中断优先级和缓冲区高频打印时 CPU 卡在循环里等 TXE外设中断全部被拖住。如果你要打大量日志建议开一个简单的环形缓冲区底层在中断里搬数据主循环里只把数据丢进缓冲区发送完成中断里再取出下一个字节。还有人会遇到串口乱码。优先排查波特率寄存器 BRR 的计算。STM32 的 BRR 是根据 PCLK 频率算的F1 系列的 USART1 挂在 APB2 上USART2/3 挂在 APB1 上。如果你系统时钟配置变了却忘了改 BRR串口直接废。用调试器读一下 BRR再对照计算器算一遍能快速定位。6.2 CAN 通信突然连不上的排查CAN 通信的坑和串口完全不是一个路子。CAN 是差分总线跑的是报文帧不是简单数据流。寄存器版 CAN 初始化要做的事情比 UART 多很多波特率分频、时间段 1/2、同步跳转宽度、滤波器、中断使能。CAN 突然连不上我遇到最多的情况是总线位定时配置不对。有的工程师只改了分频没改时间段导致采样点在错误位置。CAN 的理想采样点通常在 87.5% 左右。比如位时间分 16 个时间量子那就把时间段 1 设成 13 个量子时间段 2 设成 2 个量子。很多人直接套网上的配置把采样点设到 50% 也能小范围通信但总线长了、节点多了就容易掉线。另一种常见问题是 node 进入 BusOff 后没有及时恢复。寄存器里 CAN_MCR 的 ABOM 位决定是否自动离线管理如果你的应用需要 CAN 节点自己从 BusOff 恢复这个位要记得置 1。如果工程里出现“连不上”的故障第一步先读 CAN_ESR 看看是不是 BusOff再读 CAN_TSR 看发送邮箱是否卡死。用寄存器方式排查会非常快。6.3 禁用 JTAG 之后怎么调试STM32F1 的调试口默认是 JTAG 和 SWD 都开。有时候为了复用 JTAG 对应的引脚PA13/PA14/PA15、PB3/PB4会在 GPIO 配置里开启 AFIO 的重映射功能把 JTAG 关掉只留 SWD。如果你彻底把 SWD 也关了下次就无法用调试器连接了这是寄存器开发特别容易捅的娄子。我曾经在配置中把 AFIO_MAPR 里的 SWJ_CFG 配置成完全关闭调试口结果固件一下载调试器再也没法连上。芯片没坏但你只能通过 BOOT0 拉高进入 ISP 模式用串口下载重新烧一个固件才能恢复。所以除非你确定已经不需要在线调试否则一定要保留 SWD 口。SWD 只需要 PA13SWDIO和 PA14SWCLK比 JTAG 省两个引脚适合引脚紧张的板子。另外用 SWD 在线调试时调试器本身会读写一些内核寄存器。你在用户代码里操作 DWT 之类的内核调试寄存器时也要注意不要和调试器的读写打架。DWT 里有个 32 位周期计数器 CYCCNT可以用来做高精度短延时或运行周期测量但配置它的方式和配置外设寄存器方式不同它是通过内核的 DEMCR 寄存器开启 TRCENA再使能 CYCCNT然后读值。很多人在用户代码里没用过先用 SWD 调试就发现延时异常可能是因为调试器影响了内核时钟和复位行为。7. 被点名最多的那些“寄存器周边”7.1 后备寄存器和 RTC 电池域后备寄存器 BKPxR 是 STM32F1 一个很有特色的外设它在主电源断电后只要 VBAT 引脚还接着电池或超级电容寄存器里的数据就不会丢。它和 RTC 一起挂在备份域里。如果你做的是低功耗设备想保存一些掉电后的关键信息比如校准参数、设备状态、计数次数后备寄存器比写 Flash 快得多而且没有擦写寿命限制。后备寄存器操作有几个敏感点首先要有 PWR 备份域访问使能也就是 PWR_CR 的 DBP 位要置 1其次如果是刚上电后第一次访问可能还需要等待备份域复位释放。很多人一上来就读写 BKP 寄存器发现读出来全是 0xFFFF其实数据根本存入不了问题就出在 DBP 位没开。7.2 Modbus 线圈和寄存器不是一回事工业通信里最常用的 Modbus 协议经常被问到一个基础问题线圈到底和寄存器有什么区别从名称上说线圈是位变量对应 Modbus 里面的 0x、1x 地址区只有 0 和 1 两种状态一般表示开关量要么通要么断。寄存器是 16 位变量对应 3x、4x 地址区可以保存模拟量、温度、频率等数据。用 STM32 实现 Modbus 从站时你会需要维护一张内存映射表线圈用 bit 数组或 16 位数组按位存保持寄存器用 uint16_t 数组存。这样报文来了根据功能码直接去数组地址读写就行不用每个线圈都单独建变量。很多人纠结“线圈和寄存器在内存里怎么排布”我的做法是给每个区域单独一个结构体结构体按 16 位对齐然后提供统一的地址索引函数。7.3 LCD、触摸屏这些外设的寄存器读 ID带寄存器的外设芯片越来越多比如 LCD 控制器 ILI9341触控芯片 CST816D。它们的寄存器不是 STM32 片内的而是通过 SPI 或 I2C 等接口访问的外部设备寄存器。读外设寄存器本质就是先发寄存器地址再读取数据。ILI9341 读 ID 时如果读到 0xA1A1基本可以判断是和屏的通信没有正常建立而不是 ID 本身错误。排查方向一般是复位时序、SPI 模式或初始化序列对不对。触控芯片 CST816D 里也有很多寄存器包括手势信息、坐标寄存器、中断模式寄存器等。这类芯片通常通过 I2C 访问上电后要用 I2C 以从机地址去 probe。很多人一上来就操作寄存器读坐标结果读到的坐标全为 0问题多半是没先配置触摸中断的触发方式或者没有通过设备地址正确唤醒。用逻辑分析仪先抓一把 I2C 波形确认 ACK 都是正常的基本已经解决一大半问题。8. 寄存器调试三板斧读回、打印、先做最小用例8.1 示波器和 SWD 读寄存器的实践寄存器调试没有太多花活就是靠“读回”。初始化完外设首先用调试器把寄存器值读出来和你写的期望值对比。GPIO 复用配置错了没有CRH 是 0x44444444 还是别的值RCC 对应位开了没有SWD 窗口里一眼就看到。第二个利器是示波器。PWM 没波形先量引脚下有没有电平变化再量内部模式是否配置正确。很多寄存器问题最终都用示波器定位到了引脚复用、ODR 和 BSRR 配置冲突这种地方。波形和寄存器同时对照比自己瞎猜高效多了。第三个做一个最小用例。不要在完整工程里调试外设先建一个只初始化这个外设的裸机工程把功能跑通了再合到项目。我之前调试定时器捕获老是在 RTOS 环境里出现异常后来放到最小工程里测试发现是优先级抢占问题和环境里的其他中断互相冲突。最小用例帮你把变量降到最低。8.2 常见问题速查表现象大概率原因寄存器排查点寄存器写了没反应外设时钟没开RCC-APBxENR/APB2ENR 对应位GPIO 复用功能不对F4 忘配 AFRL/AFHRGPIOx-AFRL/AFRH串口发不出数据TXE/TC 标志没检查读 USART_SR串口乱码波特率寄存器算错读 USART_BRR核对 PCLK中断重复触发没清 EXTI_PR 或 NVIC 挂起位清对应挂起标志ADC 多通道读串没配合 DMA 或读 DR 顺序错检查 SQR3 序列和 DMA 配置CAN 掉线位定时采样点不对读 CAN_ESR 和 CAN_BTR外部 SPI 设备连不上SPI 模式/复位时序不对用逻辑分析仪抓 MOSI/MISO延时卡死SysTick 配置或优先级问题读 SysTick-CTRL下载器连不上JTAG 被全部禁用BOOT0 进 ISP 恢复这张表不是万能但覆盖了日常 80% 的“寄存器折腾事”。遇到问题先别急着改代码拿调试器去把对应寄存器读回来大多数时候问题一眼就能看出来。8.3 我的实操体验和一点点建议写寄存器代码重要的不是你背下了多少个寄存器偏移量而是你能不能把一个故障现象翻译成一个寄存器操作。打开手册、定位寄存器、读回数值、对比期望这套流程走顺了很多玄学问题都变得非常直接。我个人的体会是在做完一个模块的寄存器配置后给它写一个简单的自检程序比如把寄存器配置值打印出来存进 Flash或者通过串口传回上位机。后面产品出问题直接叫客户跑一下自检程序日志里回传的寄存器值就能告诉我们配置有没有被意外改动。这个习惯帮我在几个量产项目里省了大量时间比远程瞎猜可靠得多。最后分享一个小技巧寄存器操作里面置位和复位尽量用位操作而不是直接赋整个寄存器值。比如你要把某个位清 0最好不要xxx 0x00而是xxx ~(1n)要置 1就用xxx | (1n)。这样做的好处是避免误改同一寄存器里的其他位也让代码更容易维护。等写到后面你就明白寄存器版代码最重要的是可读性和可维护性能读懂的自己才能稳住一个个深夜调板子的时刻。
阅读完成 · 觉得有帮助?
咨询建站