創(chuàng)建好“infrared.c”和“infrared.h”文件。
1.infrared.c的代碼
#include <reg52.h> #include <infrared.h> unsigned char irflag = 0; //紅外接收標(biāo)志,收到一幀正確數(shù)據(jù)后置1 unsigned char ircode[4]; //紅外代碼接收緩沖區(qū) /* 初始化紅外接收功能 */ void InitInfrared() { IR_INPUT = 1; //確保紅外接收引腳被釋放 TMOD &= 0x0F; //清零T1的控制位 TMOD |= 0x10; //配置T1為模式1 TR1 = 0; //停止T1計(jì)數(shù) ET1 = 0; //禁止T1中斷 IT1 = 1; //設(shè)置INT1為負(fù)邊沿觸發(fā) EX1 = 1; //使能INT1中斷 } /* 獲取當(dāng)前高電平的持續(xù)時(shí)間 */ unsigned int GetHighTime() { TH1 = 0; //清零T1計(jì)數(shù)初值 TL1 = 0; TR1 = 1; //啟動(dòng)T1計(jì)數(shù) while (IR_INPUT) //紅外輸入引腳為1時(shí)循環(huán)檢測(cè)等待,變?yōu)?時(shí)則結(jié)束本循環(huán) { if (TH1 >= 0x40) { //當(dāng)T1計(jì)數(shù)值大于0x4000,即高電平持續(xù)時(shí)間超過(guò)約18ms時(shí), break; //強(qiáng)制退出循環(huán),是為了避免信號(hào)異常時(shí),程序假死在這里。 } } TR1 = 0; //停止T1計(jì)數(shù) return (TH1*256 + TL1); //T1計(jì)數(shù)值合成為16bit整型數(shù),并返回該數(shù) } /* 獲取當(dāng)前低電平的持續(xù)時(shí)間 */ unsigned int GetLowTime() { TH1 = 0; //清零T1計(jì)數(shù)初值 TL1 = 0; TR1 = 1; //啟動(dòng)T1計(jì)數(shù) while (!IR_INPUT) //紅外輸入引腳為0時(shí)循環(huán)檢測(cè)等待,變?yōu)?時(shí)則結(jié)束本循環(huán) { if (TH1 >= 0x40) { //當(dāng)T1計(jì)數(shù)值大于0x4000,即低電平持續(xù)時(shí)間超過(guò)約18ms時(shí), break; //強(qiáng)制退出循環(huán),是為了避免信號(hào)異常時(shí),程序假死在這里。 } } TR1 = 0; //停止T1計(jì)數(shù) return (TH1*256 + TL1); //T1計(jì)數(shù)值合成為16bit整型數(shù),并返回該數(shù) } /* INT1中斷服務(wù)函數(shù),執(zhí)行紅外接收及解碼 */ void EXINT1_ISR() interrupt 2 { unsigned char i,j; unsigned char byt; unsigned int time; //接收并判定引導(dǎo)碼的9ms低電平 time = GetLowTime(); if ((time<7833) || (time>8755)) //時(shí)間判定范圍為8.5~9.5ms, { //超過(guò)此范圍則說(shuō)明為誤碼,直接退出 IE1 = 0; //退出前清零INT1中斷標(biāo)志 return; } //接收并判定引導(dǎo)碼的4.5ms高電平 time = GetHighTime(); if ((time<3686) || (time>4608)) //時(shí)間判定范圍為4.0~5.0ms, { //超過(guò)此范圍則說(shuō)明為誤碼,直接退出 IE1 = 0; return; } //接收并判定后續(xù)的4字節(jié)數(shù)據(jù) for (i=0; i<4; i++) //循環(huán)接收4個(gè)字節(jié) { for (j=0; j<8; j++) //循環(huán)接收判定每字節(jié)的8個(gè)bit { //接收判定每bit的560us低電平 time = GetLowTime(); if ((time<313) || (time>718)) //時(shí)間判定范圍為340~780us, { //超過(guò)此范圍則說(shuō)明為誤碼,直接退出 IE1 = 0; return; } //接收每bit高電平時(shí)間,判定該bit的值 time = GetHighTime(); if ((time>313) && (time<718)) //時(shí)間判定范圍為340~780us, { //在此范圍內(nèi)說(shuō)明該bit值為0 byt >>= 1; //因低位在先,所以數(shù)據(jù)右移,高位為0 } else if ((time>1345) && (time<1751)) //時(shí)間判定范圍為1460~1900us, { //在此范圍內(nèi)說(shuō)明該bit值為1 byt >>= 1; //因低位在先,所以數(shù)據(jù)右移, byt |= 0x80; //高位置1 } else //不在上述范圍內(nèi)則說(shuō)明為誤碼,直接退出 { IE1 = 0; return; } } ircode[i] = byt; //接收完一個(gè)字節(jié)后保存到緩沖區(qū) } irflag = 1; //接收完畢后設(shè)置標(biāo)志 IE1 = 0; //退出前清零INT1中斷標(biāo)志 }
2.infrared.h的代碼
因?yàn)橹骱瘮?shù)中只需要使用“InitInfrared();”函數(shù)來(lái)初始化,而“unsigned int GetHighTime()”和“unsigned int GetLowTime()”都是只在“void EXINT1_ISR() interrupt 2”中使用,所以頭文件不用聲明這三部分的函數(shù)。
#ifndef __INFRARED_H__ #define __INFRARED_H__ sbit IR_INPUT = P3^3; //紅外接收引腳 extern unsigned char irflag; //紅外接收標(biāo)志,收到一幀正確數(shù)據(jù)后置1 extern unsigned char ircode[4]; //紅外代碼接收緩沖區(qū) void InitInfrared(); //初始化紅外接收功能 #endif
3.main.c測(cè)試代碼
我們?cè)谒卫蠋煹睦蘬esson16_1中通過(guò)按紅外遙控器上的按鍵得知,第一行的三個(gè)按鍵會(huì)使ircode[2]分別變?yōu)?x45、0x46、0x47顯示在數(shù)碼管上,那么我們只需要判斷ircode[2]的數(shù)據(jù)就可以知道按下的是哪個(gè)按鍵然后去執(zhí)行相關(guān)任務(wù)就可以了。
我們用小燈測(cè)試紅外遙控器的按鍵是否有效,有效則會(huì)切換小燈的亮滅。
#include <reg52.h> #include <function.h>//詳見第六章第8講 #include <infrared.h> void main() { LED_Init();//初始化LED硬件模塊 EA = 1; InitInfrared(); while (1) { if (irflag) { irflag = 0; //以下是遙控器第一行按鍵 if(ircode[2]==0x45)LED9=!LED9; if(ircode[2]==0x46)LED8=!LED8; if(ircode[2]==0x47)LED7=!LED7; //以下是遙控器第二行按鍵 if(ircode[2]==0x44)LED4=!LED4; if(ircode[2]==0x40)LED3=!LED3; if(ircode[2]==0x43)LED2=!LED2; } } }
C語(yǔ)言網(wǎng)提供由在職研發(fā)工程師或ACM藍(lán)橋杯競(jìng)賽優(yōu)秀選手錄制的視頻教程,并配有習(xí)題和答疑,點(diǎn)擊了解:
一點(diǎn)編程也不會(huì)寫的:零基礎(chǔ)C語(yǔ)言學(xué)練課程
解決困擾你多年的C語(yǔ)言疑難雜癥特性的C語(yǔ)言進(jìn)階課程
從零到寫出一個(gè)爬蟲的Python編程課程
只會(huì)語(yǔ)法寫不出代碼?手把手帶你寫100個(gè)編程真題的編程百練課程
信息學(xué)奧賽或C++選手的 必學(xué)C++課程
藍(lán)橋杯ACM、信息學(xué)奧賽的必學(xué)課程:算法競(jìng)賽課入門課程
手把手講解近五年真題的藍(lán)橋杯輔導(dǎo)課程