【stm32單片機(jī)基礎(chǔ)】紅外NEC協(xié)議解碼
前言
紅外通信協(xié)議是一種基于紅外線的傳輸技術(shù),廣泛使用的家電遙控器幾乎都是采用的紅外線傳輸技術(shù),由于紅外線為不可見光,對(duì)環(huán)境影響很小,紅外線遙控不會(huì)影響其他家用電器,也不會(huì)影響臨近的無線電設(shè)備。紅外遙控的編碼方式目前廣泛使用的是: PWM(脈沖寬度調(diào)制)的 NEC 協(xié)議和 PhilipsPPM(脈沖位置調(diào)制) 的 RC-5 協(xié)議的。本文分享NEC協(xié)議接收端的解碼程序。紅外NEC協(xié)議
通信協(xié)議分為發(fā)送端和接收端,接收端的波形與發(fā)射端剛好相反。
NEC IR 協(xié)議使用 32 位幀格式對(duì)密鑰進(jìn)行編碼,如下所示
1、NEC 幀格式
地址碼0 | 地址碼1 | 命令碼 | 命令碼反碼 |
---|---|---|---|
LSB-MSB(0-7) | LSB-MSB(8-15) | LSB-MSB(16-23) | LSB-MSB(24-31) |
在標(biāo)準(zhǔn)的NEC協(xié)議中,地址碼1為地址碼0的反碼,而在許多遙控器中,地址碼0和地址碼1共同作為紅外遙控器的編碼值。
2、發(fā)射端的波形
每個(gè)位都使用如圖所示的脈沖距離進(jìn)行傳輸。
邏輯“0”:562.5μs高電平,562.5μs低電平,總時(shí)長為1.125ms
邏輯“1”:562.5μs高電平,1.6875ms低電平,總時(shí)長為2.25ms
在遙控器上按某個(gè)鍵時(shí),傳輸?shù)南错樞虬韵聝?nèi)容:
引導(dǎo)碼:持續(xù)9ms 高電平,4.5ms低電平,作為啟動(dòng)信號(hào);
緊接著是32bit的數(shù)據(jù),按照上述的NEC幀格式的順序;最后以562.5μs脈沖高電平結(jié)尾,表示一幀消息傳輸結(jié)束。
數(shù)據(jù)位的四個(gè)字節(jié)首先發(fā)送最低有效位。
下圖示例展示了NEC 紅外傳輸幀的格式,以地址為 00h (00000000b) 和 ADh (10101101b) 的命令碼為例。
傳輸一個(gè)消息幀總共需要 67.5ms。它需要27ms來傳輸16位地址(地址+地址反碼)和16位命令(命令+命令反碼)。
重復(fù)碼
如果遙控器上的鍵保持按下狀態(tài),則會(huì)發(fā)射重復(fù)碼,通常在完整的一幀消息結(jié)束后約40ms后發(fā)送;重復(fù)碼將繼續(xù)以 108 ms的間隔發(fā)出,直到紅外遙控按鍵被釋放。
重復(fù)碼按順序包含以下內(nèi)容:
- 9ms 前導(dǎo)高電平
- 2.25ms的低電平
- 562.5μs的高電平來標(biāo)記一幀重復(fù)碼的結(jié)束。
波形如下圖所示:
文章來源:http://www.zghlxwxcb.cn/news/detail-428466.html
3、接收端程序解碼
由于接收端的波形與發(fā)射端的波形剛好相反,在下述程序中,只需要一個(gè)定時(shí)器即可解碼紅外NEC協(xié)議,包含了紅外重復(fù)碼的檢測(cè),可區(qū)別紅外遙控長按和短按事件。文章來源地址http://www.zghlxwxcb.cn/news/detail-428466.html
#define IR_IN GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_1) // PA1 紅外接收DQ引腳
unsigned char ir_code[4]; // 解碼值保存變量
unsigned char ir_decode_ok_flag = RESET; // 解碼成功標(biāo)志位
/*
NEC紅外編碼: 引導(dǎo)碼 + 地址碼 + 地址碼(取反) + 數(shù)據(jù) + 數(shù)據(jù)(取反)
引導(dǎo)嗎:0.56ms(低電平) + 2.25ms(高電平)
數(shù)據(jù)1: 0.56ms(低電平) + 1.12ms(高電平)
*/
// 紅外解碼程序,100us定期執(zhí)行就可以,將該函數(shù)放在100us的定時(shí)器中即可。
void Ir_Decode(void)
{
static unsigned int l_cnt = 0; // 低電平時(shí)間計(jì)數(shù)
static unsigned int h_cnt = 0; // 高電平時(shí)間計(jì)數(shù)
static unsigned int l_cnt_save = 0; // 保存低電平時(shí)長
static unsigned int h_cnt_save = 0; // 保存高電平時(shí)長
static unsigned char falling_edge_valid_flag = RESET; // IR電平由高變低標(biāo)志位
static unsigned char rcv_sync_ok_flag = RESET; // 同步碼接收成功標(biāo)志位
static unsigned char bit_value = 0; // 位解碼值
static unsigned char bit_rcv_cnt = 0; // 位接收個(gè)數(shù)變量
if( RESET == IR_IN )
{
if( 0 == l_cnt ) // IR由高變低后立馬記錄上次測(cè)得的高電平時(shí)長
{
h_cnt_save = h_cnt;
falling_edge_valid_flag = SET;
}
l_cnt ++;
if( l_cnt > 1600 ) // 防止計(jì)數(shù)溢出
{
l_cnt = 1600;
}
h_cnt = 0; // 計(jì)數(shù)清零
}
else
{
if( 0 == h_cnt ) // IR由低變高后立馬記錄上次測(cè)得的低電平時(shí)長
{
l_cnt_save = l_cnt;
}
h_cnt ++;
if( h_cnt > 1600 ) // 防止計(jì)數(shù)溢出
{
h_cnt = 1600;
}
l_cnt = 0; // 計(jì)數(shù)清零
if(ir_decode_ok_flag == 1)
{
if(h_cnt > 1200)
ir_decode_ok_flag = 2; // 短按
}
}
if( SET == falling_edge_valid_flag )
{
falling_edge_valid_flag = RESET;
/* 位解碼 */
if( ((l_cnt_save >= 3)&&(l_cnt_save <= 9)) && // 560us低電平, 560us高電平
((h_cnt_save >= 3)&&(h_cnt_save <= 9)) )
{
bit_value = 0;
}
else if( ((l_cnt_save >= 3)&&(l_cnt_save <= 9)) && // 560us低電平,1680us高電平
((h_cnt_save >= 14)&&(h_cnt_save <= 20)) )
{
bit_value = 1;
}
else
{
bit_value = 2;
}
if( SET == rcv_sync_ok_flag )
{
if((1 == bit_value) || (0 == bit_value) )
{
if( bit_rcv_cnt < 8 )
{
ir_code[0] |= (bit_value<< (bit_rcv_cnt%8));
}
else if( bit_rcv_cnt < 16 )
{
ir_code[1] |= (bit_value<< (bit_rcv_cnt%8));
}
else if( bit_rcv_cnt < 24 )
{
ir_code[2] |= (bit_value<< (bit_rcv_cnt%8));
}
else if( bit_rcv_cnt < 32 )
{
ir_code[3] |= (bit_value<< (bit_rcv_cnt%8));
}
if( bit_rcv_cnt >= 31 )
{
ir_decode_ok_flag = SET;
rcv_sync_ok_flag = RESET;
}
bit_rcv_cnt ++;
}
else
{
rcv_sync_ok_flag = RESET; // 位接收錯(cuò)誤,重新解碼
}
}
if( ((l_cnt_save >= 87)&&(l_cnt_save <= 93)) &&
((h_cnt_save >= 42)&&(h_cnt_save <= 48)) ) // 同步碼,9ms低電平,4.5ms高電平
{
rcv_sync_ok_flag = SET;
bit_rcv_cnt = 0;
ir_code[0] = 0;
ir_code[1] = 0;
ir_code[2] = 0;
ir_code[3] = 0;
}
else if(((l_cnt_save >= 87)&&(l_cnt_save <= 93)) &&
((h_cnt_save >= 20)&&(h_cnt_save <= 25)) )
{
printf("repeate code\r\n");
ir_decode_ok_flag = 3; //長按
}
}
}
到了這里,關(guān)于【stm32單片機(jī)基礎(chǔ)】紅外NEC協(xié)議解碼的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!