1. 项目概述:从旋转到脉冲的精确捕获
搞嵌入式开发,尤其是电机控制、机器人或者需要精确测量旋转角度和速度的项目,编码器和定时器中断绝对是绕不开的核心技术。很多朋友在初学STM32时,可能会觉得定时器配置已经够复杂了,再加上编码器模式,看着数据手册里那一堆寄存器位就有点发怵。我刚开始接触时也这样,总觉得这玩意儿是不是得用外部中断来一个个捕捉脉冲?后来才发现,STM32的定时器硬件单元早就为我们设计好了一套“全自动”的编码器接口,配合中断,能极大地解放CPU,实现高效、精准的位置与速度反馈。
简单来说,这个学习笔记要解决的核心问题就是: 如何利用STM32片上的定时器资源,不依赖CPU频繁查询,自动地、准确地读取旋转编码器产生的正交脉冲信号,并实时计算出旋转方向和计数值。 无论是测量电机的转速、确定轮子的行走距离,还是作为人机交互的旋钮输入,这套组合拳都至关重要。如果你正在做智能小车、云台、3D打印机或者任何需要精密运动控制的设备,那么理解并掌握编码器与定时器中断的配合使用,将是项目成功的关键一步。
2. 核心思路与方案选型:为什么是“编码器模式+中断”?
在深入代码之前,我们必须先想清楚为什么要采用“定时器的编码器接口+中断”这个方案。常见的替代方案有哪些?各自的优劣又是什么?只有理解了背后的设计逻辑,配置寄存器时才能心中有数,出了问题也知道往哪个方向排查。
2.1 方案对比:查询、外部中断与编码器模式
面对编码器的两相(A相和B相)脉冲信号,通常有三种处理思路:
1. 软件查询法: 这是最原始的方法。将编码器的A、B相信号接到普通的GPIO口上,在主循环里不断读取这两个引脚的电平。通过比较当前状态和上一次状态的变化,来判断方向和计数。
- 优点 :实现简单,无需复杂配置。
- 缺点 : 极度消耗CPU资源 。为了不漏掉脉冲,你的循环必须跑得足够快,这在高转速或主频较低的单片机上根本不可行。而且当程序中有其他耗时任务时,极易丢失脉冲,导致计数不准。这只能用于学习原理,几乎不能用于实际项目。
2. 外部中断法: 将编码器的A相(或B相)接到支持外部中断的GPIO引脚上,配置为双边沿触发。每次脉冲变化都进入中断服务函数,在中断里读取A、B相的电平来判断方向,并进行计数。
- 优点 :相比查询法,CPU利用率高了很多,只有在脉冲变化时才响应。
- 缺点 : 中断频率可能很高 。对于一个1000线(每转1000个脉冲)的编码器,电机转速为3000转/分(RPM),那么每秒的脉冲数(PPS)为
1000 * 3000 / 60 = 50,000。这意味着中断函数每秒要被调用5万次,这对CPU依然是沉重的负担,且在高频下容易因中断处理延迟导致计数错误。同时,方向判断逻辑需要软件实现,增加了中断函数的复杂度和执行时间。
3. 定时器编码器接口模式(本方案核心): 这是STM32定时器的高级功能之一。将编码器的A、B相信号分别接到定时器的一个 输入通道 (例如TIMx的CH1和CH2)上。然后将定时器配置为“编码器模式”。在此模式下,定时器的 计数器寄存器(CNT)会根据A、B相的相位关系自动进行递增或递减计数 ,方向判断完全由硬件完成。
- 优点 :
- 全硬件实现 :计数和方向判断无需CPU干预,零开销。
- 高精度与可靠性 :硬件处理脉冲,无软件延迟,抗干扰能力强,可处理极高频率的脉冲信号。
- 灵活的中断 :我们可以为定时器设置“更新中断”(溢出中断)或“捕获/比较中断”。通常,我们设置一个固定的时间间隔(例如10ms)产生一次更新中断,在中断服务函数中读取CNT值,即可得到这段时间内的脉冲增量,从而轻松计算出速度。CPU的负担从“处理每一个脉冲”降为“定时读取一个结果”。
- 缺点 :配置相对复杂,需要理解定时器的不同工作模式。
显然, 方案3是工程实践中的唯一正解 。它完美体现了嵌入式系统中“让硬件做它擅长的事”的设计哲学。
2.2 定时器资源选择与引脚规划
STM32的通用定时器(如TIM2, TIM3, TIM4)和高级定时器(如TIM1, TIM8)基本都支持编码器模式。在选择时,主要考虑两个因素:
- 计数器位数 :通常是16位(最大值65535)。对于高精度编码器,如果转速很快,CNT值可能很快溢出。这就需要我们合理设置中断频率,在溢出前读取并清零CNT,或者使用32位计数器(如TIM2/TIM5在某些型号上)。
- 引脚复用功能 :必须查阅你所使用的STM32型号的**数据手册(Datasheet)**中的“Pinout and pin description”章节,确认你打算使用的定时器通道对应的引脚是否支持编码器功能(通常标记为TIMx_CHx)。 绝对不能想当然地随意连接 。
例如,我手头的STM32F103C8T6核心板,计划使用TIM3的通道1(PA6)和通道2(PA7)来接编码器的A、B相。这就需要先确认PA6和PA7是否默认复用了TIM3_CH1和TIM3_CH2。
注意 :编码器模式需要占用定时器的两个输入通道。有些定时器的通道1和通道2可能分布在不同的GPIO端口上(比如一个在PA,一个在PB),只要它们属于同一个定时器即可。
3. 硬件连接与基础配置
理论清晰了,我们开始动手。这里我以STM32F103系列,使用标准库(Standard Peripheral Library)为例进行说明。使用HAL库或LL库的朋友,原理完全一致,只是函数调用不同。
3.1 编码器信号与硬件连接
常见的增量式旋转编码器有三根信号线:A相、B相和Z相(或称Index相),以及电源和地。
- A相、B相 :输出两路相位差90度的正交方波脉冲。旋转时,A相和B相的先后顺序决定了方向。这是我们必须用到的两路信号。
- Z相 :每旋转一圈输出一个脉冲,用于确定机械零位。在简单的速度测量中可以不接。
- 连接要点 :
- 上拉电阻 :编码器输出通常是开集或开漏的,需要在STM32的输入引脚上启用内部上拉电阻,或者外接一个上拉电阻(如10kΩ)到3.3V,以确保信号稳定。
- 滤波


550

被折叠的 条评论
为什么被折叠?



