发新帖本帖赏金 20.00元(功能说明)我要提问
返回列表
打印
[AT32F405]

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

[复制链接]
842|4
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
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、流程图
2、代码片段说明
NEC红外协议编码原理这里不做过多解释。
定时器初始化要特别注意分频系数
GPIO复用PB5 MUX1
1、初始化红外
void infrared_receiver_init(void)
{
  gpio_init_type gpio_init_struct;
  tmr_input_config_type  tmr_input_config_struct;
  crm_clocks_freq_type   crm_clock_freq;

  /* init infrared receiver fifo */
  infrared_receiver_fifo_init();

  /* enable tmr3/gpioa clock */
  crm_periph_clock_enable(IR_TMR_CLK, TRUE);
  crm_periph_clock_enable(IR_GPIO_CLK, TRUE);

  /* timer input pin Configuration */
  gpio_init_struct.gpio_pins = IR_GPIO_PIN;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  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(IR_GPIO_PORT, &gpio_init_struct);

  gpio_pin_mux_config(IR_GPIO_PORT, IR_GPIO_PINS_SOURCE, IR_GPIO_MUX);

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

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

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

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

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

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

  /* enable tmr */
  tmr_counter_enable(IR_TMRx, TRUE);
}
2、中断接收解码
void infrared_receiver_data_deal(void)
{
  uint32_t value;
  /* input capture event occurs */
  if(tmr_flag_get(IR_TMRx, IR_TMR_CHANNEL_FLAG) != RESET)
  {
    /* clear input capture flag */
    tmr_flag_clear(IR_TMRx, IR_TMR_CHANNEL_FLAG);

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

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

    /* rising edge capture */
    if(IR_GPIO_READ())
    {
      /* clear the counter */
      tmr_counter_value_set(IR_TMRx, 0);

      /* configure capture mode as falling edge capture */
      tmr_output_channel_polarity_set(IR_TMRx, IR_TMR_CHANNEL, TMR_POLARITY_ACTIVE_LOW);
    }
    /* falling edge capture */
    else
    {
      /* get capture counter */
      value = tmr_channel_value_get(IR_TMRx, IR_TMR_CHANNEL);

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

      /* received start code */
      if((value > 4200) && (value < 4700))
      {
                                at32_led_toggle(LED3);
        ir_data = 0;
      }
      /* received repeat code */
      else if((value > 2000) && (value < 2600))
      {
                                
        /* analysis data */
        infrared_receiver_key_deal(ir_data);
      }
      /* received bit 0 */
      else if((value > 300) && (value < 800))
      {
        ir_data <<= 1;
      }
      /* received bit 1 */
      else if((value > 1400) && (value < 1800))
      {
        ir_data <<= 1;
        ir_data |= 1;
      }
    }
  }

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

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

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

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

void keyboard_send(void *udev, uint8_t ascii_code)
{
          usbd_core_type *pudev = (usbd_core_type *)udev;
                keyboard_type *pkeyboard = (keyboard_type *)pudev->class_handler->pdata;
         while(1)
         {
                        if(pkeyboard->g_u8tx_completed == 1)
                                {
                                        pkeyboard->g_u8tx_completed = 0;
                                        pkeyboard->keyboard_buf[0] = 0;
                                        pkeyboard->keyboard_buf[2] = ascii_code;
                                        usb_keyboard_class_send_report(udev, pkeyboard->keyboard_buf, 8);
                                        break;
                                }
                                
        }
}
/*
键盘发送给PC的数据每次8个字节:BYTE0 BYTE1 BYTE2 BYTE3 BYTE4 BYTE5 BYTE6 BYTE7。定义分别是:
BYTE0 --
|--bit0: Left Control 0x01
|--bit1: Left Shift 0x02
|--bit2: Left Alt 0x04
|--bit3: Left GUI(win键) 0x08
|--bit4: Right Control 0x10
|--bit5: Right Shift 0x20
|--bit6: Right Alt 0x40
|--bit7: Right GUI 0x80
*/
void keyboard_send_composite(void *udev,uint8_t BYTE0, uint8_t ascii_code)
{
          usbd_core_type *pudev = (usbd_core_type *)udev;
                keyboard_type *pkeyboard = (keyboard_type *)pudev->class_handler->pdata;
         while(1)
         {
                        if(pkeyboard->g_u8tx_completed == 1)
                                {
                                        pkeyboard->g_u8tx_completed = 0;
                                        pkeyboard->keyboard_buf[0] = BYTE0;
                                        pkeyboard->keyboard_buf[2] = ascii_code;
                                        usb_keyboard_class_send_report(udev, pkeyboard->keyboard_buf, 8);
                                        break;
                                }
                                
        }
}

键盘键值
#define KEY_NULL 0x00  

#define KEY_A 0x04 //A  
#define KEY_B 0x05 //B  
#define KEY_C 0x06 //C  
#define KEY_D 0x07 //D  
#define KEY_E 0x08 //E  
#define KEY_F 0x09 //F  
#define KEY_G 0x0A //G  
#define KEY_H 0x0B //H  
#define KEY_I 0x0C //I  
#define KEY_J 0x0D //J  
#define KEY_K 0x0E //K  
#define KEY_L 0x0F //L  
#define KEY_M 0x10 //M  
#define KEY_N 0x11 //N  
#define KEY_O 0x12 //O  
#define KEY_P 0x13 //P  
#define KEY_Q 0x14 //Q  
#define KEY_R 0x15 //R  
#define KEY_S 0x16 //S  
#define KEY_T 0x17 //T  
#define KEY_U 0x18 //U  
#define KEY_V 0x19 //V  
#define KEY_W 0x1A //W  
#define KEY_X 0x1B //X  
#define KEY_Y 0x1C //Y  
#define KEY_Z 0x1D //Z  

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

#define KEY_ENTER 0x28  

#define KEY_ESC 0x29  

#define KEY_BACKSPACE 0x2A  

#define KEY_TAB 0x2B  

#define KEY_SPACE 0x2C  

#define KEY_SUB 0x2D // - and _  

#define KEY_EQUAL 0x2E // = and +  

#define KEY_LEFT_BRACKET 0x2F // \[ and {  

#define KEY_RIGHT_BRACKET 0x30 // \] and }  

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

#define KEY_WAVE 0x32 // \` and ~  

#define KEY_SEMICOLON 0x33 // ; and :  

#define KEY_QUOTE 0x34 // ' and "  

#define KEY_THROW 0x35 // ~ and \`  

#define KEY_COMMA 0x36 // , and <  

#define KEY_DOT 0x37 // . and >  

#define KEY_QUESTION 0x38 // / and ?  

#define KEY_CAPS_LOCK 0x39  

#define KEY_F1 0x3A  

#define KEY_F2 0x3B  

#define KEY_F3 0x3C  

#define KEY_F4 0x3D  

#define KEY_F5 0x3E  

#define KEY_F6 0x3F  

#define KEY_F7 0x40  

#define KEY_F8 0x41  

#define KEY_F9 0x42  

#define KEY_F10 0x43  

#define KEY_F11 0x44  

#define KEY_F12 0x45  

#define KEY_PRT_SCR 0x46  

#define KEY_SCOLL_LOCK 0x47  

#define KEY_PAUSE 0x48  

#define KEY_INS 0x49  

#define KEY_HOME 0x4A  

#define KEY_PAGEUP 0x4B  

#define KEY_DEL 0x4C  

#define KEY_END 0x4D  

#define KEY_PAGEDOWN 0x4E  

#define KEY_RIGHT_ARROW 0x4F  

#define KEY_LEFT_ARROW 0x50  

#define KEY_DOWN_ARROW 0x51  

#define KEY_UP_ARROW 0x52  

#define KEY_PAD_NUMLOCK 0x53  

#define KEY_PAD_DIV 0x54 // /  

#define KEY_PAD_MUL 0x55 // \*  

#define KEY_PAD_SUB 0x56 // -  

#define KEY_PAD_ADD 0x57 // +  

#define KEY_PAD_ENTER 0x58
4、main函数

int main(void)
{
  __IO uint32_t delay_index = 0;
        system_clock_config();
  nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
        delay_init();
  

  at32_board_init();
        uart_print_init(115200);
  infrared_receiver_init();
        
  /* usb gpio config */
  usb_gpio_config();

#ifdef USB_LOW_POWER_WAKUP
  /* enable pwc and bpr clock */
  crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);
  button_exint_init();
  usb_low_power_wakeup_config();
#endif

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

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

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

  /* init usb */
  usbd_init(&otg_core_struct,
            USB_SPEED_CORE_ID,
            USB_ID,
            &keyboard_class_handler,
            &keyboard_desc_handler);
  at32_led_on(LED2);
  at32_led_on(LED3);
  at32_led_on(LED4);
        printf("IR_DATA=0x%08x\n", ir_data);
  while(1)
  {
               
        if (infrared_receive(&ir_value) == SUCCESS)
                {
                        printf("IR_DATA=0x%08x\n", ir_data);
                        switch(ir_data)
                        {
                                case 0x00ff02fd :        //下箭头
                                        keyboard_send(&otg_core_struct.dev,0);        
                                        keyboard_send(&otg_core_struct.dev,KEY_DOWN_ARROW);        
                                        keyboard_send(&otg_core_struct.dev,0);
                                        ir_data=0;
                                        break;
                                case 0x00ffe21d :        //下箭头
                                        keyboard_send(&otg_core_struct.dev,0);        
                                        keyboard_send(&otg_core_struct.dev,KEY_DOWN_ARROW);        
                                        keyboard_send(&otg_core_struct.dev,0);
                                        ir_data=0;
                                        break;
                                case 0x00ffa25d :        //上箭头
                                        keyboard_send(&otg_core_struct.dev,0);        
                                        keyboard_send(&otg_core_struct.dev,KEY_UP_ARROW);        
                                        keyboard_send(&otg_core_struct.dev,0);
                                        ir_data=0;
                                        break;                                                
                                case 0x00ff22dd :        //上箭头
                                        keyboard_send(&otg_core_struct.dev,0);        
                                        keyboard_send(&otg_core_struct.dev,KEY_UP_ARROW);        
                                        keyboard_send(&otg_core_struct.dev,0);
                                        ir_data=0;
                                        break;                        
                                case 0x00ff906f :        //老板键
                                        keyboard_send(&otg_core_struct.dev,0);        
                                        keyboard_send_composite(&otg_core_struct.dev,0x08,0x07);        
                                        keyboard_send(&otg_core_struct.dev,0);
                                        ir_data=0;
                                        break;        
                                case 0x00ffc23d :        //暂停
                                        keyboard_send(&otg_core_struct.dev,0);        
                                        keyboard_send(&otg_core_struct.dev,KEY_SPACE);        
                                        keyboard_send(&otg_core_struct.dev,0);
                                        ir_data=0;
                                        break;                                       
                                case 0x00ffe01f :        //点赞
                                        keyboard_send(&otg_core_struct.dev,0);        
                                        keyboard_send(&otg_core_struct.dev,KEY_Z);        
                                        keyboard_send(&otg_core_struct.dev,0);
                                        ir_data=0;
                                        break;               
                                case 0x00ffa857 :        //收藏
                                        keyboard_send(&otg_core_struct.dev,0);        
                                        keyboard_send(&otg_core_struct.dev,KEY_C);        
                                        keyboard_send(&otg_core_struct.dev,0);
                                        ir_data=0;
                                        break;               
                                case 0x00ff629d :        //进入直播间或查看博主更多视频
                                        keyboard_send(&otg_core_struct.dev,0);        
                                        keyboard_send(&otg_core_struct.dev,KEY_F);        
                                        keyboard_send(&otg_core_struct.dev,0);
                                        ir_data=0;
                                        break;        
                                
                                
                        }

                }
    if(at32_button_press() == USER_BUTTON)
    {               
      if(usbd_connect_state_get(&otg_core_struct.dev) == USB_CONN_STATE_CONFIGURED)
      {
                                keyboard_send(&otg_core_struct.dev,0);        
                                keyboard_send(&otg_core_struct.dev,0x51);        
                                keyboard_send(&otg_core_struct.dev,0);
                                //老板键win+D显示桌面
                                keyboard_send(&otg_core_struct.dev,0);        
                                keyboard_send_composite(&otg_core_struct.dev,0x08,0x07);        
                                keyboard_send(&otg_core_struct.dev,0);
       // keyboard_send_string(&otg_core_struct.dev, (uint8_t *)" Keyboard Demo\r\n", 16);
      }
      /* remote wakeup */
      if(usbd_connect_state_get(&otg_core_struct.dev) == USB_CONN_STATE_SUSPENDED
        && (otg_core_struct.dev.remote_wakup == 1))
      {
        usbd_remote_wakeup(&otg_core_struct.dev);
      }
    }


#ifdef USB_LOW_POWER_WAKUP
     /* enter deep sleep */
    if(((keyboard_type *)(otg_core_struct.dev.class_handler->pdata))->hid_suspend_flag == 1)
    {
      __disable_irq();
      
      if(OTG_PCGCCTL(otg_core_struct.usb_reg)->pcgcctl_bit.suspendm == 1
         && usb_suspend_status_get(otg_core_struct.usb_reg) == 1)
      {
        at32_led_off(LED2);
        at32_led_off(LED3);
        at32_led_off(LED4);
#ifdef USB_OTG_HS
        otg_core_struct.usb_reg->gccfg_bit.wait_clk_rcv = TRUE;
#endif
        /* congfig the voltage regulator mode */
        pwc_voltage_regulate_set(PWC_REGULATOR_ON);

        /* enter deep sleep mode */
        pwc_deep_sleep_mode_enter(PWC_DEEP_SLEEP_ENTER_WFI);
        /* wait clock stable */
        delay_us(120);
      
        system_clock_recover();
#ifdef USB_OTG_HS
        otg_core_struct.usb_reg->gccfg_bit.wait_clk_rcv = FALSE;
        delay_ms(2);
        usb_open_phy_clk(otg_core_struct.usb_reg);
#endif
      }
      ((keyboard_type *)(otg_core_struct.dev.class_handler->pdata))->hid_suspend_flag = 0;
      
      __enable_irq();
      
      at32_led_on(LED2);
      at32_led_on(LED3);
      at32_led_on(LED4);
    }
#endif

  }
}

三、实验结果
视频地址https://www.bilibili.com/video/BV1ZJ4m1N7of/
串口打印
IR_DATA=0x00ffe21d
IR_DATA=0x00ffe21d
IR_DATA=0x00ffe21d
IR_DATA=0x00ffe21d
IR_DATA=0x00ffe21d
IR_DATA=0x00ffe21d
IR_DATA=0x00ffe21d
IR_DATA=0x00ff629d
IR_DATA=0x00ffe01f
IR_DATA=0x00ffa857
IR_DATA=0x00ffe21d
IR_DATA=0x00ffe21d
IR_DATA=0x00ffe21d
IR_DATA=0x00ff22dd
IR_DATA=0x00ff02fd
IR_DATA=0x00ff906f
IR_DATA=0x00ff906f
IR_DATA=0x00ff629d
IR_DATA=0x00ff629d


使用特权

评论回复

打赏榜单

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

沙发
xiaoqi976633690|  楼主 | 2024-5-5 17:24 | 只看该作者
附件在此

keyboard.zip

2.99 MB

使用特权

评论回复
板凳
trucyw| | 2024-5-6 07:54 | 只看该作者
不错不错

使用特权

评论回复
地板
qintian0303| | 2024-5-6 09:02 | 只看该作者
已收藏,后边准备做一个键盘的模拟器,准备参考一下,非常有意义

使用特权

评论回复
5
[鑫森淼焱垚]| | 2024-5-6 19:03 | 只看该作者
NICE

使用特权

评论回复
发新帖 本帖赏金 20.00元(功能说明)我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

28

主题

167

帖子

2

粉丝