开发环境
ubeMX
MDK5 IDE
STM32F103C8T6 芯片
Stm32最小系统板
RT-Thread操作系统
硬件条件
- LPD3806-400BM-G5-24C 脉冲AB相增量式光电旋转编码器
- AB相线需要分别连接单片机的具有编码器功能的定时器通道1和通道2两个引脚
- 两引脚需要内部上拉

- 使用开发板等引脚电路复杂读取数据会失败
-
Cube

这里用的是TIM多少,后面的RTT编码器设备就要配置Encoder多少,程序中使用pulse多少
Kconfig
menuconfig BSP_USING_PULSE_ENCODERbool "Enable Pulse Encoder"default nselect RT_USING_PULSE_ENCODERif BSP_USING_PULSE_ENCODERconfig BSP_USING_PULSE_ENCODER4bool "Enable Pulse Encoder4"default nendif
Env


scons —target=mdk5
MDK

即配置成功
- 也可修改设备名称,不使用默认的”pulse4”
见
pulse_encoder_config.h#ifdef BSP_USING_PULSE_ENCODER4#ifndef PULSE_ENCODER4_CONFIG#define PULSE_ENCODER4_CONFIG \{ \.tim_handler.Instance = TIM4, \.encoder_irqn = TIM4_IRQn, \.name = "pulse4" \}#endif /* PULSE_ENCODER4_CONFIG */#endif /* BSP_USING_PULSE_ENCODER4 */
-
接口函数
查找设备
rt_device_t rt_device_find(const char* name);
| 参数 | 描述 | | —- | —- | | name | 脉冲编码器的设备名称 | | 返回 | —— | | 脉冲编码器设备句柄 | 查找到对应设备将返回相应的设备句柄 | | RT_NULL | 没有找到设备 |
一般情况下,注册到系统的脉冲编码器的设备名称为 pulse1,pulse2等
打开设备
rt_err_t rt_device_open(rt_device_t dev, rt_uint16_t oflags);
| 参数 | 描述 | | —- | —- | | dev | 脉冲编码器设备句柄 | | oflags | 设备打开模式,一般以只读方式打开,即取值:RT_DEVICE_OFLAG_RDONLY | | 返回 | —— | | RT_EOK | 设备打开成功 | | 其他错误码 | 设备打开失败 |
控制设备
rt_err_t rt_device_control(rt_device_t dev, rt_uint8_t cmd, void* arg);
| 参数 | 描述 |
|---|---|
| dev | 设备句柄 |
| cmd | 命令控制字 |
| arg | 控制的参数 |
| 返回 | —— |
| RT_EOK | 函数执行成功 |
| -RT_ENOSYS | 执行失败,dev 为空 |
| 其他错误码 | 执行失败 |
控制字如下 | 控制字 | 描述 | | —- | —- | | PULSE_ENCODER_CMD_GET_TYPE | 获取脉冲编码器类型 | | PULSE_ENCODER_CMD_ENABLE | 使能脉冲编码器 | | PULSE_ENCODER_CMD_DISABLE | 失能脉冲编码器 | | PULSE_ENCODER_CMD_CLEAR_COUNT | 清空编码器计数值 |
-
读取计数
rt_size_t rt_device_read(rt_device_t dev, rt_off_t pos, void* buffer, rt_size_t size);
| 参数 | 描述 | | —- | —- | | dev | 设备句柄 | | pos | 固定值为 0 | | buffer | rt_int32_t 类型变量的地址,用于存放脉冲编码器的值。 | | size | 固定值为 1 | | 返回 | —— | | 固定返回值 | 返回 1 |
关闭设备
rt_err_t rt_device_close(rt_device_t dev);
| 参数 | 描述 |
|---|---|
| dev | 脉冲编码器设备句柄 |
| 返回 | —— |
| RT_EOK | 关闭设备成功 |
| -RT_ERROR | 设备已经完全关闭,不能重复关闭设备 |
| 其他错误码 | 关闭设备失败 |
实验例程
#include <rtthread.h>#include <rtdevice.h>#include <board.h>#define PULSE_ENCODER_DEV_NAME "pulse4" /* 脉冲编码器名称 */int main(void){rt_err_t ret = RT_EOK;rt_device_t pulse_encoder_dev = RT_NULL; /* 脉冲编码器设备句柄 *//* 查找脉冲编码器设备 */pulse_encoder_dev = rt_device_find(PULSE_ENCODER_DEV_NAME);if (pulse_encoder_dev == RT_NULL){rt_kprintf("pulse encoder sample run failed! can't find %s device!\n", PULSE_ENCODER_DEV_NAME);return RT_ERROR;}/* 以只读方式打开设备 */ret = rt_device_open(pulse_encoder_dev, RT_DEVICE_OFLAG_RDONLY);if (ret != RT_EOK){rt_kprintf("open %s device failed!\n", PULSE_ENCODER_DEV_NAME);return ret;}/* 设置上拉两个引脚 */rt_pin_mode(GET_PIN(B, 6), PIN_MODE_INPUT_PULLUP);rt_pin_mode(GET_PIN(B, 7), PIN_MODE_INPUT_PULLUP);rt_int32_t count;while(1){rt_thread_mdelay(1);/* 读取脉冲编码器计数值 */rt_device_read(pulse_encoder_dev, 0, &count, 1);rt_kprintf("%d",count);}}
模块化实现
Module_PulseEncoder.h
/** Copyright (c) 2020 - ~, HIT_HERO Team** PULSE ENCODER MODULE HEAD FILE* Used in RT-Thread Operate System** Change Logs:* Date Author Notes Mail* 2020-09-03 WangXi first version WangXi_chn@foxmail.com*/#ifndef _MODULE_PULSEENCODER_#define _MODULE_PULSEENCODER_#include <rtthread.h>#include <rtdevice.h>#include <board.h>struct _MODULE_PULSEENCODER{/* Property */char * Property_PulseDevName;rt_base_t Property_CH1_pin;rt_base_t Property_CH2_pin;/* Value */rt_device_t Value_pulse_dev;rt_int32_t Value_pulseNum;/* Method */void (*Method_Init)(struct _MODULE_PULSEENCODER *module);void (*Method_Read)(struct _MODULE_PULSEENCODER *module);void (*Method_Clear)(struct _MODULE_PULSEENCODER *module);};typedef struct _MODULE_PULSEENCODER MODULE_PULSEENCODER;rt_err_t Module_PulseEncoder_Config(MODULE_PULSEENCODER *module);#endif/************************ (C) COPYRIGHT 2020 WANGXI **************END OF FILE****/
Module_PulseEncoder.c
/** Copyright (c) 2020 - ~, HIT_HERO Team** PULSE ENCODER MODULE SOUCE FILE* Used in RT-Thread Operate System** Change Logs:* Date Author Notes Mail* 2020-09-03 WangXi first version WangXi_chn@foxmail.com*/#include "Module_PulseEncoder.h"static void Module_PulseEncoderInit(MODULE_PULSEENCODER *module);static void Module_PulseEncoderRead(MODULE_PULSEENCODER *module);static void Module_PulseEncoderClear(MODULE_PULSEENCODER *module);/* Global Method */rt_err_t Module_PulseEncoder_Config(MODULE_PULSEENCODER *module){if( module->Method_Init ==NULL &&module->Method_Read ==NULL &&module->Method_Clear ==NULL){/* Link the Method */module->Method_Init = Module_PulseEncoderInit;module->Method_Read = Module_PulseEncoderRead;module->Method_Clear = Module_PulseEncoderClear;}else{rt_kprintf("Warning: Module BspCommunicate is Configed twice\n");return RT_ERROR;}/* Device Init */module->Method_Init(module);return RT_EOK;}static void Module_PulseEncoderInit(MODULE_PULSEENCODER *module){rt_err_t ret = RT_EOK;/* find pulse encode device */module->Value_pulse_dev = rt_device_find(module->Property_PulseDevName);if (module->Value_pulse_dev == RT_NULL){rt_kprintf("pulse encoder sample run failed! can't find %s device!\n", module->Property_PulseDevName);return;}/* open the device in readonly mode */ret = rt_device_open(module->Value_pulse_dev, RT_DEVICE_OFLAG_RDONLY);if (ret != RT_EOK){rt_kprintf("open %s device failed!\n", module->Property_PulseDevName);return;}rt_pin_mode(module->Property_CH1_pin, PIN_MODE_INPUT_PULLUP);rt_pin_mode(module->Property_CH2_pin, PIN_MODE_INPUT_PULLUP);}static void Module_PulseEncoderRead(MODULE_PULSEENCODER *module){rt_device_read(module->Value_pulse_dev, 0, &(module->Value_pulseNum), 1);}static void Module_PulseEncoderClear(MODULE_PULSEENCODER *module){rt_device_control(module->Value_pulse_dev, PULSE_ENCODER_CMD_CLEAR_COUNT, RT_NULL);module->Value_pulseNum = 0;}/************************ (C) COPYRIGHT 2020 WANGXI **************END OF FILE****/
