紅外解碼編碼模塊采用MCU+紅外發射頭+紅外接收頭,引出MCU的串口連接其他需要紅外控制的設備,可作為紅外無線數據通信、數據傳輸等功能。具備NEC格式紅外編碼發射功能,可控制99%的NEC紅外格式設備,如大部分電視機、機頂盒、DVD、電風扇等電器設備。
只需要利用到單片機的串口通信知識,通過串口發送指定的指令進行控制模塊發射;通過串口接收方式進行紅外解碼操作,獲取遙控編碼信息。也可以使用2個模塊實現無線操控。
一、模塊來源
模塊實物展示:
資料下載鏈接:
https://pan.baidu.com/s/1idRcrVCxQ5zWLh59EFpi9g
資料提取碼:n8ud
工作電壓:5V
發射距離: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] = ''; 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 Startrn"); while(1) { printf("rndat = %drn",Infrared_emission_cmd(Midea_Open,3) ); } }
移植現象:移植現象:使用兩個紅外發射接收模塊,一個接入開發板負責發射,一個接入USB轉TTL模塊,查看發射數據是否正確。
這里串口調試助手查看的是USB轉TTL模塊的串口!
模塊移植成功案例代碼:
鏈接:https://pan.baidu.com/s/1IO6hOYyyHSqegu2tSKvmZA?pwd=LCKF
提取碼:LCKF
審核編輯 黃宇
-
編碼
+關注
關注
6文章
957瀏覽量
54911 -
紅外解碼
+關注
關注
1文章
16瀏覽量
11495 -
CW32
+關注
關注
1文章
218瀏覽量
706
發布評論請先 登錄
相關推薦
評論