【CW32模块使用】红外解码编码模块

红外解码编码模块采用MCU+红外发射头+红外接收头,引出MCU的串口连接其他需要红外控制的设备,可作为红外无线数据通信、数据传输等功能。具备NEC格式红外编码发射功能,可控制99%的NEC红外格式设备,如大部分电视机、机顶盒、DVD、电风扇等电器设备。

只需要利用到单片机的串口通信知识,通过串口发送指定的指令进行控制模块发射;通过串口接收方式进行红外解码操作,获取遥控编码信息。也可以使用2个模块实现无线操控。

一、模块来源

模块实物展示:


资料下载链接:
https://pan.baidu.com/s/1idRcrVCxQ5zWLh59EFpi9g
资料提取码:n8ud

二 、规格参数

工作电压:5V

供电电流:> 100mA

发射距离:6-10米(根据环境光线不同和收发情况有偏差)

接收距离:6-10米(和发射设备的功率有关)

控制方式:串口

管脚数量:4 Pin(2.54mm间距排针)

以上信息见厂家资料文件

三、移植过程

我们的目标是将例程移植至CW32F030C8T6开发板上【实现红外信号接收与红外信号发射的功能】。首先要获取资料,查看数据手册应如何实现读取数据,再移植至我们的工程。

3.1查看资料

发射和接收过程中指示灯会闪烁,否则常亮。

解码:解码时不需要发送任何指令,只需要拿起遥控对准模块的接收头按下,这时模块的串口就输出该红外编码。通过串口调试助手查看到解码的结果,结果输出为“用户码1+用户码2+命令码”三位。在做编码发送时也只需要发送这三位即可。

查看解码的结果方法

使用USB转TTL串口调试模块连接红外发射接收模块,打开电脑串口助手,进行调试。

USB转TTL串口调试模块

将串口调试模块与红外发射接收模块进行连接。

将串口调试助手连接电脑,按照如下配置打开串口调试软件。使用红外遥控器或者空调遥控器对着模块发送红外信号,就会看到红外发射接收模块解析遥控器信号后,返回的解码数据。图中显示的是美的空调遥控器的打开空调信号的解码数据:E0 FD FD。

通信方式

这个红外发射接收模块,通过特定的串口协议,实现的红外信号的接收和发送。需要注意的是本模块收发的串口指令格式都为 16 进制格式,即A1为0XA1。

帧头为通信地址,A1为默认地址,而默认地址是可以通过指令修改的,所以还有一个通用地址为0XFA,当忘记了自己设置的地址,可以通过通用地址0XFA进行修改。

操作位用于表示当前指令用于实现什么功能,其定义的说明见下表。

发送反馈

每一个指令发送完毕之后,都有对应的反馈信息。


示例:  发送红外信号数据    FA F1 E0 FD FD 后,返回  F1  说明发送成功; 返回其他说明发送失败;
        发送修改通信地址   FA F2 A5 00 00 后,返回   F2  说明修改成功; 返回其他说明修改失败;
        发送修改波特率     FA F3 02 00 00 后,返回   F3  说明修改成功; 返回其他说明修改失

实现代码说明:

定义一个长度为5的unsigned char的数组:unsigned char send_data[5]={0};将指令填充至数组里。

 
    unsigned char send_data[5]={0};
    send_data[0] = 0XF1;              //帧头
    send_data[1] = 0XF1;              //操作位
    send_data[2] = 0XE0;              //地址1
    send_data[3] = 0XFD;              //地址2
    send_data[4] = 0XFD;              //键值

将这个数组通过串口发送给模块。但是需要注意,因为是有反馈信息的,为了确定返回的数据是否正确,需要先清除之前接收的数据,不管之前有没有接收过数据都要清除。

    infrared_receive_clear();//先清除接收的数据
    infrared_send_hex(send_data, 5);//发送数据

发送数据完毕后,等待串口接收到反馈的数据,并且设置好如果长时间接收不到,要结束接收,防止一直等待接收导致卡死。

      time_out = 1000;//等待接收时间1000Ms
      //等待回应数据
      //infrared_recv_flag != 1说明串口没有接收到数据
      while( infrared_recv_flag != 1 && time_out > 0 )
      {
            time_out--;
            delay_1ms(1);
      }
      if( time_out > 0 )//没有超时
      {
            infrared_recv_flag = 0;//清除标志位
            //如果接收到发送成功的回应数据
            if( infrared_recv_buff[0] == 0XF1 ) return 1;
            else return 2;//接收的数据不对
      }
      return 0;//接收超时

3.2引脚选择

想要使用uart串口,需要确定使用的引脚是否有串口外设功能,可以通过用户手册进行查看。在用户手册的第146页。

这里选择使用PA2和PA3的附加串口2功能。

有串口1功能的引脚

模块接线图

3.3移植至工程

移植步骤中的导入.c和.h文件与【CW32模块使用】DHT11温湿度传感器相同,只是将.c和.h文件更改为bsp_infrared.c与bsp_infrared.h。这里不再过多讲述,移植完成后面修改相关代码。

在文件bsp_infrared.c中,编写如下代码。

/*
 * Change Logs:
 * Date           Author       Notes
 * 2024-06-21     LCKFB-LP    first version
 */
#include "bsp_infrared.h"
#include "board.h"
#include "bsp_uart.h"

unsigned char infrared_recv_buff[USART2_RECEIVE_LENGTH];//串口接收缓存
uint16_t infrared_recv_length;//串口接收长度
unsigned char infrared_recv_flag;//串口接收完毕标志 1=接收完毕 0=未接收完毕


unsigned char device_addr       = 0XA1;//默认器件地址
unsigned char Infrared_emission = 0XF1;//红外发射状态
unsigned char modified_addr     = 0XF2;//修改设备地址
unsigned char modified_baud     = 0XF3;//修改波特率


/******************************************************************
 * 函 数 名 称:Infrared_GPIO_Init
 * 函 数 说 明:初始化万能红外引脚
 * 函 数 形 参:设置波特率
 * 函 数 返 回:无
 * 作       者:LC
 * 备       注:万能红外默认波特率为9600
******************************************************************/
void Infrared_GPIO_Init(uint32_t band_rate)
{
    GPIO_InitTypeDef        GPIO_InitStruct; // GPIO初始化结构体

    BSP_INFRARED_GPIO_RCC_ENABLE();        // 使能GPIO时钟
    BSP_INFRARED_UART_RCC_ENABLE();        // 使能UART时钟

    GPIO_InitStruct.Pins = BSP_INFRARED_TX_PIN;          // GPIO引脚
    GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;          // 推挽输出
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;             // 输出速度高
    GPIO_Init(BSP_INFRARED_GPIO_PORT, &GPIO_InitStruct); // 初始化

    GPIO_InitStruct.Pins = BSP_INFRARED_RX_PIN;          // GPIO引脚
    GPIO_InitStruct.Mode = GPIO_MODE_INPUT_PULLUP;       // 上拉输入
    GPIO_Init(BSP_INFRARED_GPIO_PORT, &GPIO_InitStruct); // 初始化

    BSP_INFRARED_AF_UART_TX(); // UART_TX复用
    BSP_INFRARED_AF_UART_RX(); // UART_RX复用

    // 配置UART
    USART_InitTypeDef USART_InitStructure;

    USART_InitStructure.USART_BaudRate = band_rate;                     // 波特率
    USART_InitStructure.USART_Over = USART_Over_16;                     // 配置USART的过采样率。
    USART_InitStructure.USART_Source = USART_Source_PCLK;               // 设置时钟源
    USART_InitStructure.USART_UclkFreq = 64000000;                      //设置USART时钟频率(和主频一致即可)
    USART_InitStructure.USART_StartBit = USART_StartBit_FE;             //RXD下降沿开始
    USART_InitStructure.USART_StopBits = USART_StopBits_1;              // 停止位1
    USART_InitStructure.USART_Parity = USART_Parity_No ;                // 不使用校验
    USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None; // 不使用流控
    USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;     // 收发模式
    USART_Init(BSP_INFRARED, &USART_InitStructure);                       // 初始化串口1

    // 优先级,无优先级分组
    NVIC_SetPriority(BSP_INFRARED_IRQ, 0);

    // UARTx中断使能
    NVIC_EnableIRQ(BSP_INFRARED_IRQ);

    // 使能UARTx RC中断
    USART_ITConfig(BSP_INFRARED, USART_IT_RC, ENABLE);
}

/************************************************
函数名称 : infrared_send_byte
功    能 : 串口发送一个字节
参    数 : ucch:要发送的字节
返 回 值 :
作    者 : LC
*************************************************/
void infrared_send_byte(uint8_t ucch)
{
    // 发送一个字节
    USART_SendData_8bit(BSP_INFRARED, (uint8_t)ucch);

    // 等待发送完成
    while( RESET == USART_GetFlagStatus(BSP_INFRARED, USART_FLAG_TXE) ){}
}

void infrared_send_hex(uint8_t *ch, int len)
{
   while(len--)
   {
        infrared_send_byte(*ch++);
   }
}
/************************************************
函数名称 : infrared_receive_clear
功    能 : 清除串口接收的全部数据
参    数 : 无
返 回 值 : 无
作    者 : LC
*************************************************/
void  infrared_receive_clear(void)
{
    unsigned int i = 0;

    for( i = 0; i < USART2_RECEIVE_LENGTH; i++ )
    {
        infrared_recv_buff[ i ] = 0;
    }

    infrared_recv_length = 0;
    infrared_recv_flag = 0;
}



/******************************************************************
 * 函 数 名 称:Infrared_emission_cmd
 * 函 数 说 明:控制模块发射红外命令
 * 函 数 形 参:Infrared_buff要发射的红外信号  len红外信号长度
 * 函 数 返 回:0:  超时未接收到发射成功数据
 *              1:  发射成功
 *              2:  接收的数据不是发射成功数据
 *              100:发射的数据不是3位

 * 作       者:LC
 * 备       注:无
******************************************************************/
char Infrared_emission_cmd(unsigned char* Infrared_buff, char len)
{
    unsigned char send_data[5] = {0};//必须赋初值
    unsigned int  time_out = 1000; //超时时间,单位MS

//    //如果要发送的数据长度不对
    if( (len < 3) || (len > 3) )
        return 100;

    send_data[0] = device_addr;         //设备地址
    send_data[1] = Infrared_emission;   //操作位
    send_data[2] = Infrared_buff[0];          //数据位1
    send_data[3] = Infrared_buff[1];          //数据位2
    send_data[4] = Infrared_buff[2];          //数据位3

    infrared_receive_clear();//先清除接收的数据
    infrared_send_hex(send_data, 5);//发送数据
    //等待回应数据
    while( infrared_recv_flag != 1 && time_out > 0 )
    {
        time_out--;
        delay_ms(1);
    }
    if( time_out > 0 )//没有超时
    {
        infrared_recv_flag = 0;
        //如果接收到通信地址修改成功的回应数据
        if( infrared_recv_buff[0] == 0XF1 ) return 1;
        else return 2;
    }
    return 0;
}



/******************************************************************
 * 函 数 名 称:modified_addr_cmd
 * 函 数 说 明:修改串口地址命令
 * 函 数 形 参:addr_value 要修改的串口地址
 * 函 数 返 回:0:  超时未接收到修改成功数据
 *              1:  修改成功
 *              2:  接收的数据不是修改成功数据
 * 作       者:LC
 * 备       注:无
******************************************************************/
char modified_addr_cmd(unsigned int addr_value)
{
    unsigned char send_data[5] = {0};//必须赋初值
    unsigned int  time_out = 1000; //超时时间,单位MS


    send_data[0] = device_addr;     //设备地址
    send_data[1] = modified_addr;   //操作位
    send_data[2] = addr_value;      //数据位

    infrared_receive_clear();//先清除接收的数据
    infrared_send_hex(send_data, 5);//发送数据
    //等待回应数据
    while( infrared_recv_flag != 1 && time_out > 0 )
    {
        time_out--;
        delay_ms(1);
    }
    if( time_out > 0 )//没有超时
    {
        infrared_recv_flag = 0;
        //如果接收到通信地址修改成功的回应数据
        if( infrared_recv_buff[0] == 0XF2 ) return 1;
        else return 2;
    }
    return 0;
}

/******************************************************************
 * 函 数 名 称:modified_baud_cmd
 * 函 数 说 明:修改波特率命令
 * 函 数 形 参:baud_value 要修改的波特率,可以输入的值有:
 *              4800、9600、19200、57600
 * 函 数 返 回:0:  超时未接收到修改成功数据
 *              1:  修改成功
 *              2:  接收的数据不是修改成功数据
 * 作       者:LC
 * 备       注:
******************************************************************/
char modified_baud_cmd(unsigned int baud_value)
{
    unsigned char send_data[5] = {0};//必须赋初值
    unsigned int  time_out = 1000; //超时时间,单位MS


    send_data[0] = device_addr;     //设备地址
    send_data[1] = modified_baud;   //操作位

    switch(baud_value)//要修改的波特率值
    {
        case 4800:   send_data[2] = 0X01; break;
        case 9600:   send_data[2] = 0X02; break;
        case 19200:  send_data[2] = 0X03; break;
        case 57600:  send_data[2] = 0X04; break;
    }
    infrared_receive_clear();//先清除接收的数据
    infrared_send_hex(send_data, 5);//发送数据
    //等待回应数据
    while( infrared_recv_flag != 1 && time_out > 0 )
    {
        time_out--;
        delay_ms(1);
    }
    if( time_out > 0 )//没有超时
    {
        infrared_recv_flag = 0;
        //如果接收到波特率设置成功的回应数据
        if( infrared_recv_buff[0] == 0XF3 ) return 1;
        else return 2;
    }
    return 0;
}



/************************************************
函数名称 : BSP_INFRARED_IRQHandler
功    能 : 串口1接收中断服务函数
参    数 : 无
返 回 值 : 无
作    者 : LC
*************************************************/
void BSP_INFRARED_IRQHandler(void)
{
        if(USART_GetITStatus(BSP_INFRARED, USART_IT_RC) == SET)//判断是不是真的有接收中断发生
        {
                infrared_recv_buff[infrared_recv_length++] = USART_ReceiveData(BSP_INFRARED); // 把接收到的数据放到缓冲区中
                infrared_recv_buff[infrared_recv_length] = '\0';
                infrared_recv_flag = 1;

                USART_ClearITPendingBit(BSP_INFRARED, USART_IT_RC); //已经处理就清楚标志位
        }

}

在文件bsp_infrared.h中,编写如下代码。

/*
 * Change Logs:
 * Date           Author       Notes
 * 2024-06-21     LCKFB-LP    first version
 */

#ifndef _BSP_infrared_H_
#define _BSP_infrared_H_

#include "board.h"

#define BSP_INFRARED_GPIO_RCC_ENABLE()   __RCC_GPIOA_CLK_ENABLE()   // GPIO的时钟
#define BSP_INFRARED_UART_RCC_ENABLE()   __RCC_UART2_CLK_ENABLE()   // 串口2的时钟

#define BSP_INFRARED_AF_UART_TX()        PA02_AFx_UART2TXD()         // GPIO的引脚复用
#define BSP_INFRARED_AF_UART_RX()        PA03_AFx_UART2RXD()         // GPIO的引脚复用

#define BSP_INFRARED_GPIO_PORT           CW_GPIOA                    // GPIO的端口

#define BSP_INFRARED_TX_PIN              GPIO_PIN_2                  // 串口TX的引脚
#define BSP_INFRARED_RX_PIN              GPIO_PIN_3                  // 串口RX的引脚

#define BSP_INFRARED                     CW_UART2                    // 串口2
#define BSP_INFRARED_IRQ                 UART2_IRQn                  // 串口2中断
#define BSP_INFRARED_IRQHandler          UART2_IRQHandler            // 串口2中断服务函数

#define USART2_RECEIVE_LENGTH 1024  //串口最大接收长度

extern unsigned char infrared_recv_buff[USART2_RECEIVE_LENGTH];//串口接收缓存
extern uint16_t infrared_recv_length;//串口接收长度
extern unsigned char infrared_recv_flag;//串口接收完毕标志 1=接收完毕 0=未接收完毕

void Infrared_GPIO_Init(uint32_t band_rate);//初始化万能红外引脚
void  infrared_receive_clear(void);//清除
char Infrared_emission_cmd(unsigned char* Infrared_buff, char len);//红外发射命令
char modified_addr_cmd(unsigned int addr_value);//修改串口地址命令
char modified_baud_cmd(unsigned int baud_value);//修改波特率命令


#endif

四、移植验证

在自己工程中的main主函数中,编写如下。

/*
 * Change Logs:
 * Date           Author       Notes
 * 2024-06-21     LCKFB-LP    first version
 */
#include "board.h"
#include "stdio.h"
#include "bsp_uart.h"
#include "bsp_infrared.h"

//自测的 打开美的空调 的红外信号
unsigned char Midea_Open[3] = {0XE0,0XFD,0XFD};

int32_t main(void)
{
    board_init();        // 开发板初始化

    uart1_init(115200);        // 串口1波特率115200

    Infrared_GPIO_Init(9600);

    printf("Demo Start\r\n");

    while(1)
    {
          printf("\r\ndat = %d\r\n",Infrared_emission_cmd(Midea_Open,3) );
    }
}

移植现象:移植现象:使用两个红外发射接收模块,一个接入开发板负责发射,一个接入USB转TTL模块,查看发射数据是否正确。

这里串口调试助手查看的是USB转TTL模块的串口!

模块移植成功案例代码:

链接:https://pan.baidu.com/s/1IO6hOYyyHSqegu2tSKvmZA?pwd=LCKF

提取码:LCKF

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值