13.5 通用定时器项目:旋转编码器控制LED亮度

# 13.5 通用定时器项目:旋转编码器控制LED亮度

本实验通过STM32的TIM2定时器(编码器模式)读取旋转编码器信号,结合TIM3的PWM输出,实现LED亮度调节与颜色切换功能。
核心功能

  • 编码器计数:旋转编码器调节PWM占空比(0~100),控制LED亮度。
  • 按键切换:按下编码器按键切换红、绿、蓝三色LED通道。
  • OLED显示:实时显示当前计数值(Encoder_cnt)。

# 13.5.1 硬件电路设计

# 旋转编码器连接

  • 引脚分配
    • A相(TIM2_CH1) → PA15
    • B相(TIM2_CH2) → PB3
    • 按键(KEY) → PB4(内部上拉)
  • 滤波电路:C20、C22、C27用于抑制信号抖动,R15、R19为上拉电阻。
编码器原理图

# 13.5.2 STM32CubeMX配置

# 1. 工程基础配置

  • 芯片型号:STM32F103C8T6
  • 主频:72MHz
  • 调试接口:SWD

# 2. TIM2编码器模式配置

  1. 模式选择:Encoder Mode TI1(仅在通道1边沿计数)。
  2. 参数设置
    • 预分频器(PSC):2-1 → 时钟频率36MHz
    • 输入滤波(Filter):15(抑制噪声)
    • 极性:
      • 通道1(Rising Edge)
      • 通道2(Falling Edge)
配置TIM2为编码器模式

# 3. TIM3 PWM模式配置

  • 通道:TIM3_CH2(PA7)、TIM3_CH3(PB0)、TIM3_CH4(PB1)。
  • 参数
    • 预分频器(PSC):720-1 → PWM频率100Hz
    • 自动重装载值(ARR):100-1 → 占空比范围0%~100%
TIM3工作参数

# 13.5.3 软件设计

# 1. TIM2初始化(代码清单13‑6)

static void MX_TIM2_Init(void) {
  htim2.Instance = TIM2;
  htim2.Init.Prescaler = 2-1;       // 预分频2,时钟36MHz
  htim2.Init.Period = 65535;        // 计数器最大值(16位)
  TIM_Encoder_InitTypeDef sConfig = {
    .EncoderMode = TIM_ENCODERMODE_TI1, // 编码器模式TI1
    .IC1Polarity = TIM_ICPOLARITY_RISING,
    .IC2Polarity = TIM_ICPOLARITY_FALLING, // 通道2极性反向
    .IC1Filter = 15,                // 输入滤波
    .IC2Filter = 15
  };
  HAL_TIM_Encoder_Init(&htim2, &sConfig); // 初始化编码器
}
1
2
3
4
5
6
7
8
9
10
11
12
13

# 2. 主循环逻辑(代码清单13‑7)

int Encoder_cnt = 0;   // 编码器计数值
int Channel_index = 0; // 当前PWM通道索引
uint32_t Channels[3] = {TIM_CHANNEL_2, TIM_CHANNEL_3, TIM_CHANNEL_4};

int main(void) {
  // 初始化外设
  HAL_Init();
  MX_GPIO_Init();
  MX_TIM2_Init();
  MX_TIM3_Init();
  MX_I2C1_Init();
  OLED_Init();
  HAL_TIM_Encoder_Start(&htim2, TIM_CHANNEL_ALL); // 启动编码器
  HAL_TIM_PWM_Start(&htim3, Channels[Channel_index]); // 启动PWM

  while (1) {
    Encoder_cnt = __HAL_TIM_GET_COUNTER(&htim2); // 读取计数值
    // 限制计数值范围0~100
    if (Encoder_cnt > 100) {
      Encoder_cnt = 100;
      __HAL_TIM_SET_COUNTER(&htim2, 100);
    }
    // 按键检测:切换LED颜色
    if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4) == GPIO_PIN_RESET) {
      HAL_Delay(10); // 消抖
      if (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4) == GPIO_PIN_RESET) {
        HAL_TIM_PWM_Stop(&htim3, Channels[Channel_index]);
        Channel_index = (Channel_index + 1) % 3; // 切换通道
        HAL_TIM_PWM_Start(&htim3, Channels[Channel_index]);
      }
      while (HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_4) == GPIO_PIN_RESET);
    }
    // 更新PWM占空比
    __HAL_TIM_SET_COMPARE(&htim3, Channels[Channel_index], Encoder_cnt);
    // OLED显示计数值
    sprintf(message, "Encoder_cnt:%d", Encoder_cnt);
    OLED_NewFrame();
    OLED_PrintString(1, 1, message, &font16x16, OLED_COLOR_NORMAL);
    OLED_ShowFrame();
  }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41

# 13.5.4 下载验证

# 现象与步骤

  1. 烧录程序:通过ST-LINK下载代码至开发板。
  2. 功能验证
    • 旋转编码器:顺时针旋转增加Encoder_cnt,逆时针减少(范围0~100)。
    • LED亮度:计数值越大,当前通道LED越亮。
    • 按键切换:按下按键切换红、绿、蓝三色LED通道。
  3. OLED显示:实时显示当前计数值(如Encoder_cnt:77)。
程序现象

关键说明

  • 编码器计数方向:通过设置通道2极性为Falling Edge,确保顺时针旋转时计数值递增。
  • 占空比映射Encoder_cnt直接映射为PWM的CCR值,范围0~100对应亮度0%~100%。
  • 消抖逻辑:按键检测加入10ms延时,避免误触发。