實驗報告 一、 實驗名稱 紅外接收試驗 二、 實驗原理以及要求 1.紅外線原理 紅外線是波長在760nm~1mm之間的非可見光。紅外通信裝置由紅外發射管和紅外接受管組成,紅外發射管是能發射出紅外線的發光二極管,發射強度隨著電流的增大而增大;紅外接受管是一個具有紅外光敏感特征的PN節的光敏二極管,只對紅外線有反應,產生光電流。 產生下降沿,進入外部中斷0的中斷函數,延時一下之后檢IO口是否還是低電平,是就等待9ms的低電平過去。等待完9ms低電平過去,再去等待4.5ms的高電平過去。接著開始接收傳送的4組數據先等待560us的低電平過去檢測高電平的持續時間,如果超過1.12ms那么是高電平(高電平的的持續時間為1.69ms,低電平的持續時間為565us。)檢測接收到的數據和數據的反碼進行比較,是否等到的數據是一樣的。 2.信號調制原理 基帶信號:從信號源發出沒有經過調制的原始信號,特點是頻率較低,信號頻率從0開始,頻譜較寬。 調制:就是用待傳送信號去控制某個高頻信號的幅度、相位、頻率等參量變化的過程,即用一個信號去裝載另一個信號。 紅外遙控器使用38KB的載波對原始信號進行解調,原理如下
file:///C:\Users\WANGYA~1\AppData\Local\Temp\ksohtml\wpsF2FC.tmp.jpg
調制后產生一定頻段的高低電平,但紅外接收頭接受到的信號和調制后的信號電平相反。 3.NEC協議 紅外遙控由多種協議控制,這里介紹最主要,應用最廣的NEC協議。NEC數據格式:引導碼、用戶碼、用戶碼(或者用戶碼反碼)、按鍵鍵碼和鍵碼反碼,最后一個停止位。 引導碼:9ms的載波+4.5ms的空閑。 比特值“0”:560us的載波+560us的空閑。 比特值“1”:560us的載波+1.68ms的空閑。
file:///C:\Users\WANGYA~1\AppData\Local\Temp\ksohtml\wpsF2FD.tmp.jpg
協議規定低位首先發送。一串信息首先發送9ms的AGC(自動增益控制)的高脈沖,接著發送4.5ms的起始低電平,接下來是發送四個字節的地址碼和命令碼。如果你一直按那個按鍵,一串信息也只能發送一次,一直按著,發送的則是以110ms為周期的重復碼。 4.實驗原理圖: file:///C:\Users\WANGYA~1\AppData\Local\Temp\ksohtml\wpsF30E.tmp.jpg 三、實驗步驟: (1)本實驗通過單片機控制紅外接受設備接受紅外發送設備發送的信號,并通過數碼管的顯示判斷是否接受到信號。實驗接線為JP10接J12,J6的A,B,C分別接P2.2,P2.3,P2.4。 (2)在完成實驗代碼后將代碼燒進單片機內。通過紅外遙控檢驗實驗是否正確。 四、實驗代碼 #include<reg51.h> #define GPIO_DIG P0 sbit LSA = P2^2; sbit LSB = P2^3; sbit LSC = P2^4; sbit IRIN = P3^2; //紅外接收器位聲明 unsigned char code DIG_CODE[17]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07, 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; unsigned char DisplayData[8]; //用來存放要顯示的8位數的值 unsigned char IrValue[6]; //用來存放讀取到的紅外值 unsigned char Time; void DigDisplay(); //動態顯示函數 void IrInit(); void DelayMs(unsigned int); void main() { IrInit(); while(1) { IrValue[4]=IrValue[2]>>4; //高位 IrValue[5]=IrValue[2]&0x0f; //低位 DisplayData[0] = 0x00; DisplayData[1] = DIG_CODE[IrValue[4]]; DisplayData[2] = DIG_CODE[IrValue[5]]; DisplayData[3] = 0x76; DisplayData[4] = 0x00; DisplayData[5] = DIG_CODE[IrValue[4]]; DisplayData[6] = DIG_CODE[IrValue[5]]; DisplayData[7] = 0x76; DigDisplay(); } } void DelayMs(unsigned int x) //0.14ms誤差 0us { unsigned char i; while(x--) { for (i = 0; i<13; i++); } } void IrInit() { IT0=1; //下降沿觸發 EX0=1; //打開中斷0允許 EA=1; //打開總中斷 IRIN=1; //初始化端口 } void ReadIr() interrupt 0 { unsigned char j,k; unsigned int err; Time=0; DelayMs(70); if(IRIN==0) //確認是否真的接收到正確的信號 { err=1000; //1000*10us=10ms,超過說明接收到錯誤的信號 while((IRIN==0)&&(err>0)) //等待前面9ms的低電平過去 { DelayMs(1); err--; } if(IRIN==1) //如果正確等到9ms低電平 { err=500; while((IRIN==1)&&(err>0)) //等待4.5ms的起始高電平過去 { DelayMs(1); err--; } for(k=0;k<4;k++) //共有4組數據 { for(j=0;j<8;j++) //接收一組數據 { err=60; while((IRIN==0)&&(err>0))//等待信號前面的560us低電平過去 { DelayMs(1); err--; } err=500; while((IRIN==1)&&(err>0))//計算高電平的時間長度。 { DelayMs(1); //0.14ms Time++; err--; if(Time>30) { EX0=1; return; } } IrValue[k]>>=1; //k表示第幾組數據 if(Time>=8) //如果高電平出現大于565us,那么是1 { IrValue[k]|=0x80; } Time=0; //用完時間要重新賦值 } } } if(IrValue[2]!=~IrValue[3]) //反碼取反后與原碼相同則說明信號接受正確 { return; } } } void DigDisplay() { unsigned char i; unsigned int j; for(i=0;i<8;i++) { switch(i) //位選,選擇點亮的數碼管 { case(0): LSA=0;LSB=0;LSC=0; break; //顯示第0位 case(1): LSA=1;LSB=0;LSC=0; break; //顯示第1位 case(2): LSA=0;LSB=1;LSC=0; break; //顯示第2位 case(3): LSA=1;LSB=1;LSC=0; break; //顯示第3位 case(4): LSA=0;LSB=0;LSC=1; break; //顯示第4位 case(5): LSA=1;LSB=0;LSC=1; break; //顯示第5位 case(6): LSA=0;LSB=1;LSC=1; break; //顯示第6位 case(7): LSA=1;LSB=1;LSC=1; break; //顯示第7位 } GPIO_DIG=DisplayData; //發送段碼 j=10; //掃描間隔時間設定 while(j--); GPIO_DIG=0x00; //消隱 } }
|