123下一页
返回列表 发新帖我要提问本帖赏金: 20.00元(功能说明)

[活动] 【极海APM32F407IG Tiny Board开发板测评】6.基于官方USB鼠标例程和ADC实现用摇杆控制鼠标

[复制链接]
4549|47
 楼主| yuyy1989 发表于 2023-7-11 09:47 | 显示全部楼层 |阅读模式
#申请原创# @21小跑堂  
6.基于官方USB鼠标例程和ADC实现用摇杆控制鼠标
官方的USB例程里有一个针对这个开发板模拟鼠标的的例程
QQ截图20230710172022.png
用板子上的两个按键控制鼠标的左右移动,手里还有个这样的游戏手柄摇杆
微信图片_20230711081434.jpg
打算结合一下实现类似一些笔记本上的小红点控制鼠标的功能
先实现ADC读取XY电平数据,用PC0 PC1分别做X Y的输入
QQ截图20230710194033.png
ADC检测部分代码

  1. uint16_t adcData1 = 2047,adcData2 = 2047;
  2. void adc_init()
  3. {
  4.     GPIO_Config_T   gpioConfig;
  5.     ADC_Config_T    adcConfig;
  6.     ADC_CommonConfig_T  adcCommonConfig;

  7.     RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOC);

  8.     GPIO_ConfigStructInit(&gpioConfig);
  9.     gpioConfig.mode    = GPIO_MODE_AN;
  10.     gpioConfig.pupd    = GPIO_PUPD_NOPULL;
  11.     gpioConfig.pin     = GPIO_PIN_0|GPIO_PIN_1;
  12.     GPIO_Config(GPIOC, &gpioConfig);

  13.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
  14.     RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC2);

  15.     ADC_Reset();
  16.     ADC_ConfigStructInit(&adcConfig);
  17.     adcConfig.resolution          = ADC_RESOLUTION_12BIT;
  18.     adcConfig.continuousConvMode  = ENABLE;
  19.     adcConfig.dataAlign           = ADC_DATA_ALIGN_RIGHT;
  20.     adcConfig.extTrigEdge         = ADC_EXT_TRIG_EDGE_NONE;
  21.     adcConfig.scanConvMode        = DISABLE;
  22.     ADC_Config(ADC1, &adcConfig);
  23.     ADC_Config(ADC2, &adcConfig);
  24.    
  25.     /*Set ADC Clock Prescaler. ADC_Clock = APB2_Clock/4, 84/4=21MHz*/
  26.     adcCommonConfig.prescaler = ADC_PRESCALER_DIV4;
  27.     ADC_CommonConfig(&adcCommonConfig);

  28.     ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_10, 1, ADC_SAMPLETIME_112CYCLES);
  29.     ADC_ConfigRegularChannel(ADC2, ADC_CHANNEL_11, 1, ADC_SAMPLETIME_112CYCLES);

  30.     ADC_EnableInterrupt(ADC1, ADC_INT_EOC);
  31.     ADC_EnableInterrupt(ADC2, ADC_INT_EOC);

  32.     NVIC_EnableIRQRequest(ADC_IRQn, 1, 1);

  33.     ADC_Enable(ADC1);
  34.     ADC_Enable(ADC2);

  35.     ADC_SoftwareStartConv(ADC1);
  36.     ADC_SoftwareStartConv(ADC2);
  37. }

  38. void ADC_IRQHandler(void)
  39. {

  40.     if (ADC_ReadStatusFlag(ADC1, ADC_FLAG_EOC))
  41.     {
  42.         ADC_ClearStatusFlag(ADC1, ADC_FLAG_EOC);
  43.         adcData1 = ADC_ReadConversionValue(ADC1);
  44.     }
  45.     if (ADC_ReadStatusFlag(ADC2, ADC_FLAG_EOC))
  46.     {
  47.         ADC_ClearStatusFlag(ADC2, ADC_FLAG_EOC);
  48.         adcData2 = ADC_ReadConversionValue(ADC2);
  49.     }
  50. }
先通过串口printf打印出来看看,使用串口printf需要添加如下代码
  1. #define DEBUG_USART TINY_COM1
  2. #if defined (__CC_ARM) || defined (__ICCARM__) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
  3. int fputc(int ch, FILE* f)
  4. {
  5.     USART_TxData(DEBUG_USART, (uint8_t)ch);
  6.     while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
  7.     return (ch);
  8. }

  9. #elif defined (__GNUC__)
  10. int __io_putchar(int ch)
  11. {
  12.     USART_TxData(DEBUG_USART, ch);
  13.     while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
  14.     return ch;
  15. }

  16. int _write(int file, char* ptr, int len)
  17. {
  18.     int i;
  19.     for (i = 0; i < len; i++)
  20.     {
  21.         __io_putchar(*ptr++);
  22.     }
  23.     return len;
  24. }
  25. #else
  26. #warning Not supported compiler type
  27. #endif
并勾选Use MicroLIB
QQ截图20230710213038.png
如果勾选后编译出现这个错误,点击rebuild重新完整编译一下就行了
QQ截图20230710213201.png
最后看看读取到的adc数据
QQ截图20230710211052.png
接下来修改鼠标例程的代码,实现用摇杆控制鼠标移动,原来的2个按键用作鼠标的左右按键
先来了解一下原来代码中上报的report[4]中的4个字节都对应鼠标的哪些动作
report[0]:bit0为1左键按下0未按下,bit1为1右键按下0未按下,bit2为1中键按下0未按下
report[1]:鼠标X坐标变化量,8位有符号数正数右移负数左移
report[2]:鼠标Y坐标变化量,8位有符号数正数上移负数下移
report[3]:滚轮变化量,8位有符号数正数向前滚动负数向后滚动
了解了这些也就知道该怎么改了,修改后的鼠标代码

  1. void USB_DevUserApplication(void)
  2. {
  3.     static uint8_t userAppState = USER_APP_INIT;
  4.     static uint8_t interval = 0;
  5.     static int8_t report[4] = { 0 };
  6.     switch (userAppState)
  7.     {
  8.         case USER_APP_INIT:
  9.             interval = USBD_HID_ReadInterval(&gUsbDeviceHS);

  10.             report[0] = 0;
  11.             report[1] = 0;
  12.             report[2] = 0;
  13.             report[3] = 0;
  14.             userAppState = USER_APP_RUN;
  15.             break;

  16.         case USER_APP_RUN:
  17.             if (!APM_TINY_PBGetState(BUTTON_KEY1))
  18.             {
  19.                 APM_DelayMs(10);
  20.                 if (!APM_TINY_PBGetState(BUTTON_KEY1))
  21.                 {
  22.                     report[0] |= 0x02;
  23.                 }
  24.             }
  25.             else
  26.             {
  27.                 report[0] &= 0xFD;
  28.             }

  29.             if (!APM_TINY_PBGetState(BUTTON_KEY2))
  30.             {
  31.                 APM_DelayMs(10);
  32.                 if (!APM_TINY_PBGetState(BUTTON_KEY2))
  33.                 {
  34.                     report[0] |= 0x01;
  35.                 }
  36.             }
  37.             else
  38.             {
  39.                 report[0] &= 0xFE;
  40.             }
  41.             report[1] = 0;
  42.             report[2] = 0;
  43.             if(adcData1 > 2197 || adcData1 < 1897)
  44.             {
  45.                 report[1] = (2047 - adcData1)*15/2047;
  46.             }
  47.             if(adcData2 > 2197 || adcData2 < 1897)
  48.             {
  49.                 report[2] = (adcData2 - 2047)*15/2047;
  50.             }
  51.             
  52.             USBD_HID_TxReport(&gUsbDeviceHS, (uint8_t*)report, 4);
  53.             APM_DelayMs(interval);
  54.             break;
  55.     }
  56. }
编译烧录查看效果
摇杆控制鼠标移动
WeChat_20230711081444 00_00_00-00_00_30.gif
左右按键,左键单击双击右键单击

WeChat_20230711081458 00_00_00-00_00_30.gif


打赏榜单

Gfan 打赏了 20.00 元 2023-08-17
理由:APM32F407IG Tiny Board精选测评

评论

赞,来学习一下!  发表于 2023-10-12 11:49
guijial511 发表于 2023-7-12 08:33 来自手机 | 显示全部楼层
可以做一个游戏模拟器了
tpgf 发表于 2023-8-5 08:56 | 显示全部楼层
摇杆控制鼠标需要多少个物理量呢
chenjun89 发表于 2023-8-5 17:16 来自手机 | 显示全部楼层
不错,有点好玩,做个模拟器啥的。
wiba 发表于 2023-8-5 19:02 | 显示全部楼层
这种摇杆模拟鼠标来检测的原理是什么呢
kxsi 发表于 2023-8-5 19:41 | 显示全部楼层
不太明白它的原理 为什么需要用adc进行检测呢 使用开关量不可以吗
coshi 发表于 2023-8-5 20:28 | 显示全部楼层
使用摇杆的原理和usb鼠标是不是不相同的啊
qcliu 发表于 2023-8-5 21:00 | 显示全部楼层
这种模拟操作的实时性怎么样 会不会有一定的延迟
drer 发表于 2023-8-5 21:32 | 显示全部楼层
像是这种类型的操作是不是必须就需要跑系统来实现了啊

评论

knk
有操作系统的话程序会简单很多  发表于 2023-9-3 23:52
weifeng90 发表于 2023-8-6 09:03 来自手机 | 显示全部楼层
遥杆适合做个模拟器玩玩
yinxiangh 发表于 2023-8-26 23:56 | 显示全部楼层
这个摇杆好突兀
updownq 发表于 2023-9-5 10:02 | 显示全部楼层
需要确保鼠标驱动程序与操作系统兼容,并且可以被正确识别和配置。
alvpeg 发表于 2023-9-5 10:09 | 显示全部楼层
在编写代码时,需要注意时序控制、数据处理、中断处理等方面的问题。
lihuami 发表于 2023-9-5 10:17 | 显示全部楼层
摇杆通常由两个可动电阻、两个固定电阻和多个引脚组成,需要正确连接到单片机的ADC输入引脚上。
jimmhu 发表于 2023-9-5 10:32 | 显示全部楼层
摇杆模块和单片机都有稳定的电源供应,以防止不稳定的电压对系统的影响。
cemaj 发表于 2023-9-5 10:43 | 显示全部楼层
需要编写程序来处理摇杆的输入信号,以便将摇杆位置转换为鼠标的移动和点击信号
pentruman 发表于 2023-9-5 10:54 | 显示全部楼层
对采样得到的数字信号进行处理,将其转换为鼠标的移动控制信号。
deliahouse887 发表于 2023-9-5 11:05 | 显示全部楼层
深入理解USB协议, 正确地编写USB鼠标例程。
wwppd 发表于 2023-9-5 11:32 | 显示全部楼层
在进行数据处理时,需要注意数据的精度、数据的滤波、数据的校准等方面的问题。
eefas 发表于 2023-9-5 11:55 | 显示全部楼层
需要将ADC采集到的模拟电压转换为鼠标移动的相对坐标,并将其打包成USB协议报文发送给主机。需要注意鼠标加速度、速度和方向等特性,保证鼠标操作的流畅性和精确性。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

168

主题

826

帖子

10

粉丝
快速回复 在线客服 返回列表 返回顶部