2.12. QDEC 设备¶
2.12.1. 简介¶
QDEC(quadrature decoder)正交解码器,用于将双路旋转编码器产生的两组相位相差 90 度的脉冲解码为对应转速和旋转方向。博流系列 MCU 中 QDEC 设备具有以下特性:
拥有 3 组 QDEC 设备可使用
多种时钟来源选择,QDEC 的时钟源可以设置为 32KHz 或者 32MHz,当使用 32KHz 的时钟源时,可以从睡眠模式中唤醒
5-bit 时钟分频器,分频系数为 1-32
16-bit 脉冲计数器,计数范围 -32768~32767 pulse/sample
12 种可配置的 sample 周期(32us~131ms per sample at 1MHz)
16-bit 可设置的 report 周期(0~65535 sample/report)
内置一个可随采样进行闪烁的 LED 功能(LED on/off 0~511 us/sample)
支持 4 路可配置中断源(sample 中断、report 中断、error 中断、overflow 中断)
可配置为 PDS 的唤醒源(clock source 需要配置为 32KHz)
2.12.2. QDEC 设备结构体定义¶
typedef struct qdec_device {
struct device parent;
uint8_t id;
uint8_t acc_mode;
uint8_t sample_mode;
uint8_t sample_period;
uint8_t report_mode;
uint32_t report_period;
uint8_t led_en;
uint8_t led_swap;
uint16_t led_period;
uint8_t deglitch_en;
uint8_t deglitch_strength;
} qdec_device_t;
parent 继承父类属性
id 正交解码器 id ,使用正交解码器 0 则 id 为 0 ,使用正交解码器 1 则 id 为 1 ,以此类推
acc_mode QDEC 计数模式:连续计数和溢出即停止 两种模式
sample_mode QDEC 采样模式:连续采样和完成采样即停止 两种模式
sample_period QDEC 采样周期选择
report_mode QDEC report 模式
report_period report 周期设置
led_en 随动 LED 功能使能
led_swap led 引脚交换
led_period led 输出频率
deglitch_en 消抖功能使能
deglitch_strength 消抖长度
id
提供以下类型
enum qdec_index_type {
QDEC0_INDEX,
QDEC1_INDEX,
QDEC2_INDEX,
QDEC_MAX_INDEX,
};
acc_mode
提供以下类型
enum acc_mode_type {
QDEC_ACC_STOP_SAMPLE_IF_OVERFLOW,
QDEC_ACC_CONTINUE_ACCUMULATE,
};
sample_mode
提供以下类型
enum sample_mode_type {
QDEC_SAMPLE_SINGLE_MOD,
QDEC_SAMPLE_CONTINUE_MOD,
};
report_mode
提供以下类型
enum report_mode_type {
QDEC_REPORT_SAMPLE_CHANGE_MOD,
QDEC_REPORT_TIME_MOD,
};
2.12.3. QDEC 设备参数配置表¶
每一个 QDEC 设备都有一个参数配置宏,宏定义位于 bsp/board/xxx
目录下 peripheral_config.h
文件,变量定义位于 hal_qdec.c
中,因此无需用户自己定义变量。当用户打开对应设备的宏,该设备的配置才生效。例如打开宏 BSP_USING_QDEC0
,QDEC0_CONFIG
即生效,同时 QDEC0_INDEX
设备就可以进行注册和使用了。
/*参数配置宏*/
#if defined(BSP_USING_QDEC0)
#ifndef QDEC0_CONFIG
#define QDEC0_CONFIG \
{ \
.id = 0, \
.acc_mode = QDEC_ACC_CONTINUE_ACCUMULATE, \
.sample_mode = QDEC_SAMPLE_SINGLE_MOD, \
.sample_period = QDEC_SAMPLE_PERIOD_256US, \
.report_mode = QDEC_REPORT_TIME_MOD, \
.report_period = 2000, \
.led_en = ENABLE, \
.led_swap = DISABLE, \
.led_period = 7, \
.deglitch_en = DISABLE, \
.deglitch_strength = 0x0, \
}
#endif
#endif
#if defined(BSP_USING_QDEC1)
#ifndef QDEC1_CONFIG
#define QDEC1_CONFIG \
{ \
.id = 1, \
.acc_mode = QDEC_ACC_CONTINUE_ACCUMULATE, \
.sample_mode = QDEC_SAMPLE_SINGLE_MOD, \
.sample_period = QDEC_SAMPLE_PERIOD_256US, \
.report_mode = QDEC_REPORT_TIME_MOD, \
.report_period = 2000, \
.led_en = ENABLE, \
.led_swap = DISABLE, \
.led_period = 7, \
.deglitch_en = DISABLE, \
.deglitch_strength = 0x0, \
}
#endif
#endif
#if defined(BSP_USING_QDEC2)
#ifndef QDEC2_CONFIG
#define QDEC2_CONFIG \
{ \
.id = 2, \
.acc_mode = QDEC_ACC_CONTINUE_ACCUMULATE, \
.sample_mode = QDEC_SAMPLE_SINGLE_MOD, \
.sample_period = QDEC_SAMPLE_PERIOD_256US, \
.report_mode = QDEC_REPORT_TIME_MOD, \
.report_period = 2000, \
.led_en = ENABLE, \
.led_swap = DISABLE, \
.led_period = 7, \
.deglitch_en = DISABLE, \
.deglitch_strength = 0x0, \
}
#endif
#endif
/*变量定义*/
static qdec_device_t qdecx_device[QDEC_MAX_INDEX] = {
#ifdef BSP_USING_QDEC0
QDEC0_CONFIG,
#endif
#ifdef BSP_USING_QDEC1
QDEC1_CONFIG,
#endif
#ifdef BSP_USING_QDEC2
QDEC2_CONFIG,
#endif
};
注解
上述配置可以通过 QDEC_DEV(dev)->xxx
进行修改,只能在调用 device_open
之前使用。
2.12.4. QDEC 设备接口¶
QDEC 设备接口全部遵循标准设备驱动管理层提供的接口。
2.12.4.1. qdec_register¶
qdec_register
用来注册 QDEC 设备标准驱动接口,在注册之前需要打开对应 QDEC 设备的宏定义。例如定义宏 BSP_USING_QDEC0
方可使用 QDEC0_INDEX
设备,注册完成以后才可以使用其他接口,如果没有定义宏,则无法使用 QDEC0_INDEX
设备。
int qdec_register(enum qdec_index_type index, const char *name);
index 要注册的设备索引
name 为注册的设备命名
index
用来选择 QDEC 设备配置,一个 index 对应一个 QDEC 设备配置,比如 QDEC0_INDEX
对应 QDEC0_CONFIG
配置,index
有如下可选类型
enum qdec_index_type {
#ifdef BSP_USING_QDEC0
QDEC0_INDEX,
#endif
#ifdef BSP_USING_QDEC1
QDEC1_INDEX,
#endif
#ifdef BSP_USING_QDEC2
QDEC2_INDEX,
#endif
QDEC_MAX_INDEX,
};
2.12.4.2. device_open¶
device_open
用于 QDEC 设备的打开,oflag
表示以何种方式打开。实际调用 qdec_open
。
int device_open(struct device *dev, uint16_t oflag);
dev 设备句柄
oflag 设备的打开方式
return 错误码,0 表示打开成功,其他表示错误
oflag
可以写入以下参数:
#define DEVICE_OFLAG_STREAM_TX 0x001 /* 设备以轮训发送模式打开 */
#define DEVICE_OFLAG_STREAM_RX 0x002 /* 设备以轮训接收模式打开 */
#define DEVICE_OFLAG_INT_TX 0x004 /* 设备以中断发送模式打开 */
#define DEVICE_OFLAG_INT_RX 0x008 /* 设备以中断接收模式打开 */
#define DEVICE_OFLAG_DMA_TX 0x010 /* 设备以 DMA 发送模式打开 */
#define DEVICE_OFLAG_DMA_RX 0x020 /* 设备以 DMA 接收模式打开 */
2.12.4.3. device_close¶
device_close
用于设备的关闭。实际调用 qdec_close
。
int device_close(struct device *dev);
dev 设备句柄
return 错误码,0 表示关闭成功,其他表示错误
2.12.4.4. device_control¶
device_control
用于根据命令对 QDEC 设备进行控制和参数的修改。实际调用 qdec_control
。
int device_control(struct device *dev, int cmd, void *args);
dev 设备句柄
cmd 设备控制命令
args 控制参数
return 不同的控制命令返回的意义不同。
args
根据不同的 cmd
传入不同,具体如下:
cmd |
args |
description |
---|---|---|
DEVICE_CTRL_SET_INT |
NULL |
开启 QDEC 中断 |
DEVICE_CTRL_CLR_INT |
NULL |
关闭 QDEC 中断 |
DEVICE_CTRL_GET_INT |
NULL |
获取当前中断状态 |
DEVICE_CTRL_RESUME |
NULL |
开启 QDEC |
DEVICE_CTRL_SUSPEND |
NULL |
关闭 QDEC |
DEVICE_CTRL_GET_SAMPLE_VAL |
NULL |
获取 QDEC 当前的计数值 |
DEVICE_CTRL_GET_SAMPLE_DIR |
NULL |
获取 QDEC 当前的计数方向 |
DEVICE_CTRL_GET_ERROR_CNT |
NULL |
获取 QDEC 当前的错误计数次数 |
2.12.4.5. device_set_callback¶
device_set_callback
用于注册一个 QDEC 中断回调函数。
int device_set_callback(struct device *dev, void (*callback)(struct device *dev, void *args, uint32_t size, uint32_t event));
dev 设备句柄
callback 要注册的中断回调函数
dev 设备句柄
args 接收发送缓冲区,数据类型为 uint8_t*
size 传输长度
event 中断事件类型
QDEC 设备 event
类型如下
enum qdec_event_type {
QDEC_REPORT_EVENT, /*!< report interrupt */
QDEC_SAMPLE_EVENT, /*!< sample interrupt */
QDEC_ERROR_EVENT, /*!< error interrupt */
QDEC_OVERFLOW_EVENT, /*!< ACC1 and ACC2 overflow interrupt */
QDEC_ALL_EVENT, /*!< interrupt max num */
};