上電后第一次識別是正常的,第二次識別有一部分按鍵就會識別錯誤! 請高手指點下!
單片機源程序如下:
- #include "stc15f2k60s2.h"
- #include <intrins.h>
- #include "delay.h"
- #include "hongwaifashe.h"
- #define uchar unsigned char
- #define UINT unsigned int
- uchar setdata[3];//發送紅外用的 用戶碼 用戶碼 數據碼
- uchar IRtime; //儲存檢測紅外高低電平持續時間
- uchar IRcord[4]; //儲存解碼后的4個字節數據
- uchar IRdata[33]; //包含起始碼在內的33位數據
- bit IRpro_ok; //解碼后4個字節數據接收完成標志位
- bit IRok; //33位數據接收完成標志
- uchar RX_Data[]=0; //用于串口1接收數據數組保存變量定義
- uchar TX_Data[]=0;
- //======================================================================
- /* Variable definition */
- //======================================================================
- /* 串口1相關變量定義 */
- #define FOSC 22118400L //系統晶振頻率(單位:HZ)
- #define BAUD 9600 //串口1波特率
- #define NONE_PARITY 0 //無校驗
- #define ODD_PARITY 1 //奇校驗
- #define EVEN_PARITY 2 //偶校驗
- #define MARK_PARITY 3 //標記校驗
- #define SPACE_PARITY 4 //空白校驗
- #define PARITYBIT NONE_PARITY //定義校驗位(無校驗)
- #define S1_S0 0x40 //P_SW1.6
- #define S1_S1 0x80 //P_SW1.7
- UINT CNT_RX; //用于串口1接收數據計數保存變量定義
- UINT DAT_RX; //用于串口1接收數據保存變量定義
- UINT JDE_RX; //用于串口1接收數據判斷保存變量定義
- UINT DAT_Check; //用于串口1發送的HDT數據的校驗和計算保存變量定義
- /* 串口中斷變量定義 */
- uchar K,H; //用于循環計數變量定義
- //======================================================================
- /* Function declaration */
- //======================================================================
- void INIT_UART(void); //串口初始化子函數定義(定時器中斷2)
- void SEND_UART(uchar DAT); //串口發送數據子函數定義
- /***********************************************************************/
- //======================================================================
- // MAIN FUNCTION
- //======================================================================
- /***********************************************************************/
- void time0() interrupt 1
- {
- IRtime++;//255us
-
- if(IRtime==100) {CNT_RX=0; JDE_RX=1; }
-
- }
- //外部中斷0 存入33次脈寬
- void int0() interrupt 0
- {
- static uchar i;//靜態變量用于存入33次數據計數
- static bit startflag;//開始儲存脈寬標志位
- if(startflag)
- {
- /*判斷引導碼,如果是引導碼則從起始碼開始存*/
- if((IRtime < 63) && (IRtime >= 33)) i = 0; //
- IRdata[i] = IRtime;//以TO溢出的次數來計算脈寬把這個時間存放在數組中
- IRtime = 0;//計數清零
- i++;//計數脈寬存入次數自加
- if(i == 33) //i等于33那么就表示已經存入了33次脈寬
- {
- IRok = 1; //脈寬檢查完成
- i = 0; //把脈寬計數清零準備下次存入
- }
- }
- else
- {
- IRtime = 0; //定時器0計數清零
- startflag = 1;//開始處理標志位置1
- }
-
-
-
- }
- //把提取的33次脈寬進行解碼 NEC協議
- void IRcordpro()
- {
- uchar i;//i是用于計數處理4個字節
- uchar j;//j用于計數處理1個字節的8位數據
- uchar k;//k用于計數處理33次脈寬
- k = 1;//從第一位脈寬開始處理,丟掉起始碼
- for(i = 0; i < 4; i++)
- {
- for(j = 0; j < 8; j++)
- {
- //如果脈寬大于數據0標準的1125us那么就判定為數據1
- if(IRdata[k] > 5
-
- ) IRcord[i] |= 0x80;//寫1
- //只能右移7次,如果右移8次則會把第一位數據移出去
- if(j < 7) IRcord[i] >>= 1;
- k++; //處理下一次脈寬
- }
- }
- IRpro_ok = 1;//解碼完成
- }
- void main(void)
- {
- /*===========================================================
- ===========================================================*/
- //上電,IO口初始化
- P3M1=0x00; P3M0=0x00; //準雙向IO口
- P5M1=0x00; P5M0=0xff; //推挽
- P3=P5=0xFF;
- //上電,定時器中斷0初始化
- AUXR|=0x80; //定時器時鐘為1T模式
- TMOD&=0xF0; //定時計數器0, 工作方式1
- TL0 = 0xF8; //設置定時初值
- TH0 = 0xE9; //設置定時初值 //設置定時初值 255us
- ET0=1; //允許定時/計數器0 中斷
- TR0=1; //啟動定時/計數器0 中斷
-
-
- //上電,允許外部中斷0
- IT0 = 1;//設置外部中斷0跳變沿觸發方式
- EX0 = 1;//開外部中斷0中斷
-
-
- //上電,串口中斷初始化
- INIT_UART(); //串口中斷初始化
-
- EA=1; //打開總中斷
-
- /*===========================================================
- ===========================================================*/
- while(1)
- {
- uchar i; //計數串口發送字節數
-
- if(IRok)//判斷33次脈寬是否提取完成
- {
- IRcordpro();//根據脈寬解碼出4個字節的數據
- IRok = 0;//清零脈寬檢查完成標志位等待下一次脈寬檢查
- if(IRpro_ok)//判斷解碼是否完成
- {
-
-
-
-
- // if( IRcord[2]==~IRcord[3] )
- //
- // {
-
-
- for(i = 0; i < 4; i++) //串口發送4個字節數據
- SEND_UART(IRcord[i]) ;
- // }
- //
- IRpro_ok = 0;//清零解碼標志位
-
-
- for(i = 0; i < 4; i++){
- IRdata[i]=0;}
-
- }
- }
-
-
-
-
- if(JDE_RX==2) // 接收到指令
- {
-
- if(RX_Data[1]==0xf1)
-
-
- {
-
- setdata[0]= RX_Data[2] ;
- setdata[1]= RX_Data[3] ;
- setdata[2]= RX_Data[4] ;
-
- hongwaifashe( );
- JDE_RX=1; // 允許接收
- CNT_RX=0; // 接收數量清零
-
- }
- }
-
-
-
- }//while
-
- }//main
- /***********************************************************************/
- //======================================================================
- // UART interrupt service routine
- // 數據格式:0xFF,0x0A,0x05,0x06,0x00,0x00
- //======================================================================
- /***********************************************************************/
- void Uart_Isr() interrupt 4 using 1
- {
- if(RI)
- {
- RI=0; //清除RI位
- DAT_RX=SBUF; //讀取串口1數據
-
- /* 串口1接收數據和判斷數據結束 */
- if(JDE_RX==1) //接收數據保存判斷
- {
- IRtime=0; //計時器清零
-
- if((DAT_RX==0xFA)&(CNT_RX==0)) //避免少發數據出錯情況 每次接到FA 就會清空
- {
-
- for(K=0;K<8;K++){RX_Data[K]=0;} //串口接收的數據清0
- }
-
- RX_Data[CNT_RX]=DAT_RX;
-
- CNT_RX++; //接收數量+1
-
- if(CNT_RX==5) //接收5個字節
- {
-
- JDE_RX=2; //串口接收數據判斷變量置2 接收完畢
- }
-
-
-
- }
-
- }
- //if(TI){ TI=0; } //清除TI位
- }
- /***********************************************************************/
- //======================================================================
- // 子函數定義
- //======================================================================
- /***********************************************************************/
- //串口初始化子函數定義(定時器中斷2)
- void INIT_UART(void)
- {
- ACC = P_SW1;
- ACC &= ~(S1_S0 | S1_S1); //S1_S0=0 S1_S1=0
- P_SW1 = ACC; //(P3.0/RxD, P3.1/TxD)
-
- if(PARITYBIT==NONE_PARITY){ SCON = 0x50; } //8位可變波特率
- if((PARITYBIT==ODD_PARITY)|(PARITYBIT==EVEN_PARITY)|(PARITYBIT==MARK_PARITY)){ SCON = 0xda; } //9位可變波特率,校驗位初始為1
- if(PARITYBIT==SPACE_PARITY){ SCON = 0xd2; } //9位可變波特率,校驗位初始為0
-
- PCON = 0x80; //波特率不倍增
- T2L = (65536-(FOSC/4/BAUD)); //設置波特率重裝值
- T2H = (65536-(FOSC/4/BAUD))>>8;
- AUXR |= 0x14; //T2為1T模式, 并啟動定時器2
- AUXR |= 0x01; //選擇定時器2為串口1的波特率發生器
- ES = 1; //使能串口1中斷
- }
- //串口發送數據子函數定義
- void SEND_UART(UCHAR DAT)
- {
- SBUF=DAT;
- while(!TI); //等特數據傳送
- TI=0; //清除數據傳送標志
- }
復制代碼
|