简介:STM32 编码器模式是微控制器STM32用于获取旋转编码器信号的特殊工作方式,广泛应用于电机控制领域。本文深入探讨了 STM32 如何配置定时器实现编码器模式,并通过 encoder.c 和 encoder.h 文件的编程实践阐述了相关知识。通过本指南,读者将掌握 STM32 编码器模式的配置步骤,包括定时器初始化、编码器输入通道配置和中断服务处理,并了解 encoder.c 和 encoder.h 文件中函数和结构体的作用。本指南旨在帮助开发者快速上手 STM32 编码器模式的应用,为电机控制项目提供基础。
1. STM32 编码器编程指南
第一章:STM32 编码器模式简介
STM32 编码器是一种用于测量角位移和速度的专用硬件模块。它可以连接到外部编码器设备,例如增量式编码器或绝对式编码器。STM32 编码器模式提供以下功能:
- 测量旋转角度和速度
- 跟踪编码器的方向和位置
- 提供中断服务程序,用于快速响应编码器事件
2. 定时器配置为编码器模式
2.1 TIMx_ENCODER_MODE 配置
TIMx_ENCODER_MODE 配置是定时器编码器模式的基本配置,它将定时器配置为编码器模式,并使用内部时钟源。
代码块:
TIM_Encoder_InitTypeDef sConfig;
sConfig.EncoderMode = TIM_ENCODERMODE_TI1;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0x0;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0x0;
逻辑分析:
-
sConfig.EncoderMode = TIM_ENCODERMODE_TI1;
:将定时器配置为编码器模式,使用 TI1 输入通道作为编码器输入。 -
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
:设置 TI1 输入通道的极性为上升沿触发。 -
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
:选择 TI1 输入通道直接连接到定时器输入捕获寄存器。 -
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
:设置 TI1 输入通道的分频器为 1,即不分频。 -
sConfig.IC1Filter = 0x0;
:设置 TI1 输入通道的滤波器为 0,即不滤波。 -
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
:设置 TI2 输入通道的极性为上升沿触发。 -
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
:选择 TI2 输入通道直接连接到定时器输入捕获寄存器。 -
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
:设置 TI2 输入通道的分频器为 1,即不分频。 -
sConfig.IC2Filter = 0x0;
:设置 TI2 输入通道的滤波器为 0,即不滤波。
2.2 TIMx_ENCODER_MODE_TI12 配置
TIMx_ENCODER_MODE_TI12 配置是定时器编码器模式的扩展配置,它将定时器配置为编码器模式,并使用外部时钟源。
代码块:
TIM_Encoder_InitTypeDef sConfig;
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0x0;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0x0;
逻辑分析:
-
sConfig.EncoderMode = TIM_ENCODERMODE_TI12;
:将定时器配置为编码器模式,使用 TI1 和 TI2 输入通道作为编码器输入。 -
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
:设置 TI1 输入通道的极性为上升沿触发。 -
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
:选择 TI1 输入通道直接连接到定时器输入捕获寄存器。 -
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
:设置 TI1 输入通道的分频器为 1,即不分频。 -
sConfig.IC1Filter = 0x0;
:设置 TI1 输入通道的滤波器为 0,即不滤波。 -
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
:设置 TI2 输入通道的极性为上升沿触发。 -
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
:选择 TI2 输入通道直接连接到定时器输入捕获寄存器。 -
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
:设置 TI2 输入通道的分频器为 1,即不分频。 -
sConfig.IC2Filter = 0x0;
:设置 TI2 输入通道的滤波器为 0,即不滤波。
2.3 TIMx_ENCODER_MODE_TI12_INDEX 配置
TIMx_ENCODER_MODE_TI12_INDEX 配置是定时器编码器模式的进一步扩展配置,它将定时器配置为编码器模式,并使用外部时钟源和索引通道。
代码块:
TIM_Encoder_InitTypeDef sConfig;
sConfig.EncoderMode = TIM_ENCODERMODE_TI12_INDEX;
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
sConfig.IC1Filter = 0x0;
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
sConfig.IC2Filter = 0x0;
sConfig.IndexInput = TIM_INDEXINPUT_TI1;
sConfig.IndexPolarity = TIM_ICPOLARITY_RISING;
sConfig.IndexPrescaler = TIM_ICPSC_DIV1;
sConfig.IndexFilter = 0x0;
逻辑分析:
-
sConfig.EncoderMode = TIM_ENCODERMODE_TI12_INDEX;
:将定时器配置为编码器模式,使用 TI1 和 TI2 输入通道作为编码器输入,并使用索引通道。 -
sConfig.IC1Polarity = TIM_ICPOLARITY_RISING;
:设置 TI1 输入通道的极性为上升沿触发。 -
sConfig.IC1Selection = TIM_ICSELECTION_DIRECTTI;
:选择 TI1 输入通道直接连接到定时器输入捕获寄存器。 -
sConfig.IC1Prescaler = TIM_ICPSC_DIV1;
:设置 TI1 输入通道的分频器为 1,即不分频。 -
sConfig.IC1Filter = 0x0;
:设置 TI1 输入通道的滤波器为 0,即不滤波。 -
sConfig.IC2Polarity = TIM_ICPOLARITY_RISING;
:设置 TI2 输入通道的极性为上升沿触发。 -
sConfig.IC2Selection = TIM_ICSELECTION_DIRECTTI;
:选择 TI2 输入通道直接连接到定时器输入捕获寄存器。 -
sConfig.IC2Prescaler = TIM_ICPSC_DIV1;
:设置 TI2 输入通道的分频器为 1,即不分频。 -
sConfig.IC2Filter = 0x0;
:设置 TI2 输入通道的滤波器为 0,即不滤波。 -
sConfig.IndexInput = TIM_INDEXINPUT_TI1;
:选择 TI1 输入通道作为索引通道。 -
sConfig.IndexPolarity = TIM_ICPOLARITY_RISING;
:设置索引通道的极性为上升沿触发。 -
sConfig.IndexPrescaler = TIM_ICPSC_DIV1;
:设置索引通道的分频器为 1,即不分频。 -
sConfig.IndexFilter = 0x0;
:设置索引通道的滤波器为 0,即不滤波。
3. 编码器输入通道配置
3.1 编码器输入通道选择
STM32 编码器模式支持使用两个通道(TI1 和 TI2)作为编码器输入。这些通道可以连接到 GPIO 引脚,以接收来自外部编码器的信号。
配置输入通道时,需要指定以下参数:
- 通道源: 选择用于编码器输入的 GPIO 引脚。
- 极性: 指定编码器信号的极性(上升沿或下降沿)。
- 滤波: 配置输入信号的滤波器,以减少噪声和抖动。
3.2 编码器输入通道滤波
输入通道滤波器用于减少编码器信号中的噪声和抖动。滤波器通过对多个采样进行平均来实现,从而平滑信号。
STM32 编码器模式支持两种类型的滤波器:
- 采样滤波器: 对多个采样进行平均,以平滑信号。
- 时钟分频滤波器: 将时钟信号分频,以降低采样率,从而减少噪声。
3.3 编码器输入通道极性
编码器输入通道极性用于指定编码器信号的极性。极性可以设置为上升沿或下降沿触发。
设置极性时,需要考虑编码器的类型和连接方式。例如,对于增量式编码器,极性通常设置为上升沿或下降沿,具体取决于编码器的连接方式。
代码示例
以下代码示例展示了如何配置编码器输入通道:
/* TIMx_ENCODER_MODE 配置 */
TIMx->CCMR1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;
/* TIMx_ENCODER_MODE_TI12 配置 */
TIMx->CCMR1 |= TIM_CCMR1_CC1S_1 | TIM_CCMR1_CC2S_1;
/* TIMx_ENCODER_MODE_TI12_INDEX 配置 */
TIMx->CCMR1 |= TIM_CCMR1_CC1S_1 | TIM_CCMR1_CC2S_1 | TIM_CCMR1_CC2S_0;
参数说明
-
TIMx
:编码器定时器外设基地址。 -
CCMR1
:编码器模式寄存器 1。 -
CC1S
:捕获/比较 1 输入通道选择。 -
CC2S
:捕获/比较 2 输入通道选择。
逻辑分析
上述代码示例配置了编码器输入通道。对于 TIMx_ENCODER_MODE
配置,通道 1 和通道 2 都被选择为编码器输入。对于 TIMx_ENCODER_MODE_TI12
配置,通道 1 和通道 2 都被选择为编码器输入,并且通道 2 的极性被反转。对于 TIMx_ENCODER_MODE_TI12_INDEX
配置,通道 1 和通道 2 都被选择为编码器输入,通道 2 的极性被反转,并且通道 2 的输入被配置为索引信号。
4. 中断服务程序处理
4.1 编码器中断服务程序结构
编码器中断服务程序通常包含以下部分:
- 中断入口点: 这是中断服务程序的入口点,它保存寄存器并禁用中断。
- 数据处理: 此部分读取编码器寄存器并更新编码器计数。
- 状态机: 此部分根据编码器的当前状态更新状态机。
- 中断出口点: 这是中断服务程序的出口点,它恢复寄存器并启用中断。
4.2 编码器中断服务程序中的数据处理
在数据处理部分,中断服务程序执行以下操作:
- 读取编码器寄存器: 中断服务程序读取编码器寄存器以获取编码器计数和状态信息。
- 更新编码器计数: 中断服务程序将读取的编码器计数添加到编码器计数变量中。
- 更新编码器状态: 中断服务程序更新编码器状态变量以反映编码器的当前状态。
void TIMx_IRQHandler(void) {
// 保存寄存器
__disable_irq();
// 读取编码器寄存器
uint32_t encoder_count = TIMx->CNT;
uint32_t encoder_status = TIMx->SR;
// 更新编码器计数
encoder_count += encoder_count_offset;
// 更新编码器状态
encoder_status_flags = encoder_status;
// 清除中断标志
TIMx->SR &= ~TIM_SR_UIF;
// 恢复寄存器
__enable_irq();
}
4.3 编码器中断服务程序中的状态机
在状态机部分,中断服务程序执行以下操作:
- 检查编码器状态: 中断服务程序检查编码器的当前状态以确定编码器的方向和速度。
- 更新状态机: 中断服务程序根据编码器的当前状态更新状态机。
switch (encoder_status_flags) {
case TIM_SR_CC1IF:
// 编码器正向旋转
encoder_state = ENCODER_STATE_FORWARD;
break;
case TIM_SR_CC2IF:
// 编码器反向旋转
encoder_state = ENCODER_STATE_REVERSE;
break;
case TIM_SR_CC1IF | TIM_SR_CC2IF:
// 编码器停止旋转
encoder_state = ENCODER_STATE_STOPPED;
break;
default:
// 未知状态
encoder_state = ENCODER_STATE_UNKNOWN;
break;
}
5. encoder.c 文件代码解析
5.1 encoder_init() 函数
void encoder_init(TIM_TypeDef *TIMx, uint32_t encoder_mode)
{
// 配置定时器为编码器模式
TIMx->CR1 |= TIM_CR1_CEN;
TIMx->CCMR1 |= encoder_mode;
// 配置编码器输入通道
TIMx->CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E;
TIMx->CCMR1 |= TIM_CCMR1_CC1S_0 | TIM_CCMR1_CC2S_0;
// 配置编码器中断
TIMx->DIER |= TIM_DIER_UIE;
NVIC_EnableIRQ(TIMx_IRQn);
}
参数说明:
-
TIMx
: 定时器外设基地址 -
encoder_mode
: 编码器模式,可以是TIMx_ENCODER_MODE
、TIMx_ENCODER_MODE_TI12
或TIMx_ENCODER_MODE_TI12_INDEX
代码解释:
- 配置定时器为编码器模式:
- 设置
TIMx->CR1
寄存器的CEN
位,使能定时器。 -
设置
TIMx->CCMR1
寄存器的CC1S
和CC2S
位,选择编码器模式。 -
配置编码器输入通道:
- 设置
TIMx->CCER
寄存器的CC1E
和CC2E
位,使能编码器输入通道。 -
设置
TIMx->CCMR1
寄存器的CC1S
和CC2S
位,选择输入通道。 -
配置编码器中断:
- 设置
TIMx->DIER
寄存器的UIE
位,使能更新中断。 - 使能定时器中断。
简介:STM32 编码器模式是微控制器STM32用于获取旋转编码器信号的特殊工作方式,广泛应用于电机控制领域。本文深入探讨了 STM32 如何配置定时器实现编码器模式,并通过 encoder.c 和 encoder.h 文件的编程实践阐述了相关知识。通过本指南,读者将掌握 STM32 编码器模式的配置步骤,包括定时器初始化、编码器输入通道配置和中断服务处理,并了解 encoder.c 和 encoder.h 文件中函数和结构体的作用。本指南旨在帮助开发者快速上手 STM32 编码器模式的应用,为电机控制项目提供基础。