1.NEC協議
紅外遙控是一種比較常用的通訊方式,目前紅外遙控的編碼方式中,應用比較廣泛的是NEC協議。
NEC協議的特點如下:
1)載波頻率為 38KHz
2)8位地址和 8位指令長度
3)地址和命令2次傳輸(確保可靠性)
4)PWM 脈沖位置調制,以發(fā)射紅外載波的占空比代表“0”和“1” 其邏輯1與邏輯0的表示如圖所示:
可以看到,邏輯1的位時間為2.25ms,脈沖時間560us;邏輯0的位時間為1.12ms,脈沖時間560us。
一個完整的NEC數據包如下:
首次發(fā)送的是9ms高電平+4.5ms低電平,為引導碼。
接下來是8bit的地址碼+8bit地址碼的反碼+8bit命令碼+8bit命令碼的反碼。
以上是一個正常的數據包,但可能存在一種情況:當長按某個鍵時,發(fā)送的是以110ms為周期的重復碼,如下圖:
重復碼由9ms高電平和2.25ms的低電平以及560us的高電平組成。
2.解碼程序
在上面的圖中可以看到,邏輯1和邏輯0的位時間是不同的,占空比也不同。
所以我們可以根據位時間的長短來解碼,也可以根據占空比的不同(1/2或1/4)來解碼,或者二者同時作為解碼條件。這
里我們介紹根據位時間來解碼。 需要注意的是,很多紅外一體接收頭為了提高接受靈敏度。
輸入高電平,其輸出的是相反的低電平。
下圖為示波器實際捕獲的一組數據:
可以看到,空閑時為高電平,引導碼為9ms低電平+4.5ms高電平。根據位時間解碼的話,我們就不必關系高低電平各自的時間,只需關系總時間就行,即:引導碼為13.5ms,邏輯1為2.25ms,邏輯0為1.12ms。 首先用STM32CubeMx配置定時器。
系統(tǒng)時鐘等的配置這里不在贅述,參考其它教程。
這里使用TIM3的Channel1作為捕獲通道配置如下:
1)定時器時鐘為內部時鐘
2)Channel1配置為輸入捕獲模式
3)分頻系數為63,因為系統(tǒng)時鐘為64M,這樣定時器實際時鐘為64/(63+1)=1M,主要是為了程序中方便計算。
4)捕獲方式為下降沿捕獲
5)最后別忘了打開定時器的中斷
最后生成代碼。
在生成的TIM3中斷函數中,屏蔽生成的中斷處理還是,添加自己的解碼程序如下:
uint32_t TIM3_Over_Cnt = 0;//tim3溢出次數 uint32_t TIM3_Sum_Cnt = 0;//兩次下降沿之間的時間間隔 uint32_t cnt0 = 0; uint8_t IR_Data[60]; void TIM3_IRQHandler(void) { /* USER CODE BEGIN TIM3_IRQn 0 */ /* USER CODE END TIM3_IRQn 0 */ // HAL_TIM_IRQHandler(&htim3); /* USER CODE BEGIN TIM3_IRQn 1 */ if(__HAL_TIM_GET_FLAG(&htim3, TIM_FLAG_UPDATE)) //定時器溢出中斷 { __HAL_TIM_CLEAR_FLAG(&htim3, TIM_FLAG_UPDATE); //清除中斷標記 TIM3_Over_Cnt++; } cnt0 = __HAL_TIM_GET_COUNTER(&htim3); TIM3_Sum_Cnt = (TIM3_Over_Cnt << 16) + cnt0;//獲取計數器的值 __HAL_TIM_SetCounter(&htim3,0);//清零重新計數 TIM3_Over_Cnt = 0;//清零重新計數 if (__HAL_TIM_GET_FLAG(&htim3, TIM_FLAG_CC1) != RESET)//TIM3CH1捕獲中斷 { if(StartRevFlag == 1)//接收到引導碼,開始解碼 { if(TIM3_Sum_Cnt > 36000)//大于36ms認為是結束 { RevComplete = 1;//解碼完成 IR_Tick = 0; } else if(RevComplete == 0) { if(TIM3_Sum_Cnt > 1000 && TIM3_Sum_Cnt < 1300)//1ms~1.3ms認為是低電平 IR_Data[IR_Idx] = 0; else if(TIM3_Sum_Cnt > 2100 && TIM3_Sum_Cnt < 2400)//2.1ms~2.4ms認為是高電平 IR_Data[IR_Idx] = 1; else //接收錯誤,重新開始 StartRevFlag = 0; IR_Idx++; if(IR_Idx > 59) IR_Idx = 59; } } else { if(TIM3_Sum_Cnt > 13000 && TIM3_Sum_Cnt < 14000)//13~14ms引導碼 { StartRevFlag = 1; } IR_Tick = 0; RevComplete = 0;//解碼完成標志置零 IR_Idx = 0;//有效解碼位 TIM3_Over_Cnt = 0; TIM3_Sum_Cnt = 0;//定時器計數清零 } __HAL_TIM_CLEAR_IT(&htim3, TIM_IT_CC1); } /* USER CODE END TIM3_IRQn 1 */ }解碼程序根據每次捕獲下降沿之間的間隔判斷是引導碼還是邏輯1或邏輯0。
接收到引導碼之后,再開始將解碼的數據保存下來。
最后通過也是時長來判斷解碼結束。
這里沒有判斷重復碼,有興趣的小伙伴可以自己加上。
中斷函數中,只是將每一位解碼并保存,最后還需要在主程序中組合成字節(jié)并判斷處理。
void IR_Rev() { uint8_t num = IR_Idx / 8; uint8_t IRValue[8]; if(RevComplete == 1 && StartRevFlag == 1 && IR_Tick > 20) { if(num > 7) num = 7; for(uint8_t j=0;j>1; if(IR_Data[j*8+i]) IRValue[j] |= 0x80; } } if(IRValue[0] == 0x00 && IRValue[1] == 0xFF)//地址碼正確 { switch(IRValue[2])//判斷數據碼 { case 0x46: KeyValue = S_key_Menu; break; case 0x43: KeyValue = S_key_Set; break; case 0x40: KeyValue = S_key_Rst; break; case 0x15: KeyValue = S_key_Down; break; case 0x09: KeyValue = S_key_Up; break; } } StartRevFlag = 0; RevComplete = 0; IR_Tick = 0; } }
審核編輯:劉清
-
NEC
+關注
關注
0文章
238瀏覽量
99112 -
STM32
+關注
關注
2270文章
10896瀏覽量
355767 -
定時器
+關注
關注
23文章
3246瀏覽量
114736 -
紅外遙控
+關注
關注
22文章
347瀏覽量
45590
原文標題:STM32定時器實現紅外接收與解碼
文章出處:【微信號:嵌入式技術開發(fā),微信公眾號:嵌入式技術開發(fā)】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
相關推薦
評論