本帖最后由 lilijin1995 于 2022-9-2 22:36 编辑
1.旋转编码器
旋转编码器是用来测量转速并配合PWM技术可以实现快速调速的装置,光电式旋转编码器通过光电转换,可将输出轴的角位移、角速度等机械量转换成相应的电脉冲以数字量输出:
关于旋转编码器工作原理和驱动教程,大家可以通过这个视频了解
https://www.bilibili.com/video/BV15B4y1x7xV?vd_source=2bbde87de845d5220b1d8ba075c12fb0
2.AT-START-WB415
这是在“二姨家”活动申请到的开发板,这是AT32WB415的评估板,这是一个具备ARM9内核跑蓝牙,ARM Cortex-M4内核跑外设的高集成MCU,由于Up主水平有限,时间精力有限,故这里以USB鼠标为基础,后续有时间再了解使用实现蓝牙鼠标;
1.USB协议相关:
1.1设备描述符
设备描述符如上图,需要注意的是VID和PID以及序列号,以及厂商字符串、产品字符串,序列号字符串(UID)需要配置;
1.2 配置描述符集合
配置描述符集合里面包含了配置描述符,接口描述符,以及HID描述符,端点描述符;需要注意接口的数量和索引,HID报告描述符长度、以及端点数量,端点地址等,端点中断轮询间隔;
1.3 报告描述符
这是一个鼠标的报告描述符;这里我们只用到最后一个byte,滚轮;
2.代码移植修改
2.1encoder代码
这里我们用到的SDK是AT32WB415_Firmware_Library_V2.0.2;参考了\examples\tmr\encoder_tmr2编码器实例以及\examples\usb_device\custom_hid;
没有字节用mouse例程的原因是官方封装的函数我用不习惯;我将encoder_tmr2->custom_hid,把编码器的例程移植到custom_hid;其中代码如下
/**
**************************************************************************
* [url=home.php?mod=space&uid=288409]@file[/url] Encoder.c
* [url=home.php?mod=space&uid=895143]@version[/url] v1.0.0
* [url=home.php?mod=space&uid=212281]@date[/url] 2022-09-01
* [url=home.php?mod=space&uid=247401]@brief[/url] NULL
*
**************************************************************************
*/
#include "Encoder.h"
EncodTypeDef encoder;
gpio_init_type gpio_init_struct = {0};
crm_clocks_freq_type crm_clocks_freq_struct = {0};
void Encoder_Init(void)
{
crm_clocks_freq_get(&crm_clocks_freq_struct);
/* enable tmr2/gpioa clock */
crm_periph_clock_enable(CRM_TMR2_PERIPH_CLOCK, TRUE);
crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
/* timer1 output pin Configuration */
gpio_init_struct.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1;
gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
gpio_init(GPIOA, &gpio_init_struct);
/* tmr2 encoder mode configuration
tmr2 c1ifp1 ,c2ifp2 as encoder input pin, tmr2 counter
changed each signal edge. */
/* enable tmr2 32bit function */
tmr_32_bit_function_enable(TMR2, TRUE);
tmr_base_init(TMR2, 0xFFFFFFFF, 0);
tmr_cnt_dir_set(TMR2, TMR_COUNT_UP);
/* config encoder mode */
tmr_encoder_mode_config(TMR2, TMR_ENCODER_MODE_C, TMR_INPUT_RISING_EDGE, TMR_INPUT_RISING_EDGE);
/* enable tmr2 */
tmr_counter_enable(TMR2, TRUE);
}
另有头文件如下
/**
**************************************************************************
* [url=home.php?mod=space&uid=288409]@file[/url] Encoder.h
* [url=home.php?mod=space&uid=895143]@version[/url] v1.0.0
* [url=home.php?mod=space&uid=212281]@date[/url] 2022-09-01
* [url=home.php?mod=space&uid=247401]@brief[/url] NULL
*
**************************************************************************
*/
#ifndef __ENCODER_H
#define __ENCODER_H
#ifdef __cplusplus
extern "C" {
#endif
#include "stdio.h"
#include "at32wb415.h"
#include "at32wb415_board.h"
#include "at32wb415_clock.h"
typedef struct
{
uint8_t Dir;
uint16_t Count;
} EncodTypeDef;
extern EncodTypeDef encoder;
#define TIM2_IS_TIM_COUNTING_DOWN() ((TMR2->ctrl1_bit.cnt_dir) == (TMR_COUNT_DOWN))
extern void Encoder_Init(void);
#ifdef __cplusplus
}
#endif
#endif
2.2 USB HID代码修改
不得不说雅特力写的USB Device库还是可以的,基本回调函数的形式;
其中描述符相关以及字符串描述符相关的都放到了以下句柄结构中;我们根据1中usb协议相关的设备描述符,配置描述符,接口描述符,端点描述符改好即可;
usbd_desc_handler custom_hid_desc_handler =
{
get_device_descriptor,
get_device_qualifier,
get_device_configuration,
get_device_other_speed,
get_device_lang_id,
get_device_manufacturer_string,
get_device_product_string,
get_device_serial_string,
get_device_interface_string,
get_device_config_string,
};
这里不列出来了,详细修改教程我们通过视频讲解,将发布到Bilibili,敬请关注;
https://www.bilibili.com/video/BV1c14y1s7q8/
最后我们需要一个接口上报我们的报表定义的数据接口是:
custom_hid_class_send_report(&otg_core_struct.dev, report_buf, USBD_CUSTOM_IN_MAXPACKET_SIZE);
在while中我们解析编码器信号并上报,代码如下:
while(1)
{
encoder.Dir=TIM2_IS_TIM_COUNTING_DOWN();
encoder.Count = tmr_counter_value_get(TMR2);
if(encoder.Dir)
{
//CaptureNumberhis>CaptureNumber
if(CaptureNumberhis_Z>encoder.Count)
{
wheel=1;
} else {
wheel=0;
}
} else {
//CaptureNumber>CaptureNumberhis
if(CaptureNumberhis_Z<encoder.Count)
{
wheel=(u8)-1;
} else {
wheel=0;
}
}
report_buf[0] = 0;
report_buf[1] = 0;
report_buf[2] = 0;
report_buf[3] = wheel;
custom_hid_class_send_report(&otg_core_struct.dev, report_buf, USBD_CUSTOM_IN_MAXPACKET_SIZE);
delay_ms(10);
CaptureNumberhis_Z=encoder.Count;
wheel=0;
}
3.实验现象:
顺时针旋转,鼠标滚轮往下,反之往上;请看视频;
https://www.bilibili.com/video/BV1c14y1s7q8/
4.附件
代码如下附件
最后的最后感谢21ic电子网,感谢雅特力,让我能够参与这次评测,这将是非常美妙的体验;感谢
|