开发环境
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_ENCODER
bool "Enable Pulse Encoder"
default n
select RT_USING_PULSE_ENCODER
if BSP_USING_PULSE_ENCODER
config BSP_USING_PULSE_ENCODER4
bool "Enable Pulse Encoder4"
default n
endif
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****/