#申请原创# @21小跑堂
6.基于官方USB鼠标例程和ADC实现用摇杆控制鼠标
官方的USB例程里有一个针对这个开发板模拟鼠标的的例程
用板子上的两个按键控制鼠标的左右移动,手里还有个这样的游戏手柄摇杆
打算结合一下实现类似一些笔记本上的小红点控制鼠标的功能
先实现ADC读取XY电平数据,用PC0 PC1分别做X Y的输入
ADC检测部分代码
- uint16_t adcData1 = 2047,adcData2 = 2047;
- void adc_init()
- {
- GPIO_Config_T gpioConfig;
- ADC_Config_T adcConfig;
- ADC_CommonConfig_T adcCommonConfig;
- RCM_EnableAHB1PeriphClock(RCM_AHB1_PERIPH_GPIOC);
- GPIO_ConfigStructInit(&gpioConfig);
- gpioConfig.mode = GPIO_MODE_AN;
- gpioConfig.pupd = GPIO_PUPD_NOPULL;
- gpioConfig.pin = GPIO_PIN_0|GPIO_PIN_1;
- GPIO_Config(GPIOC, &gpioConfig);
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC1);
- RCM_EnableAPB2PeriphClock(RCM_APB2_PERIPH_ADC2);
- ADC_Reset();
- ADC_ConfigStructInit(&adcConfig);
- adcConfig.resolution = ADC_RESOLUTION_12BIT;
- adcConfig.continuousConvMode = ENABLE;
- adcConfig.dataAlign = ADC_DATA_ALIGN_RIGHT;
- adcConfig.extTrigEdge = ADC_EXT_TRIG_EDGE_NONE;
- adcConfig.scanConvMode = DISABLE;
- ADC_Config(ADC1, &adcConfig);
- ADC_Config(ADC2, &adcConfig);
-
- /*Set ADC Clock Prescaler. ADC_Clock = APB2_Clock/4, 84/4=21MHz*/
- adcCommonConfig.prescaler = ADC_PRESCALER_DIV4;
- ADC_CommonConfig(&adcCommonConfig);
- ADC_ConfigRegularChannel(ADC1, ADC_CHANNEL_10, 1, ADC_SAMPLETIME_112CYCLES);
- ADC_ConfigRegularChannel(ADC2, ADC_CHANNEL_11, 1, ADC_SAMPLETIME_112CYCLES);
- ADC_EnableInterrupt(ADC1, ADC_INT_EOC);
- ADC_EnableInterrupt(ADC2, ADC_INT_EOC);
- NVIC_EnableIRQRequest(ADC_IRQn, 1, 1);
- ADC_Enable(ADC1);
- ADC_Enable(ADC2);
- ADC_SoftwareStartConv(ADC1);
- ADC_SoftwareStartConv(ADC2);
- }
- void ADC_IRQHandler(void)
- {
- if (ADC_ReadStatusFlag(ADC1, ADC_FLAG_EOC))
- {
- ADC_ClearStatusFlag(ADC1, ADC_FLAG_EOC);
- adcData1 = ADC_ReadConversionValue(ADC1);
- }
- if (ADC_ReadStatusFlag(ADC2, ADC_FLAG_EOC))
- {
- ADC_ClearStatusFlag(ADC2, ADC_FLAG_EOC);
- adcData2 = ADC_ReadConversionValue(ADC2);
- }
- }
先通过串口printf打印出来看看,使用串口printf需要添加如下代码
- #define DEBUG_USART TINY_COM1
- #if defined (__CC_ARM) || defined (__ICCARM__) || (defined(__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050))
- int fputc(int ch, FILE* f)
- {
- USART_TxData(DEBUG_USART, (uint8_t)ch);
- while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
- return (ch);
- }
- #elif defined (__GNUC__)
- int __io_putchar(int ch)
- {
- USART_TxData(DEBUG_USART, ch);
- while (USART_ReadStatusFlag(DEBUG_USART, USART_FLAG_TXBE) == RESET);
- return ch;
- }
- int _write(int file, char* ptr, int len)
- {
- int i;
- for (i = 0; i < len; i++)
- {
- __io_putchar(*ptr++);
- }
- return len;
- }
- #else
- #warning Not supported compiler type
- #endif
并勾选Use MicroLIB
如果勾选后编译出现这个错误,点击rebuild重新完整编译一下就行了
最后看看读取到的adc数据
接下来修改鼠标例程的代码,实现用摇杆控制鼠标移动,原来的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位有符号数正数向前滚动负数向后滚动
了解了这些也就知道该怎么改了,修改后的鼠标代码
- void USB_DevUserApplication(void)
- {
- static uint8_t userAppState = USER_APP_INIT;
- static uint8_t interval = 0;
- static int8_t report[4] = { 0 };
- switch (userAppState)
- {
- case USER_APP_INIT:
- interval = USBD_HID_ReadInterval(&gUsbDeviceHS);
- report[0] = 0;
- report[1] = 0;
- report[2] = 0;
- report[3] = 0;
- userAppState = USER_APP_RUN;
- break;
- case USER_APP_RUN:
- if (!APM_TINY_PBGetState(BUTTON_KEY1))
- {
- APM_DelayMs(10);
- if (!APM_TINY_PBGetState(BUTTON_KEY1))
- {
- report[0] |= 0x02;
- }
- }
- else
- {
- report[0] &= 0xFD;
- }
- if (!APM_TINY_PBGetState(BUTTON_KEY2))
- {
- APM_DelayMs(10);
- if (!APM_TINY_PBGetState(BUTTON_KEY2))
- {
- report[0] |= 0x01;
- }
- }
- else
- {
- report[0] &= 0xFE;
- }
- report[1] = 0;
- report[2] = 0;
- if(adcData1 > 2197 || adcData1 < 1897)
- {
- report[1] = (2047 - adcData1)*15/2047;
- }
- if(adcData2 > 2197 || adcData2 < 1897)
- {
- report[2] = (adcData2 - 2047)*15/2047;
- }
-
- USBD_HID_TxReport(&gUsbDeviceHS, (uint8_t*)report, 4);
- APM_DelayMs(interval);
- break;
- }
- }
编译烧录查看效果
摇杆控制鼠标移动
左右按键,左键单击双击右键单击
|