實驗目的:利用計數器0和外部中斷0進行紅外解碼,將20鍵紅外遙控器鍵碼顯示在兩位數碼管上
遇到問題:將hex文件下載到單片機按下按鍵數碼管顯示鍵碼與遙控器鍵碼不一致。例如按下按鍵“+”,數碼管顯示41,但是正確鍵碼為40;又如按下遙控器播放按鈕,數碼管顯示1C,標準鍵碼為15.
請論壇各位前輩大佬幫我看看是哪里出錯誤了,謝謝
單片機程序代碼如下:
- #include <REGX52.H>
- sbit IR_INPUT=P3^2; //紅外接收引腳
- unsigned char ircode[4]; //紅外代碼接收緩沖區
- unsigned char NixeTable[]= //共陰數碼管鍵碼
- {0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,
- 0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71};
- /*軟件生成的延時函數,延時xms*/
- void Delay(unsigned int xms) //@12.000MHz
- {
- unsigned char i, j;
- while(xms--)
- {
- i = 12;
- j = 169;
- do
- {
- while (--j);
- } while (--i);
- }
-
- }
- /*數碼管顯示函數,用兩位數碼管顯示紅外控制碼*/
- void Nixie(unsigned char Location,Number)
- {
- switch(Location) //位選
- {
- case 1:
- P2_4=1;P2_3=1;P2_2=1;break;
- case 2:
- P2_4=1;P2_3=1;P2_2=0;break;
- }
- P0=NixeTable[Number]; //段選
- Delay(1); //這里沒有延時數碼管會很暗
- P0=0x00; //消隱
- }
- /*計數器0初始化函數*/
- void Timer0_Init(void)
- {
- TMOD &= 0xF0; //設置定時器模式
- TMOD |= 0x01; //設置定時器模式
- TL0 = 0; //設置定時初值
- TH0 = 0; //設置定時初值
- TF0 = 0; //清除TF0標志
- TR0 = 0; //定時器0不計時
- }
- /*外部中斷0初始化函數*/
- void Int0_Init(void)
- {
- IT0=1; //設置INT0下降沿觸發
- IE0=0; //清空外部中斷0中斷請求標志位
- EX0=1; //打開外部中斷0
- EA=1; //打開總中斷開關
- PX0=1; //設置外部中斷優先級
- }
- /*獲取高電平時間*/
- unsigned int GetHighTime()
- {
- TH0=0; //清零T0計數器初值
- TL0=0;
- TR0=1; //啟動T0計數
- while(IR_INPUT) //紅外輸入引腳為1時循環檢測等待,遇到下降沿時結束循環
- {
- if(TH0>=0x40) {break;} //當T0計數值大于18ms強制退出,避免程序死在這里
- }
- TR0=0; //停止計數
- return(TH0*256+TL0); //計數值合成16位整形數
- }
- /*獲取低電平時間*/
- unsigned int GetLowTime()
- {
- TH0=0;
- TL0=0;
- TR0=1;
- while(!IR_INPUT)
- {
- if(TH0>=0x40) {break;}
- }
- TR0=0;
- return(TH0*256+TL0);
- }
- /*主函數*/
- void main()
- {
- Timer0_Init();
- Int0_Init();
- while(1)
- {
- Nixie(1,ircode[2]>>4);
- Nixie(2,ircode[2]&0x0F);
- }
- }
- /*外部中斷服務子函數,執行紅外接收和解碼*/
- void Int0_Routine() interrupt 0
- {
- unsigned char i,j;
- unsigned char byt;
- unsigned int time;
-
- //接收并判定引導碼的9ms低電平
- time=GetLowTime();
- if((time<7833)||(time>8755)) //時間判定范圍為8.5ms~9.5ms,超出范圍則為誤碼
- {
- IE0=0; //退出前清零INT0中斷標志
- return;
- }
- //接收并判定引導碼的4.5ms低電平
- time=GetHighTime();
- if((time<3686)||(time>4608)) //時間判定范圍為4.0ms~5.0ms,超出范圍則為誤碼
- {
- IE0=0; //退出前清零INT0中斷標志
- return;
- }
-
- //接收并判定后續的4字節數據
- for(i=0;i<4;i++) //循環接收4個字節
- {
- for(j=0;j<8;j++) //循環接收判定每個字節的八位
- {
- time=GetLowTime();
- if((time<313)||(time>718)) //時間判定范圍為340us~780us,超出范圍則為誤碼
- {
- IE0=0;
- return;
- }
- time=GetHighTime();
- if((time>313)&&(time<718)) //時間判定范圍為340us~780us,在此范圍內說明該位為0
- {
- byt>>=1; //低位在先,數據右移,高位置零
- }
- else if((time>1345)&&(time<1751)) //時間判定范圍為1460us~1900us,在此范圍內說明該位為1
- {
- byt>>1; //低位在先,數據右移
- byt|=0x80; //高位置1
- }
- else
- {
- IE0=0;
- return;
- }
- }
- ircode[i]=byt; //接收完一個字節后保存到數組
- }
- IE0=0; //清零INT0標志
- }
復制代碼
按下“+”數碼管顯示
按下播放鍵數碼管顯示
紅外遙控器標準鍵碼
程序編譯后有一個警告:
程序編譯信息
|