STM32编码器模式实战:避开CNT寄存器处理的三大深坑
当你盯着屏幕上跳动的编码器计数值,却发现它时而正常时而诡异——突然从32767跳变到-32768,或者明明电机在反转却显示正值。这不是灵异事件,而是STM32定时器编码器模式下的典型陷阱。本文将带你直击三个最容易被忽视的底层问题,从硬件寄存器到C语言类型转换,彻底解决那些教程里没讲清楚的"玄学"现象。
1. 计数器跳变之谜:CNT寄存器的溢出与重载
第一次使用__HAL_TIM_GET_COUNTER()读取编码器值时,多数开发者会被它的突然跳变吓到。比如当顺时针旋转时,数值从0递增到65535后,下一个值突然变成了0;逆时针旋转时,0之后突然变成65535。这种现象的根源在于STM32定时器的16位CNT寄存器工作机制。
硬件真相:STM32的通用定时器(如TIM2-TIM5)采用16位向上/向下计数器,其CNT寄存器物理结构如下:
| 位宽 | 类型 | 取值范围 | 溢出行为 |
|---|---|---|---|
| 16位 | 无符号整数 | 0 ~ 65535 | 65535→0 / 0→65535 |
当编码器旋转超过机械单圈分辨率时,CNT值会循环计数。假设编码器每圈产生400个脉冲(四倍频后为1600个计数),实际应用中需要处理两种溢出场景:
c复制// 错误示例:直接使用原始计数值
uint32_t raw_count = __HAL_TIM_GET_COUNTER(&htim3);
// 当CNT从65535→0时,raw_count会突然减小,导致位置计算错误
// 正确解法:溢出补偿算法
static int32_t last_count = 0;
static int32_t total_count = 0;
int32_t current_count = (int32_t)__HAL_TIM_GET_COUNTER(&htim3);
int32_t delta = current_count - last_count;
// 处理向上溢出(正转越过65535)
if(delta > 32767) del
