stm32f103c8t6实现旋转编码器Operation

image

编码器与 STM32F103 引脚连接

编码器引脚 STM32F103 引脚 说明
VCC 3.3V 供电
GND GND
CLK(A) PA0 EXTI0,中断输入,上拉
DT(B) PA2 普通输入,上拉(不需要中断)
SW(按键) PA3 EXTI3,中断输入,上拉

OLED 与 STM32F103 引脚连接

OLED 引脚 STM32F103 引脚 说明
VCC 3.3V 电源
GND GND
SCL PB8 软件 I²C SCL
SDA PB9 软件 I²C SDA

CubeMX 配置要点

  • PA0:GPIO_Input + EXTI0,触发 Rising/Falling(双沿),Pull-up。
  • PA2:GPIO_Input,Pull-up。
  • PA3:GPIO_Input + EXTI3,触发 Falling(按键接地),Pull-up。
  • 使能 EXTI0/EXTI3 中断(NVIC 里勾选)。
  • OLED 用 I2C1(PB8/PB9)。
encoder.h
#include "encoder.h"

volatile int32_t encoder_count = 0;
volatile uint8_t encoder_button_clicked = 0;

#define ENC_A_Port GPIOA
#define ENC_A_Pin  GPIO_PIN_0   // CLK
#define ENC_B_Port GPIOA
#define ENC_B_Pin  GPIO_PIN_2   // DT
#define ENC_SW_Port GPIOA
#define ENC_SW_Pin  GPIO_PIN_3  // SW

// 若方向反了,改为 1
#define ENC_REVERSE 0

void Encoder_Init(void) { /* 空实现:GPIO/EXTI 由 CubeMX 生成 */ }

/* HAL 的 EXTI 回调:任一外部中断都会进来 */
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == ENC_A_Pin)   // A 相边沿到来,读 B 相判断方向
    {
        GPIO_PinState b = HAL_GPIO_ReadPin(ENC_B_Port, ENC_B_Pin);
    #if ENC_REVERSE
        if (b == GPIO_PIN_SET) encoder_count--;
        else                   encoder_count++;
    #else
        if (b == GPIO_PIN_SET) encoder_count++;
        else                   encoder_count--;
    #endif
    }
    else if (GPIO_Pin == ENC_SW_Pin) // 按键:简单消抖
    {
        static uint32_t last = 0;
        uint32_t now = HAL_GetTick();
        if (now - last > 20) {                   // 20ms 去抖
            if (HAL_GPIO_ReadPin(ENC_SW_Port, ENC_SW_Pin) == GPIO_PIN_RESET) {
                encoder_button_clicked = 1;      // 单击标志
            }
        }
        last = now;
    }
}
main.c
#include "encoder.h"
#include "oled.h"
#include <stdio.h>

int main(void)
{
  HAL_Init();
  SystemClock_Config();
  MX_GPIO_Init();
  MX_I2C1_Init();        // 你已有
  OLED_Init();
  OLED_Clear();
  Encoder_Init();        // 可选

  char line[16];
  int32_t last = 0;

  while (1)
  {
    if (encoder_count != last) {
      last = encoder_count;
      sprintf(line, "Cnt:%-6ld", (long)last);
      OLED_ShowString(2, 1, "            ");
      OLED_ShowString(2, 1, line);
    }

    if (encoder_button_clicked) {
      encoder_button_clicked = 0;
      OLED_ShowString(3, 1, "Button!");
      HAL_Delay(150);
      OLED_ShowString(3, 1, "        ");
    }

    HAL_Delay(5);
  }
}
posted @ 2025-08-12 13:20  huh&uh  阅读(34)  评论(0)    收藏  举报