一、項(xiàng)目介紹
遙控器是現(xiàn)代生活中必不可少的電子產(chǎn)品之一,目前市面上的遙控器種類繁多,應(yīng)用范圍廣泛。而 NEC 紅外遙控器協(xié)議則是目前應(yīng)用最為廣泛的一種協(xié)議之一,幾乎所有的電視、空調(diào)等家用電器都支持該協(xié)議。
本項(xiàng)目是基于 51 單片機(jī)設(shè)計(jì)支持 NEC 協(xié)議的紅外遙控器,實(shí)現(xiàn)接收解碼和發(fā)送功能。用戶通過按下相應(yīng)按鍵進(jìn)行信號的發(fā)射,紅外發(fā)射二極管向外發(fā)射紅外信號,被控制設(shè)備通過紅外接收頭接收到這個信號,然后解碼執(zhí)行相應(yīng)的操作。
二、硬件設(shè)計(jì)
本項(xiàng)目所需的硬件器件主要包括:
(1)5STC89C52單片機(jī)
(2)紅外發(fā)射管
(3)紅外接收頭
(4)OLED顯示屏
(5)按鍵開關(guān)
三、軟件設(shè)計(jì)
本項(xiàng)目的程序代碼采用 C 語言編寫,主要分為三個部分:初始化部分、接收解碼部分和發(fā)送數(shù)據(jù)部分。
(1)初始化部分
初始化函數(shù)主要完成各個端口的初始化和定時器的配置,以及紅外接收頭和紅外發(fā)射管的引腳的配置。
(2)接收解碼部分
接收解碼函數(shù)主要采用計(jì)數(shù)器方式對紅外遙控器發(fā)送的信號進(jìn)行捕獲,并將捕獲到的信號轉(zhuǎn)換成 NEC 碼。然后根據(jù) NEC 碼的規(guī)定,解碼出用戶所輸入的指令,最終實(shí)現(xiàn)控制設(shè)備的功能。
(3)發(fā)送數(shù)據(jù)部分
發(fā)送數(shù)據(jù)函數(shù)主要將單片機(jī)中存放的指令碼進(jìn)行編碼,并通過紅外發(fā)射管發(fā)送給被控制的設(shè)備。在該函數(shù)中,需要通過計(jì)時器的方式來調(diào)節(jié)發(fā)送信號的時間和頻率,以保證信號能夠正確傳輸。
四、代碼實(shí)現(xiàn)
4.1 NEC協(xié)議解碼代碼
下面是基于 51 單片機(jī)實(shí)現(xiàn) NEC 協(xié)議解碼的代碼:
#define IRIN P1_0 //紅外接收管
unsigned char code Remote6[] = {0x06, 0x09, 0x08, 0x0a, 0x0c, 0x0d, 0x0f};
//遙控器按鍵對應(yīng)的命令碼
?
unsigned char read_IR() //讀取紅外信號
{
int k = 0;
unsigned char data = 0;
?
while (IRIN) //等待低電平出現(xiàn)
{
k++;
?
if (k > 1000)
return 0; //超時返回
}
?
k = 0;
?
while (!IRIN) //等待高電平出現(xiàn)
{
k++;
?
if (k > 1000)
return 0; //超時返回
}
?
k = 0;
?
while (IRIN) //等待低電平出現(xiàn)
{
k++;
?
if (k > 1000)
return 0; //超時返回
}
?
for (int i = 0; i < 8; i++) //解碼 8 個 bit
{
k = 0;
?
while (!IRIN) //等待高電平出現(xiàn)
{
k++;
?
if (k > 1000)
return 0; //超時返回
}
?
delay_us(650);
?
if (IRIN) //判斷 bit 的值
data |= (1 < < i);
?
k = 0;
?
while (IRIN) //等待低電平出現(xiàn)
{
k++;
?
if (k > 1000)
return 0; //超時返回
}
}
?
return data; //返回解碼結(jié)果
}
?
unsigned char decode_IR(unsigned char code_val) //NEC 碼轉(zhuǎn)換為命令碼
{
for (int i = 0; i < 7; i++)
{
if (Remote6[i] == code_val)
return (i + 1);
}
?
return 0;
}
?
void main()
{
unsigned char data = 0;
unsigned char code_val = 0;
?
while (1)
{
data = read_IR(); //讀取紅外信號
?
if (data == 0) //判斷是否讀取成功
continue;
?
code_val = decode_IR(data); //將 NEC 碼轉(zhuǎn)換為命令碼
?
switch (code_val) //根據(jù)命令碼控制設(shè)備
{
case 1: //控制設(shè)備執(zhí)行命令 1
break;
case 2: //控制設(shè)備執(zhí)行命令 2
break;
case