stm32f103c8t6四个编码器
时间: 2025-05-31 11:50:34 浏览: 47
### STM32F103C8T6 处理四个编码器的实现方法
STM32F103C8T6 微控制器可以通过其通用输入捕获功能来支持正交编码器接口(QEI)。为了处理四个编码器,可以利用多个定时器通道作为外部信号捕捉单元。以下是具体的配置和编程实现方式。
#### 配置 GPIO 和 TIM 定时器
每个编码器需要两个 GPIO 引脚用于 A/B 相位信号输入。假设我们有四个编码器,则至少需要八个 GPIO 引脚。这些引脚应连接到具有输入捕获能力的定时器通道上。例如:
- 编码器 1 使用 `TIM2 CH1` 和 `CH2`
- 编码器 2 使用 `TIM3 CH1` 和 `CH2`
- 编码器 3 使用 `TIM4 CH1` 和 `CH2`
- 编码器 4 使用 `TIM5 CH1` 和 `CH2`
GPIO 初始化代码如下所示:
```c
void Encoder_GPIO_Init(void) {
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);
GPIO_InitTypeDef GPIO_InitStruct;
// 配置 PA0 (TIM2_CH1), PA1 (TIM2_CH2)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入模式
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 配置 PB4 (TIM3_CH1), PB5 (TIM3_CH2)
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
}
```
#### 配置 TIM 定时器
对于每个编码器对应的定时器,需将其设置为增量模式(Encoder Mode),并启用相应的中断服务程序以便实时更新计数值。以下是一个典型的定时器初始化函数示例:
```c
void Timer_Encoder_Init(TIM_TypeDef* TIMx, uint16_t PrescalerValue) {
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_TIM3 |
RCC_APB1Periph_TIM4 | RCC_APB1Periph_TIM5, ENABLE);
TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct;
TIM_ICInitTypeDef TIM_ICInitStruct;
// 基础参数设定
TIM_TimeBaseStruct.TIM_Period = 0xFFFF; // 自动重装载值最大
TIM_TimeBaseStruct.TIM_Prescaler = PrescalerValue;// 设置预分频系数
TIM_TimeBaseStruct.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStruct);
// 输入捕获配置
TIM_ICInitStruct.TIM_Channel = TIM_Channel_1 | TIM_Channel_2;
TIM_ICInitStruct.TIM_ICPolarity = TIM_ICPolarity_Rising; // 上升沿触发
TIM_ICInitStruct.TIM_ICSelection = TIM_ICSelection_DirectTI; // 直接映射至 TIx
TIM_ICInitStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1; // 不分频
TIM_ICInitStruct.TIM_ICFilter = 0xF; // 数字滤波器长度
TIM_ICInit(TIMx, &TIM_ICInitStruct);
// 启用编码器模式
TIM_EncoderInterfaceConfig(TIMx, TIM_EncoderMode_TI12,
TIM_ICPolarity_Rising, TIM_ICPolarity_Rising);
// 中断使能与优先级分配
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn; // 替换为对应定时器中断号
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
TIM_ITConfig(TIMx, TIM_IT_Update, ENABLE); // 开启溢出中断
}
// 调用该函数完成所有定时器初始化
void All_Timers_Init() {
Timer_Encoder_Init(TIM2, 72 - 1); // 对应PA0/PA1
Timer_Encoder_Init(TIM3, 72 - 1); // 对应PB4/PB5
Timer_Encoder_Init(TIM4, 72 - 1); // 其他两组同理...
Timer_Encoder_Init(TIM5, 72 - 1);
}
```
#### 实现中断服务程序
当某个定时器发生事件时会进入其中断服务程序,在此期间读取当前计数值并将数据存储起来供后续使用。下面展示了一个简单的 ISR 结构:
```c
volatile int32_t Enc_Counts[4]; // 存储各编码器累计脉冲数
void TIM2_IRQHandler(void){
if(TIM_GetITStatus(TIM2,TIM_IT_Update)==SET){ // 判断是否是更新中断源引起
Enc_Counts[0] += TIM2->CNT; // 更新第一个编码器计数值
TIM_SetCounter(TIM2,0); // 清零计数寄存器以防溢出
TIM_ClearITPendingBit(TIM2,TIM_IT_Update); // 清除标志位防止重复响应
}
}
// 类似定义其他三个定时器ISR ...
```
通过以上步骤即可成功搭建基于 STM32 的四路独立编码器测量平台[^1][^2]。
阅读全文
相关推荐




















