当前位置: 首页 > news >正文

GD32F407VE天空星开发板的旋转编码器EC12的实现

GD32F407VE天空星开发板的旋转编码器的实现

一、旋转编码器概述

1.1 什么是旋转编码器?

旋转编码器 (Rotary Encoder) 是一种机电元件,可以将旋转的机械位移转换成一系列的数字电信号。它本质上是一个"无限旋转的旋钮",为用户提供直观的交互体验。

1.2 主要应用场景

  • 音量调节:音响系统、汽车音响的音量控制
  • 菜单导航:设备设置界面的上下选择
  • 参数设定:仪器仪表的精确数值调整
  • 位置控制:电机转速、机械臂位置等精密控制

1.3 EC12旋转编码器特性

  • 型号:EC12D1524403
  • 引脚功能
    • A、B相:旋转检测
    • D引脚:按下功能
    • C、E引脚:未使用(根据原理图)

二、硬件设计与连接

2.1 引脚定义与接线

//////////////////// EC12 旋钮 ////////////////////
/*  接线说明
交互板           GD32F407A  ===>  PD11   (外部中断11)B  ===>  PD13   (普通输入)D  ===>  PD15   (外部中断15)3v3 ===>  3v3GND ===>  GND
*/

2.2 硬件抽象层定义

//// 外部中断实现
#define EC12_A_RCU          RCU_GPIOD
#define EC12_A_PIN          GPIOD, GPIO_PIN_11
#define EC12_A_STATE()      gpio_input_bit_get(EC12_A_PIN)
#define EC12_A_ON_TRIG()    EXTI11_on_trig() // 外部中断11回调函数#define EC12_B_RCU          RCU_GPIOD
#define EC12_B_PIN          GPIOD, GPIO_PIN_13
#define EC12_B_STATE()      gpio_input_bit_get(EC12_B_PIN)#define EC12_D_RCU          RCU_GPIOD
#define EC12_D_PIN          GPIOD, GPIO_PIN_15
#define EC12_D_STATE()      gpio_input_bit_get(EC12_D_PIN)
#define EC12_D_ON_TRIG()    EXTI15_on_trig() // 外部中断15回调函数

三、旋转检测原理

3.1 正交编码原理

旋转编码器采用正交编码技术,使用两个存在90度相位差的信号通道:

  • A相 (Phase A)B相 (Phase B)
  • 通过两个信号的相位关系判断旋转方向

在这里插入图片描述
EC11是相反的结构,其他都是一样的

3.2 方向判断算法

根据A、B两相的相位关系,可以准确判断旋转方向:

/*
旋转方向判断逻辑:
- 如果 A是下降沿时,此时B为高电平,那么说明,旋钮是顺时针旋转(右转)。
- 如果 A是下降沿时,此时B为低电平,那么说明,旋钮是逆时针旋转(左转)。
- 如果 A是上升沿时,此时B为低电平,那么说明,旋钮是顺时针旋转(右转)。
- 如果 A是上升沿时,此时B为高电平,那么说明,旋钮是逆时针旋转(左转)。
*/

3.3 时钟类比理解

  • 顺时针旋转 (Clockwise, CW) - 右转

    • 想象时钟指针从12点走向1点、2点
    • A相上升沿时,B相为低电平(0)
  • 逆时针旋转 (Counter-Clockwise, CCW) - 左转

    • 与时钟指针相反方向,从12点走向11点
    • A相上升沿时,B相为高电平(1)

四、软件架构设计

4.1 头文件定义

#ifndef __BSP_EC12_H__
#define __BSP_EC12_H__#include "gpio_cfg.h"//// 中断实现 
void EC12_init();// ======= 轻触按钮回调配置
#define EC12_USE_DOWN   1
#define EC12_USE_UP     1
void EC12_on_down();
void EC12_on_up();// ======= 旋转回调配置
#define EC12_USE_RIGHT  1
#define EC12_USE_LEFT   1
void EC12_on_turn_right(); // 顺时针旋转
void EC12_on_turn_left();  // 逆时针旋转#endif

4.2 核心实现代码

#include "bsp_ec12.h"void EC12_init() {printf("==EC12_init==\n");// B相配置为浮空输入GPIO_input(EC12_B_RCU, EC12_B_PIN, GPIO_PUPD_NONE);
}#define DOWN    RESET
#define UP      SET// 按键中断处理函数
void EC12_D_ON_TRIG() {static FlagStatus last_state = UP; // 上一次状态FlagStatus cur_state = EC12_D_STATE(); // 当前状态if (last_state != cur_state) {last_state = cur_state; // 保存状态if (cur_state == DOWN) {#if EC12_USE_DOWNEC12_on_down();#endif} else {#if EC12_USE_UPEC12_on_up();#endif}}
}// 旋转检测中断处理函数
void EC12_A_ON_TRIG() {static FlagStatus last_state = SET;FlagStatus cur_state = EC12_A_STATE();if (last_state != cur_state) {last_state = cur_state;FlagStatus b_state = EC12_B_STATE();if (cur_state == DOWN) { // 下降沿if (b_state == SET) { // 顺时针旋转#if EC12_USE_RIGHTEC12_on_turn_right();#endif} else { // 逆时针旋转#if EC12_USE_LEFTEC12_on_turn_left();#endif }   } else { // 上升沿if (b_state == RESET) { // 顺时针旋转#if EC12_USE_RIGHTEC12_on_turn_right();#endif} else { // 逆时针旋转#if EC12_USE_LEFTEC12_on_turn_left();#endif }}}
}

五、外部中断配置

5.1 中断配置系统

// EXTI_config.h 配置
#define USE_EXTI_11    1  // A相旋转检测
#define USE_EXTI_15    1  // D相按键检测#if USE_EXTI_11#define EXTI11_RCU          RCU_GPIOD#define EXTI11_PORT         GPIOD#define EXTI11_PUPD         GPIO_PUPD_PULLUP#define EXTI11_SOURCE_PORT  EXTI_SOURCE_GPIOD#define EXTI11_TRIG_TYPE    EXTI_TRIG_BOTH  // 双边沿触发#define EXTI11_PRIORITY     2, 2
#endif#if USE_EXTI_15#define EXTI15_RCU          RCU_GPIOD#define EXTI15_PORT         GPIOD#define EXTI15_PUPD         GPIO_PUPD_PULLUP#define EXTI15_SOURCE_PORT  EXTI_SOURCE_GPIOD#define EXTI15_TRIG_TYPE    EXTI_TRIG_BOTH  // 双边沿触发#define EXTI15_PRIORITY     2, 2
#endif

5.2 通用中断配置函数

static void EXTI_config(rcu_periph_enum rcu, uint32_t port, uint32_t pin, uint32_t pull_up_down, uint8_t exti_port, uint8_t exti_pin,exti_line_enum linex, exti_trig_type_enum trig_type,uint8_t nvic_irq, uint8_t nvic_irq_pre_priority, uint8_t nvic_irq_sub_priority) {// 引脚初始化GPIO_input(rcu, port, pin, pull_up_down);// 系统配置时钟使能rcu_periph_clock_enable(RCU_SYSCFG);// 中断线连接配置syscfg_exti_line_config(exti_port, exti_pin);// EXTI初始化exti_init(linex, EXTI_INTERRUPT, trig_type);exti_interrupt_enable(linex);// NVIC中断配置nvic_irq_enable(nvic_irq, nvic_irq_pre_priority, nvic_irq_sub_priority);
}

六、应用层回调实现

6.1 基础回调函数

// ============= 用户回调函数,可移至业务模块
void EC12_on_down() { // 按下printf("ec12 down\n");// 实际应用中可执行菜单确认、功能切换等操作
}void EC12_on_up() { // 抬起printf("ec12 up\n");// 可执行释放状态处理
}void EC12_on_turn_right() { // 顺时针旋转printf("----顺时针旋转(右转)----\n");// 实际应用:音量增加、数值增大、菜单下翻等
}void EC12_on_turn_left() {  // 逆时针旋转printf("----逆时针旋转(左转)----\n");// 实际应用:音量减小、数值减小、菜单上翻等
}

6.2 高级应用示例

// 音量控制应用
static int volume = 50;void EC12_on_turn_right_volume() {if(volume < 100) {volume += 2;printf("音量增加: %d%%\n", volume);// 更新显示或发送控制命令}
}void EC12_on_turn_left_volume() {if(volume > 0) {volume -= 2;printf("音量减少: %d%%\n", volume);// 更新显示或发送控制命令}
}void EC12_on_down_volume() {printf("静音切换\n");// 实现静音功能
}// 菜单导航应用
static int menu_index = 0;
static const char* menu_items[] = {"设置", "音乐", "视频", "系统"};void EC12_on_turn_right_menu() {menu_index = (menu_index + 1) % 4;printf("选中: %s\n", menu_items[menu_index]);
}void EC12_on_turn_left_menu() {menu_index = (menu_index - 1 + 4) % 4;printf("选中: %s\n", menu_items[menu_index]);
}void EC12_on_down_menu() {printf("进入: %s\n", menu_items[menu_index]);// 执行进入菜单操作
}

七、防抖与稳定性优化

7.1 软件防抖处理

// 增强版旋转检测,添加时间防抖
#define DEBOUNCE_DELAY_MS 5void EC12_A_ON_TRIG_enhanced() {static FlagStatus last_state = SET;static uint32_t last_time = 0;FlagStatus cur_state = EC12_A_STATE();uint32_t current_time = get_system_tick();// 时间防抖检查if((current_time - last_time) < DEBOUNCE_DELAY_MS) {return;}if (last_state != cur_state) {last_state = cur_state;last_time = current_time;// ... 原有的方向判断逻辑}
}

7.2 状态机实现

typedef enum {STATE_IDLE,STATE_ROTATING,STATE_BUTTON_PRESSED
} ec12_state_t;static ec12_state_t current_state = STATE_IDLE;void EC12_state_machine_handler() {switch(current_state) {case STATE_IDLE:// 等待事件break;case STATE_ROTATING:// 处理旋转事件break;case STATE_BUTTON_PRESSED:// 处理按钮事件break;}
}

八、系统集成与测试

8.1 完整初始化序列

void System_EC12_init() {// 初始化外部中断系统EXTI_init();// 初始化旋转编码器EC12_init();printf("旋转编码器系统初始化完成\n");printf("支持功能: 旋转检测、按键检测\n");
}void Application_main() {System_EC12_init();while(1) {// 主循环处理其他任务// 旋转编码器通过中断自动处理// 系统休眠或处理其他业务delay_ms(10);}
}

8.2 调试与测试

// 调试信息输出
void EC12_debug_info() {printf("A相状态: %d\n", EC12_A_STATE());printf("B相状态: %d\n", EC12_B_STATE());printf("D按键状态: %d\n", EC12_D_STATE());
}// 测试模式
void EC12_test_mode() {printf("进入旋转编码器测试模式\n");printf("旋转旋钮观察方向检测\n");printf("按下旋钮测试按键功能\n");
}

九、设计要点与最佳实践

9.1 硬件设计注意事项

  1. 上拉电阻:确保A、B、D引脚都有合适的上拉电阻
  2. 信号滤波:在噪声环境中添加硬件RC滤波器
  3. 布局优化:编码器尽量靠近MCU,减少信号线长度
  4. 电源稳定:确保3.3V电源干净稳定

9.2 软件优化建议

  1. 中断优先级:合理设置中断优先级,避免丢失脉冲
  2. 资源占用:中断处理函数尽量简洁,快速退出
  3. 状态保存:使用static变量保存历史状态
  4. 模块化设计:回调机制便于功能扩展

9.3 可靠性设计

// 错误检测与恢复
#define MAX_MISSED_PULSES 10static int error_count = 0;void EC12_error_handler() {error_count++;if(error_count > MAX_MISSED_PULSES) {printf("旋转编码器异常,尝试重新初始化\n");EC12_init();error_count = 0;}
}

十、总结

  1. 精确的方向检测:基于正交编码原理,准确识别顺时针/逆时针旋转
  2. 多功能集成:同时支持旋转检测和按键功能
  3. 高效的中断处理:双边沿触发,确保不丢失任何操作
  4. 灵活的架构:回调机制便于功能扩展和模块化设计
  5. 稳定性保障:软件防抖、错误恢复等可靠性设计
http://www.dtcms.com/a/560931.html

相关文章:

  • 从零开始学习Redis(五):多级缓存
  • 解码LVGL样式
  • 山西响应式网站建设价位企业培训计划
  • 深入浅出 C++ 多态:从概念到原理
  • 多实现类(如IService有ServiceA/ServiceB)的注入配置与获取
  • web自动化测试-Selenium04_iframe切换、窗口切换
  • 分类与回归算法(一)- 模型评价指标
  • 浙江十大建筑公司排名用v9做网站优化
  • 江门网站建设自助建站站内seo和站外seo区别
  • 嵌入式Linux:线程同步(自旋锁)
  • RHCE复习第一次作业
  • 2025年山西省职业院校技能大赛应用软件系统开发赛项竞赛样题
  • 铁路机车乘务员心理健康状况的研究进展
  • 人才市场官方网站装修公司网站平台
  • Flink 2.1 SQL:解锁实时数据与AI集成,实现可扩展流处理
  • 【软件安全】什么是AFL(American Fuzzy Lop)基于覆盖率引导的模糊测试工具?
  • 山西省最新干部调整佛山网站建设优化
  • 背包DP合集
  • Docker 拉取镜像:SSL 拦截与国内镜像源失效问题解决
  • full join优化改写经验
  • 软件测试:黑盒测试用例篇
  • 【Linux】Linux第一个小程序 - 进度条
  • ubuntu新增用户
  • 青州市网站建设长沙招聘网58同城招聘发布
  • 江苏中南建设集团网站是多少长沙互联网网站建设
  • 从零开始的云原生之旅(十一):压测实战:验证弹性伸缩效果
  • 民宿网站的建设wordpress gallery
  • 【开题答辩全过程】以 广州网红点打卡介绍网站为例,包含答辩的问题和答案
  • Taro 源码浅析
  • Chart.js 混合图:深度解析与应用技巧