打印
[活动专区]

【AT-START-WB415测评】基于AT32WB415实现鼠标滚轮

[复制链接]
697|8
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
本帖最后由 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电子网,感谢雅特力,让我能够参与这次评测,这将是非常美妙的体验;感谢



AT32WB415_Firmware_Library_V2.0.2(for li).rar

4.97 MB

使用特权

评论回复
沙发
ulystronglll| | 2022-9-3 16:31 | 只看该作者
鼠标滚动是什么实现的  

使用特权

评论回复
板凳
lilijin1995|  楼主 | 2022-9-3 16:45 | 只看该作者
ulystronglll 发表于 2022-9-3 16:31
鼠标滚动是什么实现的

旋转编码器

使用特权

评论回复
地板
alvpeg| | 2022-9-3 18:26 | 只看该作者
可以实现模拟鼠标输入了。

使用特权

评论回复
5
timfordlare| | 2022-9-3 19:05 | 只看该作者
能够做一个遥感吗

使用特权

评论回复
6
chenci2013| | 2022-9-3 21:18 | 只看该作者
usb做hid吗

使用特权

评论回复
7
lilijin1995|  楼主 | 2022-9-5 13:33 | 只看该作者
timfordlare 发表于 2022-9-3 19:05
能够做一个遥感吗

可以,
第一种是蓝牙板:

https://www.bilibili.com/video/BV1QV4y177cm/?spm_id_from=333.788&vd_source=2bbde87de845d5220b1d8ba075c12fb0

第二种是usb板:
https://www.bilibili.com/video/BV12W4y1r7cZ/?vd_source=2bbde87de845d5220b1d8ba075c12fb0

使用特权

评论回复
8
Henryko| | 2022-9-7 21:22 | 只看该作者
我之前刷到过这视频

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

54

主题

162

帖子

7

粉丝