返回列表 发新帖我要提问本帖赏金: 70.00元(功能说明)

[AT32F405] 【AT-START-F405测评】+红外+USB kyeboard控制电脑刷抖音

[复制链接]
4882|7
 楼主| xiaoqi976633690 发表于 2024-5-5 17:20 | 显示全部楼层 |阅读模式
本帖最后由 xiaoqi976633690 于 2024-5-5 17:20 编辑

#申请原创# #有奖活动# #申请开发板#
一、项目描述

1、项目介绍
该项目基于AT-START-F405 V1.0 板载了AT32F405RCT7-7芯片,外设配置LED灯,按钮,两组USB type-C和Type-A的连接器。
并自带自带嵌入式调试/烧录工具AT-Link-EZ。
外围只需要简单的IR模块+IR遥控就可以搭建一个简易的基于红外控制的usb键盘。
2、设计思路
a.红外接收部分基于TIMEER3捕获红外NEC解码。
b.USB部分使用USB device 配置为 keyboard。
3、硬件
a.AT-START-F405 V1.0
b.IR接受模块
c.IR多媒体遥控

二、软件流程图及各功能对应的主要代码片段及说明
1、流程图
01.png
2、代码片段说明
NEC红外协议编码原理这里不做过多解释。
定时器初始化要特别注意分频系数
02.png
GPIO复用PB5 MUX1
03.png
1、初始化红外
  1. void infrared_receiver_init(void)
  2. {
  3.   gpio_init_type gpio_init_struct;
  4.   tmr_input_config_type  tmr_input_config_struct;
  5.   crm_clocks_freq_type   crm_clock_freq;

  6.   /* init infrared receiver fifo */
  7.   infrared_receiver_fifo_init();

  8.   /* enable tmr3/gpioa clock */
  9.   crm_periph_clock_enable(IR_TMR_CLK, TRUE);
  10.   crm_periph_clock_enable(IR_GPIO_CLK, TRUE);

  11.   /* timer input pin Configuration */
  12.   gpio_init_struct.gpio_pins = IR_GPIO_PIN;
  13.   gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  14.   gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  15.   gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  16.   gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  17.   gpio_init(IR_GPIO_PORT, &gpio_init_struct);

  18.   gpio_pin_mux_config(IR_GPIO_PORT, IR_GPIO_PINS_SOURCE, IR_GPIO_MUX);

  19.   /* get the system frequency value */
  20.   crm_clocks_freq_get(&crm_clock_freq);

  21.   /* tmr counter mode configuration */
  22. // tmr_base_init(IR_TMRx, 6000, crm_clock_freq.apb1_freq / 1000000);
  23.         tmr_base_init(IR_TMRx, 6000,215);//改为分频215
  24.   tmr_cnt_dir_set(IR_TMRx, TMR_COUNT_UP);

  25.   /* configure tmr channel to get clock signal */
  26.   tmr_input_config_struct.input_channel_select = IR_TMR_CHANNEL;
  27.   tmr_input_config_struct.input_mapped_select = TMR_CC_CHANNEL_MAPPED_DIRECT;
  28.   tmr_input_config_struct.input_polarity_select = TMR_INPUT_RISING_EDGE;
  29.   tmr_input_channel_init(IR_TMRx, &tmr_input_config_struct, TMR_CHANNEL_INPUT_DIV_1);

  30.   /* enable capture interrupt */
  31.   tmr_interrupt_enable(IR_TMRx, IR_TMR_CHANNEL_INT, TRUE);

  32.   /* disable overflow interrupt */
  33.   tmr_interrupt_enable(IR_TMRx, TMR_OVF_INT, FALSE);

  34.   /* interrupt nvic init */
  35.   nvic_irq_enable(IR_TMR_IRQn, 1, 0);

  36.   /* enable tmr */
  37.   tmr_counter_enable(IR_TMRx, TRUE);
  38. }
2、中断接收解码
  1. void infrared_receiver_data_deal(void)
  2. {
  3.   uint32_t value;
  4.   /* input capture event occurs */
  5.   if(tmr_flag_get(IR_TMRx, IR_TMR_CHANNEL_FLAG) != RESET)
  6.   {
  7.     /* clear input capture flag */
  8.     tmr_flag_clear(IR_TMRx, IR_TMR_CHANNEL_FLAG);

  9.     /* clear overflow flag */
  10.     tmr_flag_clear(IR_TMRx, TMR_OVF_FLAG);

  11.     /* enable overflow interrupt */
  12.     tmr_interrupt_enable(IR_TMRx, TMR_OVF_INT, TRUE);

  13.     /* rising edge capture */
  14.     if(IR_GPIO_READ())
  15.     {
  16.       /* clear the counter */
  17.       tmr_counter_value_set(IR_TMRx, 0);

  18.       /* configure capture mode as falling edge capture */
  19.       tmr_output_channel_polarity_set(IR_TMRx, IR_TMR_CHANNEL, TMR_POLARITY_ACTIVE_LOW);
  20.     }
  21.     /* falling edge capture */
  22.     else
  23.     {
  24.       /* get capture counter */
  25.       value = tmr_channel_value_get(IR_TMRx, IR_TMR_CHANNEL);

  26.       /* configure capture mode as rising edge capture */
  27.       tmr_output_channel_polarity_set(IR_TMRx, IR_TMR_CHANNEL, TMR_POLARITY_ACTIVE_HIGH);

  28.       /* received start code */
  29.       if((value > 4200) && (value < 4700))
  30.       {
  31.                                 at32_led_toggle(LED3);
  32.         ir_data = 0;
  33.       }
  34.       /* received repeat code */
  35.       else if((value > 2000) && (value < 2600))
  36.       {
  37.                                 
  38.         /* analysis data */
  39.         infrared_receiver_key_deal(ir_data);
  40.       }
  41.       /* received bit 0 */
  42.       else if((value > 300) && (value < 800))
  43.       {
  44.         ir_data <<= 1;
  45.       }
  46.       /* received bit 1 */
  47.       else if((value > 1400) && (value < 1800))
  48.       {
  49.         ir_data <<= 1;
  50.         ir_data |= 1;
  51.       }
  52.     }
  53.   }

  54.   /* overflow event occurs, 6ms , receive complete */
  55.   else if(tmr_flag_get(IR_TMRx, TMR_OVF_FLAG) != RESET)
  56.   {
  57.     /* clear overflow flag */
  58.     tmr_flag_clear(IR_TMRx, TMR_OVF_FLAG);

  59.     /* disable overflow interrupt */
  60.     tmr_interrupt_enable(IR_TMRx, TMR_OVF_INT, FALSE);

  61.     /* configure capture mode as rising edge capture */
  62.     tmr_output_channel_polarity_set(IR_TMRx, IR_TMR_CHANNEL, TMR_POLARITY_ACTIVE_HIGH);

  63.     /* analysis data */
  64.     infrared_receiver_key_deal(ir_data);
  65.   }
  66. }
3
USB device部分
  USB基于examples\usb_device\keyboard 例程修改
  在keyboard_class.c增加2个函数用于发送键值和组合按键

  1. void keyboard_send(void *udev, uint8_t ascii_code)
  2. {
  3.           usbd_core_type *pudev = (usbd_core_type *)udev;
  4.                 keyboard_type *pkeyboard = (keyboard_type *)pudev->class_handler->pdata;
  5.          while(1)
  6.          {
  7.                         if(pkeyboard->g_u8tx_completed == 1)
  8.                                 {
  9.                                         pkeyboard->g_u8tx_completed = 0;
  10.                                         pkeyboard->keyboard_buf[0] = 0;
  11.                                         pkeyboard->keyboard_buf[2] = ascii_code;
  12.                                         usb_keyboard_class_send_report(udev, pkeyboard->keyboard_buf, 8);
  13.                                         break;
  14.                                 }
  15.                                 
  16.         }
  17. }
  18. /*
  19. 键盘发送给PC的数据每次8个字节:BYTE0 BYTE1 BYTE2 BYTE3 BYTE4 BYTE5 BYTE6 BYTE7。定义分别是:
  20. BYTE0 --
  21. |--bit0: Left Control 0x01
  22. |--bit1: Left Shift 0x02
  23. |--bit2: Left Alt 0x04
  24. |--bit3: Left GUI(win键) 0x08
  25. |--bit4: Right Control 0x10
  26. |--bit5: Right Shift 0x20
  27. |--bit6: Right Alt 0x40
  28. |--bit7: Right GUI 0x80
  29. */
  30. void keyboard_send_composite(void *udev,uint8_t BYTE0, uint8_t ascii_code)
  31. {
  32.           usbd_core_type *pudev = (usbd_core_type *)udev;
  33.                 keyboard_type *pkeyboard = (keyboard_type *)pudev->class_handler->pdata;
  34.          while(1)
  35.          {
  36.                         if(pkeyboard->g_u8tx_completed == 1)
  37.                                 {
  38.                                         pkeyboard->g_u8tx_completed = 0;
  39.                                         pkeyboard->keyboard_buf[0] = BYTE0;
  40.                                         pkeyboard->keyboard_buf[2] = ascii_code;
  41.                                         usb_keyboard_class_send_report(udev, pkeyboard->keyboard_buf, 8);
  42.                                         break;
  43.                                 }
  44.                                 
  45.         }
  46. }

键盘键值
  1. #define KEY_NULL 0x00  

  2. #define KEY_A 0x04 //A  
  3. #define KEY_B 0x05 //B  
  4. #define KEY_C 0x06 //C  
  5. #define KEY_D 0x07 //D  
  6. #define KEY_E 0x08 //E  
  7. #define KEY_F 0x09 //F  
  8. #define KEY_G 0x0A //G  
  9. #define KEY_H 0x0B //H  
  10. #define KEY_I 0x0C //I  
  11. #define KEY_J 0x0D //J  
  12. #define KEY_K 0x0E //K  
  13. #define KEY_L 0x0F //L  
  14. #define KEY_M 0x10 //M  
  15. #define KEY_N 0x11 //N  
  16. #define KEY_O 0x12 //O  
  17. #define KEY_P 0x13 //P  
  18. #define KEY_Q 0x14 //Q  
  19. #define KEY_R 0x15 //R  
  20. #define KEY_S 0x16 //S  
  21. #define KEY_T 0x17 //T  
  22. #define KEY_U 0x18 //U  
  23. #define KEY_V 0x19 //V  
  24. #define KEY_W 0x1A //W  
  25. #define KEY_X 0x1B //X  
  26. #define KEY_Y 0x1C //Y  
  27. #define KEY_Z 0x1D //Z  

  28. #define KEY_1 0x1E //1 !  
  29. #define KEY_2 0x1F //2 [url=home.php?mod=space&uid=72445]@[/url]  
  30. #define KEY_3 0x20 //3 #
  31. #define KEY_4 0x21 //4 $
  32. #define KEY_5 0x22 //5 %
  33. #define KEY_6 0x23 //6 ^
  34. #define KEY_7 0x24 //7 &  
  35. #define KEY_8 0x25 //8 *
  36. #define KEY_9 0x26 //9 (
  37. #define KEY_0 0x27 //0 )

  38. #define KEY_ENTER 0x28  

  39. #define KEY_ESC 0x29  

  40. #define KEY_BACKSPACE 0x2A  

  41. #define KEY_TAB 0x2B  

  42. #define KEY_SPACE 0x2C  

  43. #define KEY_SUB 0x2D // - and _  

  44. #define KEY_EQUAL 0x2E // = and +  

  45. #define KEY_LEFT_BRACKET 0x2F // \[ and {  

  46. #define KEY_RIGHT_BRACKET 0x30 // \] and }  

  47. #define KEY_VERTICAL_LINE 0x31 // "\" and |  

  48. #define KEY_WAVE 0x32 // \` and ~  

  49. #define KEY_SEMICOLON 0x33 // ; and :  

  50. #define KEY_QUOTE 0x34 // ' and "  

  51. #define KEY_THROW 0x35 // ~ and \`  

  52. #define KEY_COMMA 0x36 // , and <  

  53. #define KEY_DOT 0x37 // . and >  

  54. #define KEY_QUESTION 0x38 // / and ?  

  55. #define KEY_CAPS_LOCK 0x39  

  56. #define KEY_F1 0x3A  

  57. #define KEY_F2 0x3B  

  58. #define KEY_F3 0x3C  

  59. #define KEY_F4 0x3D  

  60. #define KEY_F5 0x3E  

  61. #define KEY_F6 0x3F  

  62. #define KEY_F7 0x40  

  63. #define KEY_F8 0x41  

  64. #define KEY_F9 0x42  

  65. #define KEY_F10 0x43  

  66. #define KEY_F11 0x44  

  67. #define KEY_F12 0x45  

  68. #define KEY_PRT_SCR 0x46  

  69. #define KEY_SCOLL_LOCK 0x47  

  70. #define KEY_PAUSE 0x48  

  71. #define KEY_INS 0x49  

  72. #define KEY_HOME 0x4A  

  73. #define KEY_PAGEUP 0x4B  

  74. #define KEY_DEL 0x4C  

  75. #define KEY_END 0x4D  

  76. #define KEY_PAGEDOWN 0x4E  

  77. #define KEY_RIGHT_ARROW 0x4F  

  78. #define KEY_LEFT_ARROW 0x50  

  79. #define KEY_DOWN_ARROW 0x51  

  80. #define KEY_UP_ARROW 0x52  

  81. #define KEY_PAD_NUMLOCK 0x53  

  82. #define KEY_PAD_DIV 0x54 // /  

  83. #define KEY_PAD_MUL 0x55 // \*  

  84. #define KEY_PAD_SUB 0x56 // -  

  85. #define KEY_PAD_ADD 0x57 // +  

  86. #define KEY_PAD_ENTER 0x58
4、main函数

  1. int main(void)
  2. {
  3.   __IO uint32_t delay_index = 0;
  4.         system_clock_config();
  5.   nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
  6.         delay_init();
  7.   

  8.   at32_board_init();
  9.         uart_print_init(115200);
  10.   infrared_receiver_init();
  11.         
  12.   /* usb gpio config */
  13.   usb_gpio_config();

  14. #ifdef USB_LOW_POWER_WAKUP
  15.   /* enable pwc and bpr clock */
  16.   crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
  17.   button_exint_init();
  18.   usb_low_power_wakeup_config();
  19. #endif

  20.   /* enable otg clock */
  21.   crm_periph_clock_enable(OTG_CLOCK, TRUE);

  22.   /* select usb 48m clcok source */
  23.   usb_clock48m_select(USB_CLK_HEXT);

  24.   /* enable otg irq */
  25.   nvic_irq_enable(OTG_IRQ, 0, 0);

  26.   /* init usb */
  27.   usbd_init(&otg_core_struct,
  28.             USB_SPEED_CORE_ID,
  29.             USB_ID,
  30.             &keyboard_class_handler,
  31.             &keyboard_desc_handler);
  32.   at32_led_on(LED2);
  33.   at32_led_on(LED3);
  34.   at32_led_on(LED4);
  35.         printf("IR_DATA=0x%08x\n", ir_data);
  36.   while(1)
  37.   {
  38.                
  39.         if (infrared_receive(&ir_value) == SUCCESS)
  40.                 {
  41.                         printf("IR_DATA=0x%08x\n", ir_data);
  42.                         switch(ir_data)
  43.                         {
  44.                                 case 0x00ff02fd :        //下箭头
  45.                                         keyboard_send(&otg_core_struct.dev,0);        
  46.                                         keyboard_send(&otg_core_struct.dev,KEY_DOWN_ARROW);        
  47.                                         keyboard_send(&otg_core_struct.dev,0);
  48.                                         ir_data=0;
  49.                                         break;
  50.                                 case 0x00ffe21d :        //下箭头
  51.                                         keyboard_send(&otg_core_struct.dev,0);        
  52.                                         keyboard_send(&otg_core_struct.dev,KEY_DOWN_ARROW);        
  53.                                         keyboard_send(&otg_core_struct.dev,0);
  54.                                         ir_data=0;
  55.                                         break;
  56.                                 case 0x00ffa25d :        //上箭头
  57.                                         keyboard_send(&otg_core_struct.dev,0);        
  58.                                         keyboard_send(&otg_core_struct.dev,KEY_UP_ARROW);        
  59.                                         keyboard_send(&otg_core_struct.dev,0);
  60.                                         ir_data=0;
  61.                                         break;                                                
  62.                                 case 0x00ff22dd :        //上箭头
  63.                                         keyboard_send(&otg_core_struct.dev,0);        
  64.                                         keyboard_send(&otg_core_struct.dev,KEY_UP_ARROW);        
  65.                                         keyboard_send(&otg_core_struct.dev,0);
  66.                                         ir_data=0;
  67.                                         break;                        
  68.                                 case 0x00ff906f :        //老板键
  69.                                         keyboard_send(&otg_core_struct.dev,0);        
  70.                                         keyboard_send_composite(&otg_core_struct.dev,0x08,0x07);        
  71.                                         keyboard_send(&otg_core_struct.dev,0);
  72.                                         ir_data=0;
  73.                                         break;        
  74.                                 case 0x00ffc23d :        //暂停
  75.                                         keyboard_send(&otg_core_struct.dev,0);        
  76.                                         keyboard_send(&otg_core_struct.dev,KEY_SPACE);        
  77.                                         keyboard_send(&otg_core_struct.dev,0);
  78.                                         ir_data=0;
  79.                                         break;                                       
  80.                                 case 0x00ffe01f :        //点赞
  81.                                         keyboard_send(&otg_core_struct.dev,0);        
  82.                                         keyboard_send(&otg_core_struct.dev,KEY_Z);        
  83.                                         keyboard_send(&otg_core_struct.dev,0);
  84.                                         ir_data=0;
  85.                                         break;               
  86.                                 case 0x00ffa857 :        //收藏
  87.                                         keyboard_send(&otg_core_struct.dev,0);        
  88.                                         keyboard_send(&otg_core_struct.dev,KEY_C);        
  89.                                         keyboard_send(&otg_core_struct.dev,0);
  90.                                         ir_data=0;
  91.                                         break;               
  92.                                 case 0x00ff629d :        //进入直播间或查看博主更多视频
  93.                                         keyboard_send(&otg_core_struct.dev,0);        
  94.                                         keyboard_send(&otg_core_struct.dev,KEY_F);        
  95.                                         keyboard_send(&otg_core_struct.dev,0);
  96.                                         ir_data=0;
  97.                                         break;        
  98.                                 
  99.                                 
  100.                         }

  101.                 }
  102.     if(at32_button_press() == USER_BUTTON)
  103.     {               
  104.       if(usbd_connect_state_get(&otg_core_struct.dev) == USB_CONN_STATE_CONFIGURED)
  105.       {
  106.                                 keyboard_send(&otg_core_struct.dev,0);        
  107.                                 keyboard_send(&otg_core_struct.dev,0x51);        
  108.                                 keyboard_send(&otg_core_struct.dev,0);
  109.                                 //老板键win+D显示桌面
  110.                                 keyboard_send(&otg_core_struct.dev,0);        
  111.                                 keyboard_send_composite(&otg_core_struct.dev,0x08,0x07);        
  112.                                 keyboard_send(&otg_core_struct.dev,0);
  113.        // keyboard_send_string(&otg_core_struct.dev, (uint8_t *)" Keyboard Demo\r\n", 16);
  114.       }
  115.       /* remote wakeup */
  116.       if(usbd_connect_state_get(&otg_core_struct.dev) == USB_CONN_STATE_SUSPENDED
  117.         && (otg_core_struct.dev.remote_wakup == 1))
  118.       {
  119.         usbd_remote_wakeup(&otg_core_struct.dev);
  120.       }
  121.     }


  122. #ifdef USB_LOW_POWER_WAKUP
  123.      /* enter deep sleep */
  124.     if(((keyboard_type *)(otg_core_struct.dev.class_handler->pdata))->hid_suspend_flag == 1)
  125.     {
  126.       __disable_irq();
  127.       
  128.       if(OTG_PCGCCTL(otg_core_struct.usb_reg)->pcgcctl_bit.suspendm == 1
  129.          && usb_suspend_status_get(otg_core_struct.usb_reg) == 1)
  130.       {
  131.         at32_led_off(LED2);
  132.         at32_led_off(LED3);
  133.         at32_led_off(LED4);
  134. #ifdef USB_OTG_HS
  135.         otg_core_struct.usb_reg->gccfg_bit.wait_clk_rcv = TRUE;
  136. #endif
  137.         /* congfig the voltage regulator mode */
  138.         pwc_voltage_regulate_set(PWC_REGULATOR_ON);

  139.         /* enter deep sleep mode */
  140.         pwc_deep_sleep_mode_enter(PWC_DEEP_SLEEP_ENTER_WFI);
  141.         /* wait clock stable */
  142.         delay_us(120);
  143.       
  144.         system_clock_recover();
  145. #ifdef USB_OTG_HS
  146.         otg_core_struct.usb_reg->gccfg_bit.wait_clk_rcv = FALSE;
  147.         delay_ms(2);
  148.         usb_open_phy_clk(otg_core_struct.usb_reg);
  149. #endif
  150.       }
  151.       ((keyboard_type *)(otg_core_struct.dev.class_handler->pdata))->hid_suspend_flag = 0;
  152.       
  153.       __enable_irq();
  154.       
  155.       at32_led_on(LED2);
  156.       at32_led_on(LED3);
  157.       at32_led_on(LED4);
  158.     }
  159. #endif

  160.   }
  161. }

三、实验结果
视频地址https://www.bilibili.com/video/BV1ZJ4m1N7of/
串口打印
  1. IR_DATA=0x00ffe21d
  2. IR_DATA=0x00ffe21d
  3. IR_DATA=0x00ffe21d
  4. IR_DATA=0x00ffe21d
  5. IR_DATA=0x00ffe21d
  6. IR_DATA=0x00ffe21d
  7. IR_DATA=0x00ffe21d
  8. IR_DATA=0x00ff629d
  9. IR_DATA=0x00ffe01f
  10. IR_DATA=0x00ffa857
  11. IR_DATA=0x00ffe21d
  12. IR_DATA=0x00ffe21d
  13. IR_DATA=0x00ffe21d
  14. IR_DATA=0x00ff22dd
  15. IR_DATA=0x00ff02fd
  16. IR_DATA=0x00ff906f
  17. IR_DATA=0x00ff906f
  18. IR_DATA=0x00ff629d
  19. IR_DATA=0x00ff629d


打赏榜单

ArteryMCU 打赏了 50.00 元 2024-06-07
理由:[F405开发板评测活动]内容优质

ArterySW 打赏了 20.00 元 2024-05-07
理由:作品优秀

 楼主| xiaoqi976633690 发表于 2024-5-5 17:24 | 显示全部楼层
附件在此

keyboard.zip

2.99 MB, 下载次数: 18

trucyw 发表于 2024-5-6 07:54 | 显示全部楼层
不错不错
qintian0303 发表于 2024-5-6 09:02 | 显示全部楼层
已收藏,后边准备做一个键盘的模拟器,准备参考一下,非常有意义
[鑫森淼焱垚] 发表于 2024-5-6 19:03 | 显示全部楼层
gangong 发表于 2024-10-30 20:41 | 显示全部楼层
楼主棒
micoccd 发表于 2024-11-16 18:40 | 显示全部楼层
这个就那种以前用遥控器看电视的感觉了
菜鸟的第一步 发表于 2024-11-24 19:09 | 显示全部楼层
学习的意义大于这个功能的意义
您需要登录后才可以回帖 登录 | 注册

本版积分规则

35

主题

205

帖子

2

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