• 正文
    • 一、模塊來源
    • 二 規(guī)格參數(shù)
    • 三、移植過程
  • 相關推薦
申請入駐 產(chǎn)業(yè)圖譜

【CW32模塊使用】紅外解碼編碼模塊

01/07 08:40
1318
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

紅外解碼編碼模塊采用MCU+紅外發(fā)射頭+紅外接收頭,引出MCU的串口連接其他需要紅外控制的設備,可作為紅外無線數(shù)據(jù)通信、數(shù)據(jù)傳輸等功能。具備NEC格式紅外編碼發(fā)射功能,可控制99%的NEC紅外格式設備,如大部分電視機、機頂盒、DVD、電風扇等電器設備。

只需要利用到單片機串口通信知識,通過串口發(fā)送指定的指令進行控制模塊發(fā)射;通過串口接收方式進行紅外解碼操作,獲取遙控編碼信息。也可以使用2個模塊實現(xiàn)無線操控。

一、模塊來源

模塊實物展示:

資料下載鏈接:https://pan.baidu.com/s/1idRcrVCxQ5zWLh59EFpi9g

資料提取碼:n8ud

規(guī)格參數(shù)

工作電壓:5V

供電電流:> 100mA

發(fā)射距離:6-10米(根據(jù)環(huán)境光線不同和收發(fā)情況有偏差)

接收距離:6-10米(和發(fā)射設備的功率有關)

控制方式:串口

管腳數(shù)量:4 Pin(2.54mm間距排針

以上信息見廠家資料文件

三、移植過程

我們的目標是將例程移植至CW32F030C8T6開發(fā)板上【實現(xiàn)紅外信號接收與紅外信號發(fā)射的功能】。首先要獲取資料,查看數(shù)據(jù)手冊應如何實現(xiàn)讀取數(shù)據(jù),再移植至我們的工程。

3.1查看資料

發(fā)射和接收過程中指示燈會閃爍,否則常亮。

解碼:解碼時不需要發(fā)送任何指令,只需要拿起遙控對準模塊的接收頭按下,這時模塊的串口就輸出該紅外編碼。通過串口調(diào)試助手查看到解碼的結果,結果輸出為“用戶碼1+用戶碼2+命令碼”三位。在做編碼發(fā)送時也只需要發(fā)送這三位即可。

查看解碼的結果方法

使用USB轉(zhuǎn)TTL串口調(diào)試模塊連接紅外發(fā)射接收模塊,打開電腦串口助手,進行調(diào)試。

USB轉(zhuǎn)TTL串口調(diào)試模塊

將串口調(diào)試模塊與紅外發(fā)射接收模塊進行連接。

將串口調(diào)試助手連接電腦,按照如下配置打開串口調(diào)試軟件。使用紅外遙控器或者空調(diào)遙控器對著模塊發(fā)送紅外信號,就會看到紅外發(fā)射接收模塊解析遙控器信號后,返回的解碼數(shù)據(jù)。圖中顯示的是美的空調(diào)遙控器的打開空調(diào)信號的解碼數(shù)據(jù):E0 FD FD。

通信方式

這個紅外發(fā)射接收模塊,通過特定的串口協(xié)議,實現(xiàn)的紅外信號的接收和發(fā)送。需要注意的是本模塊收發(fā)的串口指令格式都為 16 進制格式,即A1為0XA1。

幀頭為通信地址,A1為默認地址,而默認地址是可以通過指令修改的,所以還有一個通用地址為0XFA,當忘記了自己設置的地址,可以通過通用地址0XFA進行修改。

操作位用于表示當前指令用于實現(xiàn)什么功能,其定義的說明見下表。

發(fā)送反饋

每一個指令發(fā)送完畢之后,都有對應的反饋信息。

示例:  發(fā)送紅外信號數(shù)據(jù)    FA F1 E0 FD FD 后,返回  F1  說明發(fā)送成功; 返回其他說明發(fā)送失??;        發(fā)送修改通信地址   FA F2 A5 00 00 后,返回   F2  說明修改成功; 返回其他說明修改失敗;        發(fā)送修改波特率     FA F3 02 00 00 后,返回   F3  說明修改成功; 返回其他說明修改失?。?/code>

實現(xiàn)代碼說明:

定義一個長度為5的unsigned char的數(shù)組:unsigned char send_data[5]={0};將指令填充至數(shù)組里。


    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;              //鍵值

將這個數(shù)組通過串口發(fā)送給模塊。但是需要注意,因為是有反饋信息的,為了確定返回的數(shù)據(jù)是否正確,需要先清除之前接收的數(shù)據(jù),不管之前有沒有接收過數(shù)據(jù)都要清除。


    infrared_receive_clear();//先清除接收的數(shù)據(jù)    infrared_send_hex(send_data, 5);//發(fā)送數(shù)據(jù)

發(fā)送數(shù)據(jù)完畢后,等待串口接收到反饋的數(shù)據(jù),并且設置好如果長時間接收不到,要結束接收,防止一直等待接收導致卡死。


      time_out = 1000;//等待接收時間1000Ms      //等待回應數(shù)據(jù)      //infrared_recv_flag != 1說明串口沒有接收到數(shù)據(jù)      while( infrared_recv_flag != 1 && time_out > 0 )      {            time_out--;            delay_1ms(1);      }      if( time_out > 0 )//沒有超時      {            infrared_recv_flag = 0;//清除標志位            //如果接收到發(fā)送成功的回應數(shù)據(jù)            if( infrared_recv_buff[0] == 0XF1 ) return 1;            else return 2;//接收的數(shù)據(jù)不對      }      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;//紅外發(fā)射狀態(tài)unsigned char modified_addr     = 0XF2;//修改設備地址unsigned char modified_baud     = 0XF3;//修改波特率

/****************************************************************** * 函 數(shù) 名 稱:Infrared_GPIO_Init * 函 數(shù) 說 明:初始化萬能紅外引腳 * 函 數(shù) 形 參:設置波特率 * 函 數(shù) 返 回:無 * 作       者: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;     // 收發(fā)模式    USART_Init(BSP_INFRARED, &USART_InitStructure);                       // 初始化串口1
    // 優(yōu)先級,無優(yōu)先級分組    NVIC_SetPriority(BSP_INFRARED_IRQ, 0);
    // UARTx中斷使能    NVIC_EnableIRQ(BSP_INFRARED_IRQ);
    // 使能UARTx RC中斷    USART_ITConfig(BSP_INFRARED, USART_IT_RC, ENABLE);}
/************************************************函數(shù)名稱 : infrared_send_byte功    能 : 串口發(fā)送一個字節(jié)參    數(shù) : ucch:要發(fā)送的字節(jié)返 回 值 :作    者 : LC*************************************************/void infrared_send_byte(uint8_t ucch){    // 發(fā)送一個字節(jié)    USART_SendData_8bit(BSP_INFRARED, (uint8_t)ucch);
    // 等待發(fā)送完成    while( RESET == USART_GetFlagStatus(BSP_INFRARED, USART_FLAG_TXE) ){}}
void infrared_send_hex(uint8_t *ch, int len){   while(len--)   {        infrared_send_byte(*ch++);   }}/************************************************函數(shù)名稱 : infrared_receive_clear功    能 : 清除串口接收的全部數(shù)據(jù)參    數(shù) : 無返 回 值 : 無作    者 : 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;}


/****************************************************************** * 函 數(shù) 名 稱:Infrared_emission_cmd * 函 數(shù) 說 明:控制模塊發(fā)射紅外命令 * 函 數(shù) 形 參:Infrared_buff要發(fā)射的紅外信號  len紅外信號長度 * 函 數(shù) 返 回:0:  超時未接收到發(fā)射成功數(shù)據(jù) *              1:  發(fā)射成功 *              2:  接收的數(shù)據(jù)不是發(fā)射成功數(shù)據(jù) *              100:發(fā)射的數(shù)據(jù)不是3位
 * 作       者:LC * 備       注:無******************************************************************/char Infrared_emission_cmd(unsigned char* Infrared_buff, char len){    unsigned char send_data[5] = {0};//必須賦初值    unsigned int  time_out = 1000; //超時時間,單位MS
//    //如果要發(fā)送的數(shù)據(jù)長度不對    if( (len < 3) || (len > 3) )        return 100;
    send_data[0] = device_addr;         //設備地址    send_data[1] = Infrared_emission;   //操作位    send_data[2] = Infrared_buff[0];          //數(shù)據(jù)位1    send_data[3] = Infrared_buff[1];          //數(shù)據(jù)位2    send_data[4] = Infrared_buff[2];          //數(shù)據(jù)位3
    infrared_receive_clear();//先清除接收的數(shù)據(jù)    infrared_send_hex(send_data, 5);//發(fā)送數(shù)據(jù)    //等待回應數(shù)據(jù)    while( infrared_recv_flag != 1 && time_out > 0 )    {        time_out--;        delay_ms(1);    }    if( time_out > 0 )//沒有超時    {        infrared_recv_flag = 0;        //如果接收到通信地址修改成功的回應數(shù)據(jù)        if( infrared_recv_buff[0] == 0XF1 ) return 1;        else return 2;    }    return 0;}


/****************************************************************** * 函 數(shù) 名 稱:modified_addr_cmd * 函 數(shù) 說 明:修改串口地址命令 * 函 數(shù) 形 參:addr_value 要修改的串口地址 * 函 數(shù) 返 回:0:  超時未接收到修改成功數(shù)據(jù) *              1:  修改成功 *              2:  接收的數(shù)據(jù)不是修改成功數(shù)據(jù) * 作       者: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;      //數(shù)據(jù)位
    infrared_receive_clear();//先清除接收的數(shù)據(jù)    infrared_send_hex(send_data, 5);//發(fā)送數(shù)據(jù)    //等待回應數(shù)據(jù)    while( infrared_recv_flag != 1 && time_out > 0 )    {        time_out--;        delay_ms(1);    }    if( time_out > 0 )//沒有超時    {        infrared_recv_flag = 0;        //如果接收到通信地址修改成功的回應數(shù)據(jù)        if( infrared_recv_buff[0] == 0XF2 ) return 1;        else return 2;    }    return 0;}
/****************************************************************** * 函 數(shù) 名 稱:modified_baud_cmd * 函 數(shù) 說 明:修改波特率命令 * 函 數(shù) 形 參:baud_value 要修改的波特率,可以輸入的值有: *              4800、9600、19200、57600 * 函 數(shù) 返 回:0:  超時未接收到修改成功數(shù)據(jù) *              1:  修改成功 *              2:  接收的數(shù)據(jù)不是修改成功數(shù)據(jù) * 作       者: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();//先清除接收的數(shù)據(jù)    infrared_send_hex(send_data, 5);//發(fā)送數(shù)據(jù)    //等待回應數(shù)據(jù)    while( infrared_recv_flag != 1 && time_out > 0 )    {        time_out--;        delay_ms(1);    }    if( time_out > 0 )//沒有超時    {        infrared_recv_flag = 0;        //如果接收到波特率設置成功的回應數(shù)據(jù)        if( infrared_recv_buff[0] == 0XF3 ) return 1;        else return 2;    }    return 0;}


/************************************************函數(shù)名稱 : BSP_INFRARED_IRQHandler功    能 : 串口1接收中斷服務函數(shù)參    數(shù) : 無返 回 值 : 無作    者 : LC*************************************************/void BSP_INFRARED_IRQHandler(void){        if(USART_GetITStatus(BSP_INFRARED, USART_IT_RC) == SET)//判斷是不是真的有接收中斷發(fā)生        {                infrared_recv_buff[infrared_recv_length++] = USART_ReceiveData(BSP_INFRARED); // 把接收到的數(shù)據(jù)放到緩沖區(qū)中                infrared_recv_buff[infrared_recv_length] = '';                infrared_recv_flag = 1;
                USART_ClearITPendingBit(BSP_INFRARED, USART_IT_RC); //已經(jīng)處理就清楚標志位        }
}

在文件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中斷服務函數(shù)
#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);//紅外發(fā)射命令char modified_addr_cmd(unsigned int addr_value);//修改串口地址命令char modified_baud_cmd(unsigned int baud_value);//修改波特率命令

#endif

移植驗證

在自己工程中的main主函數(shù)中,編寫如下。

/* * 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"
//自測的 打開美的空調(diào) 的紅外信號unsigned char Midea_Open[3] = {0XE0,0XFD,0XFD};
int32_t main(void){    board_init();        // 開發(fā)板初始化
    uart1_init(115200);        // 串口1波特率115200
    Infrared_GPIO_Init(9600);
    printf("Demo Startrn");
    while(1)    {          printf("rndat = %drn",Infrared_emission_cmd(Midea_Open,3) );    }}

移植現(xiàn)象:移植現(xiàn)象:使用兩個紅外發(fā)射接收模塊,一個接入開發(fā)板負責發(fā)射,一個接入USB轉(zhuǎn)TTL模塊,查看發(fā)射數(shù)據(jù)是否正確。

這里串口調(diào)試助手查看的是USB轉(zhuǎn)TTL模塊的串口!

模塊移植成功案例代碼:

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

提取碼:LCKF

相關推薦

登錄即可解鎖
  • 海量技術文章
  • 設計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

以開放、共享、互助為理念,致力于構建武漢芯源半導體CW32系列MCU生態(tài)社區(qū)。無論是嵌入式MCU小自還是想要攻破技術難題的工程師,亦或是需求解決方案的產(chǎn)品經(jīng)理都可在CW32生態(tài)社區(qū)汲取營養(yǎng)、共同成長。

B站