STM32開(kāi)發(fā)指南--第三十二章 紅外遙控實(shí)驗(yàn)
第三十二章紅外遙控實(shí)驗(yàn)
本章,我們將向大家介紹如何通過(guò)STM32來(lái)解碼紅外遙控器的信號(hào)。ALIENTK戰(zhàn)艦STM32開(kāi)發(fā)板標(biāo)配了紅外接收頭和一個(gè)很小巧的紅外遙控器。在本章中,我們將利用STM32的輸入捕獲功能,解碼開(kāi)發(fā)板標(biāo)配的這個(gè)紅外遙控器的編碼信號(hào),并將解碼后的鍵值TFTLCD模塊上顯示出來(lái)。本章分為如下幾個(gè)部分:
32.1 紅外遙控簡(jiǎn)介
32.2 硬件設(shè)計(jì)
32.3 軟件設(shè)計(jì)
32.4 下載驗(yàn)證
32.1紅外遙控簡(jiǎn)介
紅外遙控是一種無(wú)線、非接觸控制技術(shù),具有抗干擾能力強(qiáng),信息傳輸可靠,功耗低,成本低,易實(shí)現(xiàn)等顯著優(yōu)點(diǎn),被諸多電子設(shè)備特別是家用電器廣泛采用,并越來(lái)越多的應(yīng)用到計(jì)算機(jī)系統(tǒng)中。
由于紅外線遙控不具有像無(wú)線電遙控那樣穿過(guò)障礙物去控制被控對(duì)象的能力,所以,在設(shè)計(jì)紅外線遙控器時(shí),不必要像無(wú)線電遙控器那樣,每套(發(fā)射器和接收器)要有不同的遙控頻率或編碼(否則,就會(huì)隔墻控制或干擾鄰居的家用電器),所以同類產(chǎn)品的紅外線遙控器,可以有相同的遙控頻率或編碼,而不會(huì)出現(xiàn)遙控信號(hào)“串門(mén)”的情況。這對(duì)于大批量生產(chǎn)以及在家用電器上普及紅外線遙控提供了極大的方面。由于紅外線為不可見(jiàn)光,因此對(duì)環(huán)境影響很小,再由紅外光波動(dòng)波長(zhǎng)遠(yuǎn)小于無(wú)線電波的波長(zhǎng),所以紅外線遙控不會(huì)影響其他家用電器,也不會(huì)影響臨近的無(wú)線電設(shè)備。
紅外遙控的編碼目前廣泛使用的是:NEC Protocol 的PWM(脈沖寬度調(diào)制)和Philips
RC-5 Protocol 的PPM(脈沖位置調(diào)制)。ALIENTEK戰(zhàn)艦STM32開(kāi)發(fā)板配套的遙控器使用的是NEC協(xié)議,其特征如下:
1、8位地址和8位指令長(zhǎng)度;
2、地址和命令2次傳輸(確??煽啃裕?/p>
3、PWM脈沖位置調(diào)制,以發(fā)射紅外載波的占空比代表“0”和“1”;
4、載波頻率為38Khz;
5、位時(shí)間為1.125ms或2.25ms;
NEC碼的位定義:一個(gè)脈沖對(duì)應(yīng)560us的連續(xù)載波,一個(gè)邏輯1傳輸需要2.25ms(560us脈沖+1680us低電平),一個(gè)邏輯0的傳輸需要1.125ms(560us脈沖+560us低電平)。而遙控接收頭在收到脈沖的時(shí)候?yàn)榈碗娖?,在沒(méi)有脈沖的時(shí)候?yàn)楦唠娖?,這樣,我們?cè)诮邮疹^端收到的信號(hào)為:邏輯1應(yīng)該是560us低+1680us高,邏輯0應(yīng)該是560us低+560us高。
NEC遙控指令的數(shù)據(jù)格式為:同步碼頭、地址碼、地址反碼、控制碼、控制反碼。同步碼由一個(gè)9ms的低電平和一個(gè)4.5ms的高電平組成,地址碼、地址反碼、控制碼、控制反碼均是8位數(shù)據(jù)格式。按照低位在前,高位在后的順序發(fā)送。采用反碼是為了增加傳輸?shù)目煽啃裕捎糜谛r?yàn))。
我們遙控器的按鍵2按下時(shí),從紅外接收頭端收到的波形如圖32.1.1所示:
圖32.1.1 按鍵2所對(duì)應(yīng)的紅外波形
從圖32.1.1中可以看到,其地址碼為0,控制碼為168??梢钥吹皆?00ms之后,我們還收到了幾個(gè)脈沖,這是NEC碼規(guī)定的連發(fā)碼(由9ms低電平+2.5m高電平+0.56ms低電平+97.94ms高電平組成),如果在一幀數(shù)據(jù)發(fā)送完畢之后,按鍵仍然沒(méi)有放開(kāi),則發(fā)射重復(fù)碼,即連發(fā)碼,可以通過(guò)統(tǒng)計(jì)連發(fā)碼的次數(shù)來(lái)標(biāo)記按鍵按下的長(zhǎng)短/次數(shù)。
第十五章我們?cè)?jīng)介紹過(guò)利用輸入捕獲來(lái)測(cè)量高電平的脈寬,本章解碼紅外遙控信號(hào),剛好可以利用輸入捕獲的這個(gè)功能來(lái)實(shí)現(xiàn)遙控解碼。關(guān)于輸入捕獲的介紹,請(qǐng)參考第十五章的內(nèi)容。
32.2硬件設(shè)計(jì)
本實(shí)驗(yàn)采用定時(shí)器的輸入捕獲功能實(shí)現(xiàn)紅外解碼,本章實(shí)驗(yàn)功能簡(jiǎn)介:開(kāi)機(jī)在LCD上顯示一些信息之后,即進(jìn)入等待紅外觸發(fā),如過(guò)接收到正確的紅外信號(hào),則解碼,并在LCD上顯示鍵值和所代表的意義,以及按鍵次數(shù)等信息。同樣我們也是用LED0來(lái)指示程序正在運(yùn)行。
所要用到的硬件資源如下:
1)指示燈DS0
2) TFTLCD模塊(帶觸摸屏)
3)紅外接收頭
4)紅外遙控器
前兩個(gè),在之前的實(shí)例已經(jīng)介紹過(guò)了,遙控器屬于外部器件,遙控接收頭在板子上,與MCU的連接原理圖如32.2.1所示:
圖32.2.1 紅外遙控接收頭與STM32的連接電路圖
紅外遙控接收頭連接在STM32的PB9(TIM4_CH4)上。硬件上不需要變動(dòng),只要程序?qū)IM4_CH4設(shè)計(jì)為輸入捕獲,然后將收到的脈沖信號(hào)解碼就可以了。 開(kāi)發(fā)板配套的紅外遙控器外觀如圖32.2.2所示:
圖32.2.2 紅外遙控器
32.3軟件設(shè)計(jì)
打開(kāi)上一章的工程,首先在HARDWARE文件夾下新建一個(gè)REMOTE的文件夾。然后新建一個(gè)remote.c和remote.h的文件保存在REMOTE文件夾下,并將這個(gè)文件夾加入頭文件包含路徑。
打開(kāi)remote.c文件,輸入如下代碼:
#include "remote.h"
#include "delay.h"
#include "usart.h"
//紅外遙控初始化
//設(shè)置IO以及定時(shí)器4的輸入捕獲
void Remote_Init(void)
{
RCC->APB1ENR|=1<<2; //TIM4時(shí)鐘使能
RCC->APB2ENR|=1<<3; //使能PORTB時(shí)鐘
GPIOB->CRH&=0XFFFFFF0F; //PB9輸入
GPIOB->CRH|=0X00000080; //上拉輸入
GPIOB->ODR|=1<<9; //PB9上拉
TIM4->ARR=10000; //設(shè)定計(jì)數(shù)器自動(dòng)重裝值最大10ms溢出
TIM4->PSC=71; //預(yù)分頻器,1M的計(jì)數(shù)頻率,1us加1.
TIM4->CCMR2|=1<<8; //CC4S=01 選擇輸入端IC4映射到TI4上
TIM4->CCMR2|=3<<12; //IC4F=0011配置輸入濾波器8個(gè)定時(shí)器時(shí)鐘周期濾波
TIM4->CCMR2|=0<<10; //IC4PS=00 配置輸入分頻,不分頻
TIM4->CCER|=0<<13; //CC4P=0 上升沿捕獲
TIM4->CCER|=1<<12; //CC4E=1 允許捕獲計(jì)數(shù)器的值到捕獲寄存器中
TIM4->DIER|=1<<4; //允許CC4IE捕獲中斷
TIM4->DIER|=1<<0; //允許更新中斷
TIM4->CR1|=0x01; //使能定時(shí)器4
MY_NVIC_Init(1,3,TIM4_IRQChannel,2);//搶占1,子優(yōu)先級(jí)3,組2
}
//遙控器接收狀態(tài)
//[7]:收到了引導(dǎo)碼標(biāo)志
//[6]:得到了一個(gè)按鍵的所有信息
//[5]:保留
//[4]:標(biāo)記上升沿是否已經(jīng)被捕獲
//[3:0]:溢出計(jì)時(shí)器
u8 RmtSta=0;
u16 Dval; //下降沿時(shí)計(jì)數(shù)器的值
u32 RmtRec=0; //紅外接收到的數(shù)據(jù)
u8RmtCnt=0; //按鍵按下的次數(shù)
//定時(shí)器2中斷服務(wù)程序
void TIM4_IRQHandler(void)
{
//省略代碼
}
//處理紅外鍵盤(pán)
//返回值:
// 0,沒(méi)有任何按鍵按下
//其他,按下的按鍵鍵值.
u8 Remote_Scan(void)
{
u8 sta=0;
u8 t1,t2;
if(RmtSta&(1<<6))//得到一個(gè)按鍵的所有信息了
{
t1=RmtRec>>24; //得到地址碼
t2=(RmtRec>>16)&0xff; //得到地址反碼
if((t1==(u8)~t2)&&t1==REMOTE_ID)//檢驗(yàn)遙控識(shí)別碼(ID)及地址
{
t1=RmtRec>>8;
t2=RmtRec;
if(t1==(u8)~t2)sta=t1;//鍵值正確
}
if((sta==0)||((RmtSta&0X80)==0))//按鍵數(shù)據(jù)錯(cuò)誤/遙控已經(jīng)沒(méi)有按下了
{
RmtSta&=~(1<<6);//清除接收到有效按鍵標(biāo)識(shí)
RmtCnt=0; //清除按鍵次數(shù)計(jì)數(shù)器
}
}
return sta;
}
該部分代碼包含3個(gè)函數(shù),首先是Remote_Init函數(shù),該函數(shù)用于初始化IO口,并配置TIM4_CH4為輸入捕獲,并設(shè)置其相關(guān)參數(shù)。TIM4_IRQHandler函數(shù)是TIM4的中斷服務(wù)函數(shù),在該函數(shù)里面,實(shí)現(xiàn)對(duì)紅外信號(hào)的高電平脈沖的捕獲,同時(shí)根據(jù)我們之前簡(jiǎn)介的協(xié)議內(nèi)容來(lái)解碼 ,該函數(shù)用到幾個(gè)全局變量,用于輔助解碼,并存儲(chǔ)解碼結(jié)果。最后是Remote_Scan函數(shù),該函用來(lái)掃描解碼結(jié)果,相當(dāng)于我們的按鍵掃描,輸入捕獲解碼的紅外數(shù)據(jù),通過(guò)該函數(shù)傳送給其他程序。
保存remote.c,然后把該文件加入HARDWARE組下。接下來(lái)打開(kāi)remote.h在該文件里面加入如下代碼:
//省略代碼
這里的REMOTE_ID就是我們開(kāi)發(fā)板配套的遙控器的識(shí)別碼,對(duì)于其他遙控器可能不一樣,只要修改這個(gè)為你所使用的遙控器的一致就可以了。其他是一些函數(shù)的聲明,我們保存此部分代碼,然后在test.c里面修改主函數(shù)如下:
int main(void)
{
//省略部分代碼
}
至此,我們的軟件設(shè)計(jì)部分就結(jié)束了。
32.4下載驗(yàn)證
在代碼編譯成功之后,我們通過(guò)下載代碼到ALIENTEK戰(zhàn)艦STM32開(kāi)發(fā)板上,可以看到LCD顯示如圖32.4.1所示的內(nèi)容:
圖32.4.1 程序運(yùn)行效果圖
此時(shí)我們通過(guò)遙控器按下不同的按鍵,則可以看到LCD上顯示了不同按鍵的鍵值以及按鍵次數(shù)和對(duì)應(yīng)的遙控器上的符號(hào)。如圖32.4.2所示:
圖32.4.2 解碼成功