发新帖本帖赏金 60.00元(功能说明)我要提问
返回列表
打印
[应用相关]

【每周分享】STM32F103核心板+HX1838实现红外遥控电脑

[复制链接]
15959|3
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
#申请原创# #技术资源# @21小跑堂  红外遥控是利用红外光进行通信的设备,由红外LED将调制后的信号发出,由专用的红外接收头进行解调输出。红外线的波长在可见光范围外,所以人眼是看不到的。在生活中电视机空调等设备都可以用红外遥控器来控制,正好手里有个HX1838红外接收器和遥控器,想着也给电脑做个红外遥控。
用到的设备:HX1838红外接收器,红外遥控,引出USB的STM32F103核心板

基本原理就是用STM32F103核心板模拟USB键盘,解析HX1838收到的红外信号后转为按键命令发送给电脑
先来实现对红外信号的解析,要解析红外信号就要用到红外接收器,红外接收器是一种能够接收红外光信号并将其转换为电信号的元件。红外接收器会对接收到的红外光信号进行解析,以还原出原始的指令或数据。红外接收头通常被集成在一个元件中,内部包含光敏二极管等关键部件,以及用于信号放大、解调等功能的电路。这里用到的HX1838模块是可接收标准38KHz调制的遥控器信号,通过对进行编程,即可实现对遥控器信号的解码操作。
这套遥控套件使用的是NEC编码,关于NEC编码的介绍可以看这篇帖子 【每周分享】红外遥控中常用的NEC编码https://bbs.21ic.com/icview-3409956-1-1.html
HX1838模块接收到38KHz的红外PWM信号时输出低电平,否则输出高电平,这点和NEC编码中相反,编程时需要注意,程序通过高低电平的时间来解析红外数据。
配套遥控器的按键码

先根据NEC编码规则写出解析红外信号的代码
enum
{
    IR_CODE_STEP_IDLE = 0,
    IR_CODE_STEP_START,
    IR_CODE_STEP_DATA,
    IR_CODE_STEP_STOP,
};
enum
{
    IR_CODE_FLAG_NONE = 0,
    IR_CODE_FLAG_CMD,
    IR_CODE_FLAG_REPEAT,
};
#define MAX_TIME_DIFF 60
uint32_t IR_time_us = 0;
uint32_t IR_H_time_us = 0;
uint32_t IR_L_time_us = 0;
uint8_t IR_code[4];
uint8_t IR_code_index = 0;
uint8_t IR_code_bit = 0;
uint8_t IR_code_step = IR_CODE_STEP_IDLE;
uint8_t IR_lev_last = 0;
uint8_t IR_code_flag = IR_CODE_FLAG_NONE;

uint8_t IRIsTimeInRange(uint32_t time,uint32_t targettime,uint32_t diff)
{
    if(time < targettime && targettime - time > diff)
        return 0;
    if(time > targettime && time - targettime > diff)
        return 0;
    return 1;
}
void IRTimeCount(uint32_t us)
{
    IR_time_us += us;
}
void IRDataProc(void)
{
    switch(IR_code_step)
    {
        case IR_CODE_STEP_IDLE:
            if(IRIsTimeInRange(IR_H_time_us,9000,MAX_TIME_DIFF) != 0)
            {
                IR_code_step = IR_CODE_STEP_START;
                IR_code_flag = IR_CODE_FLAG_NONE;
            }
            break;
        case IR_CODE_STEP_START:
            if(IRIsTimeInRange(IR_L_time_us,4500,MAX_TIME_DIFF) != 0)
            {
                //开始指令
                memset(IR_code,0,4);
                IR_code_index = 0;
                IR_code_bit = 0;
                IR_code_step = IR_CODE_STEP_DATA;
            }
            else if(IRIsTimeInRange(IR_L_time_us,2250,MAX_TIME_DIFF) != 0)
            {
                //重复指令
                IR_code_step = IR_CODE_STEP_STOP;
                IR_code_flag = IR_CODE_FLAG_REPEAT;
            }
            else
            {
                IR_code_step = IR_CODE_STEP_IDLE;
                IR_code_flag = IR_CODE_FLAG_NONE;
            }
            break;
        case IR_CODE_STEP_DATA:
            if(IRIsTimeInRange(IR_H_time_us,560,MAX_TIME_DIFF) != 0)
            {
                if(IRIsTimeInRange(IR_L_time_us,1690,MAX_TIME_DIFF) != 0)
                {
                    IR_code[IR_code_index] |= (1<<IR_code_bit);
                }
                else if(IRIsTimeInRange(IR_L_time_us,560,MAX_TIME_DIFF) == 0)
                {
                    IR_code_step = IR_CODE_STEP_IDLE;
                    IR_code_flag = IR_CODE_FLAG_NONE;
                }
                IR_code_bit += 1;
                if(IR_code_bit == 8)
                {
                    IR_code_bit = 0;
                    IR_code_index += 1;
                    if(IR_code_index == 4)
                    {
                        IR_code_step = IR_CODE_STEP_STOP;
                        IR_code_flag = IR_CODE_FLAG_CMD;
                    }
                }
            }
            else
            {
                IR_code_step = IR_CODE_STEP_IDLE;
                IR_code_flag = IR_CODE_FLAG_NONE;
            }
            break;
        case IR_CODE_STEP_STOP:
            if(IRIsTimeInRange(IR_H_time_us,560,MAX_TIME_DIFF) != 0)
            {
                //结束指令
                IR_code_step = IR_CODE_STEP_IDLE;
            }
            else
            {
                IR_code_step = IR_CODE_STEP_IDLE;
                IR_code_flag = IR_CODE_FLAG_NONE;
            }
            break;
        default:
            IR_code_step = IR_CODE_STEP_IDLE;
            break;
    }
}
void IRIOcheck(uint8_t lev)
{
    if(lev != IR_lev_last)
    {
        IR_lev_last = lev;
        if(lev == 0)
        {
            IR_H_time_us = IR_time_us;
            if(IR_code_step == IR_CODE_STEP_IDLE || IR_code_step == IR_CODE_STEP_STOP)
            {
                IRDataProc();
            }
        }
        else
        {
            if(IR_code_step == IR_CODE_STEP_IDLE)
            {
                IR_L_time_us = 0;
            }
            else
            {
                IR_L_time_us = IR_time_us;
                IRDataProc();
            }
        }
        IR_time_us = 0;
    }
}
通过STM32CubeMX配置一个定时器用来对高低电平进行计时,为了避免太过频繁的进入中断,这里配置的周期是20us

在定时器中断函数里调用IRTimeCount传入参数为定时器触发的周期
void TIM4_IRQHandler(void)
{
  /* USER CODE BEGIN TIM4_IRQn 0 */
    if(LL_TIM_IsActiveFlag_UPDATE(TIM4) == SET)
    {
        LL_TIM_ClearFlag_UPDATE(TIM4);
        IRTimeCount(20);
    }
  /* USER CODE END TIM4_IRQn 0 */
  /* USER CODE BEGIN TIM4_IRQn 1 */

  /* USER CODE END TIM4_IRQn 1 */
}
配置检测红外信号的引脚,我这里使用的是PB9开启了双边沿中断

触发中断后检测PB9的电平,需要注意的是要做取反处理
uint8_t ir_pin_it_flag = 0;
void EXTI9_5_IRQHandler(void)
{
  /* USER CODE BEGIN EXTI9_5_IRQn 0 */

  /* USER CODE END EXTI9_5_IRQn 0 */
  if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_9) != RESET)
  {
    LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_9);
    /* USER CODE BEGIN LL_EXTI_LINE_9 */
        ir_pin_it_flag = 1;
    /* USER CODE END LL_EXTI_LINE_9 */
  }
  /* USER CODE BEGIN EXTI9_5_IRQn 1 */

  /* USER CODE END EXTI9_5_IRQn 1 */
}
void IRAPP(void)
{
    if(ir_pin_it_flag != 0)
    {
        ir_pin_it_flag = 0;
        IRIOcheck(!LL_GPIO_IsInputPinSet(IR_PIN_GPIO_Port,IR_PIN_Pin));
    }
}

如果不用中断就直接轮询PB9的状态
void IRAPP(void)
{
    IRIOcheck(!LL_GPIO_IsInputPinSet(IR_PIN_GPIO_Port,IR_PIN_Pin));
}

在主循环中调用IRAPP(),检测到正确的红外控制命令后IR_code_flag会被置位,先通过串口打印看看效果
if(IR_code_flag == IR_CODE_FLAG_CMD)
{
        printf("rev ir data: %02X%02X%02X%02X\r\n",IR_code[0],IR_code[1],IR_code[2],IR_code[3]);
        IR_code_flag = IR_CODE_FLAG_NONE;
}
else if(IR_code_flag == IR_CODE_FLAG_REPEAT)
{
        printf("rev ir repeat\r\n");
}



接下来实现用STM32F103模拟键盘,在STM32CubeMX中开启USBDevice

选择HID

生成的代码默认设备类型是鼠标,找个键盘的描述符替换掉usbd_hid.c中的鼠标描述符
//#define HID_MOUSE_REPORT_DESC_SIZE    74U
#define HID_MOUSE_REPORT_DESC_SIZE    63U
/*修改usbd_hid.c中的报告设备描述符*/
__ALIGN_BEGIN static uint8_t HID_MOUSE_ReportDesc[HID_MOUSE_REPORT_DESC_SIZE] __ALIGN_END =
{
        0x05, 0x01, // USAGE_PAGE (Generic Desktop) //63
        0x09, 0x06, // USAGE (Keyboard)
        0xa1, 0x01, // COLLECTION (Application)
        0x05, 0x07, // USAGE_PAGE (Keyboard)
        0x19, 0xe0, // USAGE_MINIMUM (Keyboard LeftControl)
        0x29, 0xe7, // USAGE_MAXIMUM (Keyboard Right GUI)
        0x15, 0x00, // LOGICAL_MINIMUM (0)
        0x25, 0x01, // LOGICAL_MAXIMUM (1)
        0x75, 0x01, // REPORT_SIZE (1)
        0x95, 0x08, // REPORT_COUNT (8)
        0x81, 0x02, // INPUT (Data,Var,Abs)
        0x95, 0x01, // REPORT_COUNT (1)
        0x75, 0x08, // REPORT_SIZE (8)
        0x81, 0x03, // INPUT (Cnst,Var,Abs)
        0x95, 0x05, // REPORT_COUNT (5)
        0x75, 0x01, // REPORT_SIZE (1)
        0x05, 0x08, // USAGE_PAGE (LEDs)
        0x19, 0x01, // USAGE_MINIMUM (Num Lock)
        0x29, 0x05, // USAGE_MAXIMUM (Kana)
        0x91, 0x02, // OUTPUT (Data,Var,Abs)
        0x95, 0x01, // REPORT_COUNT (1)
        0x75, 0x03, // REPORT_SIZE (3)
        0x91, 0x03, // OUTPUT (Cnst,Var,Abs)
        0x95, 0x06, // REPORT_COUNT (6)
        0x75, 0x08, // REPORT_SIZE (8)
        0x15, 0x00, // LOGICAL_MINIMUM (0)
        0x25, 0x65, // LOGICAL_MAXIMUM (101)
        0x05, 0x07, // USAGE_PAGE (Keyboard)
        0x19, 0x00, // USAGE_MINIMUM (Reserved (no event indicated))
        0x29, 0x65, // USAGE_MAXIMUM (Keyboard Application)
        0x81, 0x00, // INPUT (Data,Ary,Abs)
        0xc0,       // END_COLLECTION
};

文件中USBD_HID_OtherSpeedCfgDesc这两处也改掉

看一下键盘HID消息格式

找一份键盘值映射代码
typedef enum
{
    KEYBOARD_NONE = 0,
    KEYBOARD_ERROR_ROLL_OVER,
    KEYBOARD_POST_FAIL,
    KEYBOARD_ERROR_UNDEFINED,
    KEYBOARD_A,
    KEYBOARD_B,
    KEYBOARD_C,
    KEYBOARD_D,
    KEYBOARD_E,
    KEYBOARD_F,
    KEYBOARD_G,
    KEYBOARD_H,
    KEYBOARD_I,
    KEYBOARD_J,
    KEYBOARD_K,
    KEYBOARD_L,
    KEYBOARD_M,
    KEYBOARD_N,
    KEYBOARD_O,
    KEYBOARD_P,
    KEYBOARD_Q,
    KEYBOARD_R,
    KEYBOARD_S,
    KEYBOARD_T,
    KEYBOARD_U,
    KEYBOARD_V,
    KEYBOARD_W,
    KEYBOARD_X,
    KEYBOARD_Y,
    KEYBOARD_Z,
    KEYBOARD_1_EXCLAMATION,
    KEYBOARD_2_AT,
    KEYBOARD_3_NUMBER_SIGN,
    KEYBOARD_4_DOLLAR,
    KEYBOARD_5_PERCENT,
    KEYBOARD_6_CARET,
    KEYBOARD_7_AMPERSAND,
    KEYBOARD_8_ASTERISK,
    KEYBOARD_9_OPARENTHESIS,
    KEYBOARD_0_CPARENTHESIS,
    KEYBOARD_ENTER,
    KEYBOARD_ESCAPE,
    KEYBOARD_BACKSPACE,
    KEYBOARD_TAB,
    KEYBOARD_SPACEBAR,
    KEYBOARD_MINUS_UNDERSCORE,
    KEYBOARD_EQUAL_PLUS,
    KEYBOARD_OBRACKET_AND_OBRACE,
    KEYBOARD_CBRACKET_AND_CBRACE,
    KEYBOARD_BACKSLASH_VERTICAL_BAR,
    KEYBOARD_NONUS_NUMBER_SIGN_TILDE,
    KEYBOARD_SEMICOLON_COLON,
    KEYBOARD_SINGLE_AND_DOUBLE_QUOTE,
    KEYBOARD_GRAVE_ACCENT_AND_TILDE,
    KEYBOARD_COMMA_AND_LESS,
    KEYBOARD_DOT_GREATER,
    KEYBOARD_SLASH_QUESTION,
    KEYBOARD_CAPS_LOCK,
    KEYBOARD_F1,
    KEYBOARD_F2,
    KEYBOARD_F3,
    KEYBOARD_F4,
    KEYBOARD_F5,
    KEYBOARD_F6,
    KEYBOARD_F7,
    KEYBOARD_F8,
    KEYBOARD_F9,
    KEYBOARD_F10,
    KEYBOARD_F11,
    KEYBOARD_F12,
    KEYBOARD_PRINTSCREEN,
    KEYBOARD_SCROLL_LOCK,
    KEYBOARD_PAUSE,
    KEYBOARD_INSERT,
    KEYBOARD_HOME,
    KEYBOARD_PAGEUP,
    KEYBOARD_DELETE,
    KEYBOARD_END1,
    KEYBOARD_PAGEDOWN,
    KEYBOARD_RIGHTARROW,
    KEYBOARD_LEFTARROW,
    KEYBOARD_DOWNARROW,
    KEYBOARD_UPARROW,
    KEYBOARD_KEYBOARDPAD_NUM_LOCK_AND_CLEAR,
    KEYBOARD_KEYBOARDPAD_SLASH,
    KEYBOARD_KEYBOARDPAD_ASTERIKS,
    KEYBOARD_KEYBOARDPAD_MINUS,
    KEYBOARD_KEYBOARDPAD_PLUS,
    KEYBOARD_KEYBOARDPAD_ENTER,
    KEYBOARD_KEYBOARDPAD_1_END,
    KEYBOARD_KEYBOARDPAD_2_DOWN_ARROW,
    KEYBOARD_KEYBOARDPAD_3_PAGEDN,
    KEYBOARD_KEYBOARDPAD_4_LEFT_ARROW,
    KEYBOARD_KEYBOARDPAD_5,
    KEYBOARD_KEYBOARDPAD_6_RIGHT_ARROW,
    KEYBOARD_KEYBOARDPAD_7_HOME,
    KEYBOARD_KEYBOARDPAD_8_UP_ARROW,
    KEYBOARD_KEYBOARDPAD_9_PAGEUP,
    KEYBOARD_KEYBOARDPAD_0_INSERT,
    KEYBOARD_KEYBOARDPAD_DECIMAL_SEPARATOR_DELETE,
    KEYBOARD_NONUS_BACK_SLASH_VERTICAL_BAR,
    KEYBOARD_APPLICATION,
    KEYBOARD_POWER,
    KEYBOARD_KEYBOARDPAD_EQUAL,
    KEYBOARD_F13,
    KEYBOARD_F14,
    KEYBOARD_F15,
    KEYBOARD_F16,
    KEYBOARD_F17,
    KEYBOARD_F18,
    KEYBOARD_F19,
    KEYBOARD_F20,
    KEYBOARD_F21,
    KEYBOARD_F22,
    KEYBOARD_F23,
    KEYBOARD_F24,
    KEYBOARD_EXECUTE,
    KEYBOARD_HELP,
    KEYBOARD_MENU,
    KEYBOARD_SELECT,
    KEYBOARD_STOP,
    KEYBOARD_AGAIN,
    KEYBOARD_UNDO,
    KEYBOARD_CUT,
    KEYBOARD_COPY,
    KEYBOARD_PASTE,
    KEYBOARD_FIND,
    KEYBOARD_MUTE,
    KEYBOARD_VOLUME_UP,
    KEYBOARD_VOLUME_DOWN,
    KEYBOARD_LOCKING_CAPS_LOCK,
    KEYBOARD_LOCKING_NUM_LOCK,
    KEYBOARD_LOCKING_SCROLL_LOCK,
    KEYBOARD_KEYBOARDPAD_COMMA,
    KEYBOARD_KEYBOARDPAD_EQUAL_SIGN,
    KEYBOARD_INTERNATIONAL1,
    KEYBOARD_INTERNATIONAL2,
    KEYBOARD_INTERNATIONAL3,
    KEYBOARD_INTERNATIONAL4,
    KEYBOARD_INTERNATIONAL5,
    KEYBOARD_INTERNATIONAL6,
    KEYBOARD_INTERNATIONAL7,
    KEYBOARD_INTERNATIONAL8,
    KEYBOARD_INTERNATIONAL9,
    KEYBOARD_LANG1,
    KEYBOARD_LANG2,
    KEYBOARD_LANG3,
    KEYBOARD_LANG4,
    KEYBOARD_LANG5,
    KEYBOARD_LANG6,
    KEYBOARD_LANG7,
    KEYBOARD_LANG8,
    KEYBOARD_LANG9,
    KEYBOARD_ALTERNATE_ERASE,
    KEYBOARD_SYSREQ,
    KEYBOARD_CANCEL,
    KEYBOARD_CLEAR,
    KEYBOARD_PRIOR,
    KEYBOARD_RETURN,
    KEYBOARD_SEPARATOR,
    KEYBOARD_OUT,
    KEYBOARD_OPER,
    KEYBOARD_CLEAR_AGAIN,
    KEYBOARD_CRSEL,
    KEYBOARD_EXSEL,
    KEYBOARD_RESERVED1,
    KEYBOARD_RESERVED2,
    KEYBOARD_RESERVED3,
    KEYBOARD_RESERVED4,
    KEYBOARD_RESERVED5,
    KEYBOARD_RESERVED6,
    KEYBOARD_RESERVED7,
    KEYBOARD_RESERVED8,
    KEYBOARD_RESERVED9,
    KEYBOARD_RESERVED10,
    KEYBOARD_RESERVED11,
    KEYBOARD_KEYBOARDPAD_00,
    KEYBOARD_KEYBOARDPAD_000,
    KEYBOARD_THOUSANDS_SEPARATOR,
    KEYBOARD_DECIMAL_SEPARATOR,
    KEYBOARD_CURRENCY_UNIT,
    KEYBOARD_CURRENCY_SUB_UNIT,
    KEYBOARD_KEYBOARDPAD_OPARENTHESIS,
    KEYBOARD_KEYBOARDPAD_CPARENTHESIS,
    KEYBOARD_KEYBOARDPAD_OBRACE,
    KEYBOARD_KEYBOARDPAD_CBRACE,
    KEYBOARD_KEYBOARDPAD_TAB,
    KEYBOARD_KEYBOARDPAD_BACKSPACE,
    KEYBOARD_KEYBOARDPAD_A,
    KEYBOARD_KEYBOARDPAD_B,
    KEYBOARD_KEYBOARDPAD_C,
    KEYBOARD_KEYBOARDPAD_D,
    KEYBOARD_KEYBOARDPAD_E,
    KEYBOARD_KEYBOARDPAD_F,
    KEYBOARD_KEYBOARDPAD_XOR,
    KEYBOARD_KEYBOARDPAD_CARET,
    KEYBOARD_KEYBOARDPAD_PERCENT,
    KEYBOARD_KEYBOARDPAD_LESS,
    KEYBOARD_KEYBOARDPAD_GREATER,
    KEYBOARD_KEYBOARDPAD_AMPERSAND,
    KEYBOARD_KEYBOARDPAD_LOGICAL_AND,
    KEYBOARD_KEYBOARDPAD_VERTICAL_BAR,
    KEYBOARD_KEYBOARDPAD_LOGIACL_OR,
    KEYBOARD_KEYBOARDPAD_COLON,
    KEYBOARD_KEYBOARDPAD_NUMBER_SIGN,
    KEYBOARD_KEYBOARDPAD_SPACE,
    KEYBOARD_KEYBOARDPAD_AT,
    KEYBOARD_KEYBOARDPAD_EXCLAMATION_MARK,
    KEYBOARD_KEYBOARDPAD_MEMORY_STORE,
    KEYBOARD_KEYBOARDPAD_MEMORY_RECALL,
    KEYBOARD_KEYBOARDPAD_MEMORY_CLEAR,
    KEYBOARD_KEYBOARDPAD_MEMORY_ADD,
    KEYBOARD_KEYBOARDPAD_MEMORY_SUBTRACT,
    KEYBOARD_KEYBOARDPAD_MEMORY_MULTIPLY,
    KEYBOARD_KEYBOARDPAD_MEMORY_DIVIDE,
    KEYBOARD_KEYBOARDPAD_PLUSMINUS,
    KEYBOARD_KEYBOARDPAD_CLEAR,
    KEYBOARD_KEYBOARDPAD_CLEAR_ENTRY,
    KEYBOARD_KEYBOARDPAD_BINARY,
    KEYBOARD_KEYBOARDPAD_OCTAL,
    KEYBOARD_KEYBOARDPAD_DECIMAL,
    KEYBOARD_KEYBOARDPAD_HEXADECIMAL,
    KEYBOARD_RESERVED12,
    KEYBOARD_RESERVED13,
    KEYBOARD_LEFTCONTROL,
    KEYBOARD_LEFTSHIFT,
    KEYBOARD_LEFTALT,
    KEYBOARD_LEFT_GUI,
    KEYBOARD_RIGHTCONTROL,
    KEYBOARD_RIGHTSHIFT,
    KEYBOARD_RIGHTALT,
    KEYBOARD_RIGHT_GUI,
} USBH_HID_KEYBOARD_VALUE_T;
将遥控器的数字键按照原本的数字输入,方向键控制光标方向,OK键回车,*键退格,#键del
uint8_t IRCode2Key(uint8_t ircode)
{
    switch(ircode)
    {
        case 0x45:
            return KEYBOARD_1_EXCLAMATION;
        case 0x46:
            return KEYBOARD_2_AT;
        case 0x47:
            return KEYBOARD_3_NUMBER_SIGN;
        case 0x44:
            return KEYBOARD_4_DOLLAR;
        case 0x40:
            return KEYBOARD_5_PERCENT;
        case 0x43:
            return KEYBOARD_6_CARET;
        case 0x07:
            return KEYBOARD_7_AMPERSAND;
        case 0x15:
            return KEYBOARD_8_ASTERISK;
        case 0x9:
            return KEYBOARD_9_OPARENTHESIS;
        case 0x16:
            return KEYBOARD_BACKSPACE;
        case 0x19:
            return KEYBOARD_0_CPARENTHESIS;
        case 0x0D:
            return KEYBOARD_DELETE;
        case 0x0C:
            break;
        case 0x18:
            return KEYBOARD_UPARROW;
        case 0x5E:
            break;
        case 0x08:
            return KEYBOARD_LEFTARROW;
        case 0x1C:
            return KEYBOARD_ENTER;
        case 0x5A:
            return KEYBOARD_RIGHTARROW;
        case 0x42:
            break;
        case 0x52:
            return KEYBOARD_DOWNARROW;
        case 0x4A:
            break;
        default:
            break;
    }
    return 0;
}
发送按键数据后还要发送一个空的包,表示按键抬起,不然会一直输入,在定时器哪里增加个变量来计时
uint16_t release_key_time = 0;
void IRTimeCount(uint32_t us)
{
    IR_time_us += us;
    if(release_key_time > us)
    {
        release_key_time -= us;
    }
    else if(release_key_time > 0)
    {
        release_key_time = 1;
    }
}
void IRAPP(void)
{
    uint8_t HID_Buffer[8] = {0};
    if(ir_pin_it_flag != 0)
    {
        ir_pin_it_flag = 0;
        IRIOcheck(!LL_GPIO_IsInputPinSet(IR_PIN_GPIO_Port,IR_PIN_Pin));
    }
    if(IR_code_flag == IR_CODE_FLAG_CMD)
    {
        //printf("rev ir data: %02X%02X%02X%02X\r\n",IR_code[0],IR_code[1],IR_code[2],IR_code[3]);
        IR_code_flag = IR_CODE_FLAG_NONE;
        if((IR_code[2]^IR_code[3]) == 0xFF)
        {
            HID_Buffer[2] = IRCode2Key(IR_code[2]);
            USBD_HID_SendReport(&hUsbDeviceFS, HID_Buffer, 8);
            release_key_time = 20000;
        }
    }
    else if(IR_code_flag == IR_CODE_FLAG_REPEAT)
    {
        //printf("rev ir repeat\r\n");
        IR_code_flag = IR_CODE_FLAG_NONE;
    }
    if(release_key_time == 1)
    {
        release_key_time = 0;
        USBD_HID_SendReport(&hUsbDeviceFS, HID_Buffer, 8);
    }
}
需要注意开启USB后要注释掉串口相关操作,不然会有问题,我这里会出现发送空指令变成输入e的情况,最终效果如下

就实际使用来说蓝牙或者2.4G的遥控更好用,这个项目适合对红外解码和USB通讯的学习。



使用特权

评论回复

打赏榜单

21小跑堂 打赏了 60.00 元 2024-11-14
理由:恭喜通过原创审核!期待您更多的原创作品~~

评论
21小跑堂 2024-11-14 15:44 回复TA
使用STM32F103+红外接收器模块实现遥控控制电脑,虽然实用性不强,但是用于学习红外解码和USB HID设备很是好用。 
沙发
AdaMaYun| | 2024-11-11 17:28 | 只看该作者
适合对红外解码和USB通讯的学习

使用特权

评论回复
板凳
海洋无限| | 2024-11-25 22:30 | 只看该作者

适合对红外解码

使用特权

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

本版积分规则

149

主题

706

帖子

7

粉丝