本帖最后由 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;
- }
-
- }
- }
键盘键值
- 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
|