外设测试指南:X4 模式下的脉冲计数验证)
RIOT OS 正交解码器QDEC外设测试指南X4 模式下的脉冲计数验证【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT正交解码器Quadrature DecoderQDEC是旋转编码器、电机转速测量等场景的核心外设。本文以 RIOT OS 仓库中的tests/periph/qdec测试程序为对象完整讲解该测试的设计思路、硬件接线、编译烧录方法与预期结果并结合drivers/include/periph/qdec.h接口定义与 nRF5x/STM32 平台的底层实现帮助读者理解 QDEC 驱动在 RIOT 中的工作方式以及如何将该测试移植到自己的板卡上。测试目标与预期结果tests/periph/qdec是 RIOT 操作系统中针对底层 QDEC 驱动low-level QDEC driver的测试程序。其核心目的正如 tests/periph/qdec/README.md 所述如果一切按预期运行你应该在每一个配置了 QDEC 的设备上看到 X4 模式的正交解码。也就是说该测试的唯一预期结果是程序正确初始化所有已声明的 QDEC 设备并在 X4 模式下持续输出计数器数值。只要每个 QDEC 通道每秒都能打印出符合输入信号的计数值测试即视为通过。程序行为初始化、计数与回调测试程序本体位于 tests/periph/qdec/main.c逻辑非常简洁由初始化和周期读取两个阶段组成。阶段一初始化所有 QDEC 设备程序遍历全部 QDEC 设备逐一调用qdec_init()for (i 0; i QDEC_NUMOF; i) { int32_t error qdec_init(QDEC_DEV(i), QDEC_X4, handler, (void *)(uintptr_t)i); if (error) { fprintf(stderr, Mode not supported!\n); return error; } }这里的关键要素包括QDEC_NUMOF由板级配置periph_conf.h中定义的设备数量宏见 drivers/include/periph/qdec.h 中的默认访问宏QDEC_DEV(x)。QDEC_X4解码模式即对 A、B 两路信号的上升沿与下降沿全部计数。handler溢出中断回调。QDEC 计数器溢出时会触发中断并调用该回调回调内调用qdec_read_and_reset()将计数器清零static void handler(void *arg) { qdec_t qdec (qdec_t)(uintptr_t)arg; printf(QDEC %u counter overflow : reset counter\n, qdec); qdec_read_and_reset(QDEC_DEV(qdec)); }若某个设备不支持请求的模式qdec_init()返回错误码程序打印Mode not supported!并退出。这正与 README 中X4 模式解码的预期一致本测试严格要求在 X4 模式下运行。阶段二每秒读取并清零计数初始化完成后主循环每秒对每个 QDEC 通道执行读值—清零—打印while (1) { for (i 0; i QDEC_NUMOF; i) { value qdec_read_and_reset(QDEC_DEV(i)); printf(QDEC %lu %ld\n, (unsigned long int)i, (long int)value); } xtimer_sleep(1); }由此可以得到每秒的脉冲计数增量方便直接对比输入信号的频率验证解码是否正确。xtimer_sleep(1)依赖xtimer模块已在 tests/periph/qdec/Makefile 中通过USEMODULE xtimer引入。QDEC 驱动接口与三种解码模式qdec_init()、qdec_read()、qdec_read_and_reset()、qdec_start()、qdec_stop()五个 API 构成了 RIOT 的 QDEC 外设接口定义在 drivers/include/periph/qdec.h。正交信号与方向判定原理正交编码器输出两路相位相差 90° 的方波 A 与 B。驱动通过检测一路信号的边沿并检查另一路信号的电平来判断旋转方向。qdec.h的文档给出了完整的 8 种判定情形节选核心规则A 上升沿且 B 为高 → 顺时针计数加一A 上升沿且 B 为低 → 逆时针计数减一B 下降沿且 A 为高 → 顺时针计数加一依此类推。据此衍生出三种解码模式模式计数边沿对应情形QDEC_X1仅 A 上升沿情形 1、2QDEC_X2A 上升沿 下降沿情形 14QDEC_X4A、B 全部边沿全部 8 种情形qdec_mode_t枚举即对应这三种模式typedef enum { QDEC_X1, /* X1 mode */ QDEC_X2, /* X2 mode */ QDEC_X4, /* X4 mode */ } qdec_mode_t;X4 模式分辨率最高每个编码器周期产生 4 个计数脉冲这也是本测试指定使用该模式的原因。初始化前置条件接口文档特别强调调用qdec_init()前目标设备必须处于非活动状态——要么从未初始化过要么已通过qdec_stop()停止。换言之重复初始化前必须先停止设备这是驱动层保证状态一致性的约束。硬件接线以 nucleo-f401re 为例测试程序打印的接线说明对应 STM32 平台为QDEC0 : signal A on PA6 and signal B on PA7 QDEC1 : signal A on PB6 and signal B on PB7即默认板卡nucleo-f401retests/periph/qdec/Makefile 中BOARD ? nucleo-f401re配置了两个 QDEC 通道。若使用该板卡应将编码器的 A/B 两路信号分别接到上述引脚并保证共地。STM32 平台上的 QDEC 实现基于定时器的编码器接口模式相关代码见 cpu/stm32/periph/qdec.c。编译与烧录运行在仓库根目录执行make -C tests/periph/qdec flash termmake -C指定测试目录flash负责编译并烧录term打开串口终端查看输出。若交叉编译工具链未加入PATH可先执行source /path/to/RIOT/RIOT/dist/tools/export之类的方式导出工具链环境以实际部署为准。通过BOARD...可覆盖默认板卡例如make -C tests/periph/qdec BOARDnrf52840dk flash term。正常运行时应看到类似输出Welcome into Quadrature Decoder (QDEC) test program. This program will count pulses on all available QDEC channels ... QDEC 0 42 QDEC 1 0每秒打印一次各通道计数值用手转动编码器时对应计数值应随之增减即为 README 所述X4 模式解码正常的直观体现。移植到其他板卡nRF52840 DK 的定制示例测试通过EXTERNAL_BOARD_DIRS机制附带了一个定制板卡目录用于在默认没有 QDEC 配置的板卡上快速启用该外设EXTERNAL_BOARD_DIRS $(CURDIR)/boards_modded定制板卡的组织结构boards_modded/nrf52840dk_mod目录包含Makefile将模块命名为board_nrf52840dk_qdec刻意与native实现的板卡名区分并通过DIRS $(RIOTBOARD)/nrf52840dk复用官方 nRF52840 DK 板卡目录Makefile.featuresFEATURES_PROVIDED periph_qdec向系统声明该板卡提供 QDEC 外设功能Makefile.depUSEMODULE board_nrf52840dk_qdec引入定制模块include/periph_conf.h定义 QDEC 的引脚与参数配置。QDEC 配置结构体periph_conf.h中通过qdec_conf_t数组声明设备nRF52840 DK 定制示例的配置为static const qdec_conf_t qdec_config[] { { .a_pin GPIO_PIN(0, 11), /* Button 1 */ .b_pin GPIO_PIN(0, 12), /* Button 2 */ .led_pin GPIO_PIN(0, 13), /* And the first LED */ .sample_period QDEC_SAMPLEPER_SAMPLEPER_128us, .debounce_filter true, .led_active_state false }, }; #define QDEC_NUMOF ARRAY_SIZE(qdec_config)各字段含义与 nRF5x 平台实现cpu/nrf5x_common/periph/qdec.c对应如下a_pin/b_pin正交信号 A、B 输入引脚初始化时被配置为上拉输入GPIO_IN_PU并写入PSEL.A/PSEL.B寄存器led_pin可选 LED 指示引脚。为有效引脚时写入PSEL.LED并依据led_active_state设置LEDPOL为GPIO_UNDEF时则断开写入CONNECT掩码sample_period采样周期用于设置SAMPLEPER寄存器决定信号采样的时间分辨率debounce_filter使能硬件去抖滤波写入DBFEN寄存器适合有抖动干扰的机械编码器场景。QDEC_NUMOF由ARRAY_SIZE(qdec_config)自动推导与main.c的遍历循环直接联动。此外qdec_init()内部通过断言校验sample_period不超过QDEC_SAMPLEPER_SAMPLEPER_131ms移植时应注意取值边界。nRF5x 平台实现要点从 cpu/nrf5x_common/periph/qdec.c 可以看出该平台的几个关键约束与行为仅支持 X4 模式if (mode ! QDEC_X4) return -EINVAL;nRF5x 的 QDEC 外设天然对所有边沿计数不支持 X1/X2溢出回调可选传入非空cb时使能ACCOF中断并注册isr_qdec否则关闭中断。isr_qdec只服务唯一可用的 QDEC 设备QDEC_DEV(0)读值即清零qdec_read_and_reset()通过触发TASKS_RDCLRACC任务寄存器读取并清除ACC累加寄存器实现原子性的读后清零停止语义qdec_stop()触发TASKS_STOP后忙等EVENTS_STOPPED事件确保外设真正停止后才返回。这也解释了 README 的措辞既然 nRF5x 只支持 X4那么在每个配置了 QDEC 的设备上看到 X4 模式解码就是该平台测试通过的唯一标准。如何扩展测试到更多板卡若要在其他支持periph_qdec功能的板卡上运行本测试只需确认板卡periph_conf.h中定义了qdec_config[]数组与QDEC_NUMOF宏可在FEATURES_PROVIDED中声明periph_qdec或参考nrf52840dk_mod通过EXTERNAL_BOARD_DIRS定制按qdec_conf_t结构体字段配置 A/B 引脚、采样周期、去抖与 LED 选项以BOARD板卡名编译运行观察每秒打印的计数是否随编码器输入变化。仓库中另提供native与 STM32 平台的参考实现cpu/native/periph/qdec.c、cpu/stm32/periph/qdec.c可作为理解接口语义与移植实现的对照素材。总结tests/periph/qdec是一个聚焦X4 模式正交解码的轻量级外设冒烟测试初始化全部 QDEC 通道、注册溢出回调、每秒读值清零并打印。通过它既能快速验证硬件接线与板级periph_conf.h配置是否正确也能从 drivers/include/periph/qdec.h 与 nRF5x/STM32 实现中理解正交信号解码、三种模式差异、溢出中断回调等底层机制是学习 RIOT 外设驱动与进行板卡移植验证的良好起点。【免费下载链接】RIOTRIOT - The friendly OS for IoT项目地址: https://gitcode.com/GitHub_Trending/riot/RIOT创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考