標題: 求助!單片機紅外接收異常 上電后第一次正常 [打印本頁]

作者: kaixin8318    時間: 2020-2-4 09:52
標題: 求助!單片機紅外接收異常 上電后第一次正常
上電后第一次識別是正常的,第二次識別有一部分按鍵就會識別錯誤! 請高手指點下!

單片機源程序如下:

  1. #include "stc15f2k60s2.h"

  2. #include <intrins.h>

  3. #include "delay.h"
  4. #include "hongwaifashe.h"

  5. #define uchar        unsigned char
  6. #define UINT        unsigned int

  7. uchar setdata[3];//發(fā)送紅外用的   用戶碼 用戶碼 數(shù)據(jù)碼

  8. uchar IRtime;          //儲存檢測紅外高低電平持續(xù)時間
  9. uchar IRcord[4];  //儲存解碼后的4個字節(jié)數(shù)據(jù)
  10. uchar IRdata[33]; //包含起始碼在內(nèi)的33位數(shù)據(jù)
  11. bit IRpro_ok;          //解碼后4個字節(jié)數(shù)據(jù)接收完成標志位
  12. bit IRok;                  //33位數(shù)據(jù)接收完成標志

  13. uchar RX_Data[]=0;        //用于串口1接收數(shù)據(jù)數(shù)組保存變量定義
  14. uchar TX_Data[]=0;

  15. //======================================================================
  16. /*        Variable definition */
  17. //======================================================================
  18. /* 串口1相關(guān)變量定義 */
  19. #define FOSC 22118400L        //系統(tǒng)晶振頻率(單位:HZ)
  20. #define BAUD 9600                //串口1波特率

  21. #define NONE_PARITY         0                                //無校驗
  22. #define ODD_PARITY         1                                //奇校驗
  23. #define EVEN_PARITY         2                                //偶校驗
  24. #define MARK_PARITY         3                                //標記校驗
  25. #define SPACE_PARITY 4                                //空白校驗
  26. #define PARITYBIT          NONE_PARITY        //定義校驗位(無校驗)

  27. #define S1_S0 0x40        //P_SW1.6
  28. #define S1_S1 0x80        //P_SW1.7

  29. UINT CNT_RX;        //用于串口1接收數(shù)據(jù)計數(shù)保存變量定義
  30. UINT DAT_RX;        //用于串口1接收數(shù)據(jù)保存變量定義
  31. UINT JDE_RX;        //用于串口1接收數(shù)據(jù)判斷保存變量定義
  32. UINT DAT_Check;        //用于串口1發(fā)送的HDT數(shù)據(jù)的校驗和計算保存變量定義

  33. /* 串口中斷變量定義 */
  34. uchar K,H;                                //用于循環(huán)計數(shù)變量定義




  35. //======================================================================
  36. /*        Function declaration */
  37. //======================================================================
  38. void INIT_UART(void);                //串口初始化子函數(shù)定義(定時器中斷2)
  39. void SEND_UART(uchar DAT);        //串口發(fā)送數(shù)據(jù)子函數(shù)定義


  40. /***********************************************************************/
  41. //======================================================================
  42. //        MAIN FUNCTION
  43. //======================================================================
  44. /***********************************************************************/

  45. void time0() interrupt 1
  46. {
  47.         IRtime++;//255us
  48.         
  49.                 if(IRtime==100)     {CNT_RX=0;                JDE_RX=1; }
  50.         
  51. }

  52. //外部中斷0 存入33次脈寬
  53. void int0() interrupt 0
  54. {
  55.         static uchar i;//靜態(tài)變量用于存入33次數(shù)據(jù)計數(shù)
  56.         static bit startflag;//開始儲存脈寬標志位
  57.         if(startflag)
  58.         {
  59.                 /*判斷引導(dǎo)碼,如果是引導(dǎo)碼則從起始碼開始存*/
  60.                 if((IRtime < 63) && (IRtime >= 33))        i = 0;                    //
  61.                 IRdata[i] = IRtime;//以TO溢出的次數(shù)來計算脈寬把這個時間存放在數(shù)組中
  62.                 IRtime = 0;//計數(shù)清零
  63.                 i++;//計數(shù)脈寬存入次數(shù)自加
  64.                 if(i == 33)           //i等于33那么就表示已經(jīng)存入了33次脈寬
  65.                 {
  66.                         IRok = 1; //脈寬檢查完成
  67.                         i = 0;          //把脈寬計數(shù)清零準備下次存入
  68.                 }
  69.         }
  70.         else
  71.         {
  72.                 IRtime = 0;          //定時器0計數(shù)清零
  73.                 startflag = 1;//開始處理標志位置1
  74.         }

  75.                                 
  76.                                 
  77.                                 
  78. }

  79. //把提取的33次脈寬進行解碼 NEC協(xié)議
  80. void IRcordpro()
  81. {
  82.         uchar i;//i是用于計數(shù)處理4個字節(jié)
  83.         uchar j;//j用于計數(shù)處理1個字節(jié)的8位數(shù)據(jù)
  84.         uchar k;//k用于計數(shù)處理33次脈寬
  85.         k = 1;//從第一位脈寬開始處理,丟掉起始碼
  86.         for(i = 0; i < 4; i++)
  87.         {
  88.                 for(j = 0; j < 8; j++)
  89.                 {
  90.                         //如果脈寬大于數(shù)據(jù)0標準的1125us那么就判定為數(shù)據(jù)1
  91.                         if(IRdata[k] > 5      
  92.                                                                                                 
  93.                                                                                                               ) IRcord[i] |= 0x80;//寫1
  94.                         //只能右移7次,如果右移8次則會把第一位數(shù)據(jù)移出去
  95.                         if(j < 7) IRcord[i] >>= 1;
  96.                         k++; //處理下一次脈寬
  97.                 }
  98.         }
  99.         IRpro_ok = 1;//解碼完成
  100. }




  101. void main(void)
  102. {
  103.     /*===========================================================
  104.     ===========================================================*/
  105.         //上電,IO口初始化
  106.         P3M1=0x00; P3M0=0x00;        //準雙向IO口
  107.         P5M1=0x00; P5M0=0xff;        //推挽
  108.         P3=P5=0xFF;

  109.     //上電,定時器中斷0初始化
  110.            AUXR|=0x80;        //定時器時鐘為1T模式
  111.     TMOD&=0xF0;        //定時計數(shù)器0, 工作方式1
  112.     TL0 = 0xF8;                //設(shè)置定時初值
  113.           TH0 = 0xE9;                //設(shè)置定時初值                //設(shè)置定時初值  255us
  114.           ET0=1;            //允許定時/計數(shù)器0 中斷
  115.     TR0=1;            //啟動定時/計數(shù)器0 中斷
  116.         
  117.         
  118.      //上電,允許外部中斷0
  119.       IT0 = 1;//設(shè)置外部中斷0跳變沿觸發(fā)方式
  120.       EX0 = 1;//開外部中斷0中斷
  121.         
  122.         
  123.     //上電,串口中斷初始化
  124.     INIT_UART();        //串口中斷初始化
  125.                
  126.            EA=1;                        //打開總中斷
  127.         
  128.         /*===========================================================
  129.     ===========================================================*/        
  130.         while(1)
  131.         {
  132.                 uchar i; //計數(shù)串口發(fā)送字節(jié)數(shù)

  133.                
  134.                  if(IRok)//判斷33次脈寬是否提取完成
  135.                 {
  136.                          IRcordpro();//根據(jù)脈寬解碼出4個字節(jié)的數(shù)據(jù)
  137.                         IRok = 0;//清零脈寬檢查完成標志位等待下一次脈寬檢查
  138.                         if(IRpro_ok)//判斷解碼是否完成
  139.                         {
  140.                                                                
  141.                                                                                                         
  142.                                                                                                         
  143.                                                                                                         
  144. //                                                                                                        if(   IRcord[2]==~IRcord[3] )                        
  145. //                                                                                                                                
  146. //                                                                                                                        {        
  147.                                                                                                                                  
  148.                                                                                                                                 
  149.                                                                                                                    for(i = 0; i < 4; i++) //串口發(fā)送4個字節(jié)數(shù)據(jù)

  150.                                                                                                                                              SEND_UART(IRcord[i]) ;

  151. //                                }
  152. //                                                                                                
  153.                                                                                                                                  IRpro_ok = 0;//清零解碼標志位
  154.                                                                                                         
  155.                                                                                                         
  156.                                                                                                                    for(i = 0; i < 4; i++){
  157.                                  IRdata[i]=0;}
  158.                                                                                                         
  159.                         }
  160.                 }
  161.                
  162.                         

  163.                
  164.         
  165.         if(JDE_RX==2)   // 接收到指令
  166.        {
  167.                      
  168.                        if(RX_Data[1]==0xf1)
  169.                        
  170.                                                                  
  171.                        {
  172.         
  173.                    setdata[0]=  RX_Data[2] ;
  174.              setdata[1]=  RX_Data[3] ;
  175.              setdata[2]=  RX_Data[4] ;
  176.         
  177.                     hongwaifashe(  );


  178.                                                                  JDE_RX=1;   //  允許接收
  179.                                                                     CNT_RX=0;   // 接收數(shù)量清零
  180.                                                                  
  181.          }

  182.                  }                 
  183.                                  
  184.                                  
  185.                                  

  186.    }//while
  187.         
  188. }//main


  189. /***********************************************************************/
  190. //======================================================================
  191. //        UART interrupt service routine
  192. //  數(shù)據(jù)格式:0xFF,0x0A,0x05,0x06,0x00,0x00
  193. //======================================================================
  194. /***********************************************************************/
  195. void Uart_Isr() interrupt 4 using 1
  196. {
  197.         if(RI)
  198.   {
  199.                 RI=0;                                //清除RI位
  200.                 DAT_RX=SBUF;        //讀取串口1數(shù)據(jù)
  201.                
  202.                 /* 串口1接收數(shù)據(jù)和判斷數(shù)據(jù)結(jié)束 */
  203.                 if(JDE_RX==1)        //接收數(shù)據(jù)保存判斷
  204.                 {
  205.                         IRtime=0;  //計時器清零
  206.                         
  207.                         if((DAT_RX==0xFA)&(CNT_RX==0))         //避免少發(fā)數(shù)據(jù)出錯情況           每次接到FA 就會清空
  208.                         {
  209.                                                                                                                                                 
  210.                                 for(K=0;K<8;K++){RX_Data[K]=0;}        //串口接收的數(shù)據(jù)清0
  211.                   }
  212.                                                         
  213.                         RX_Data[CNT_RX]=DAT_RX;
  214.                         
  215.                         CNT_RX++;  //接收數(shù)量+1
  216.                         
  217.                         if(CNT_RX==5)  //接收5個字節(jié)
  218.                         {
  219.                                    
  220.                                 JDE_RX=2;                //串口接收數(shù)據(jù)判斷變量置2 接收完畢
  221.                         }
  222.                         
  223.                         
  224.                         
  225.                 }
  226.                
  227.   }
  228.         //if(TI){ TI=0; }        //清除TI位
  229. }



  230. /***********************************************************************/
  231. //======================================================================
  232. //  子函數(shù)定義
  233. //======================================================================
  234. /***********************************************************************/
  235. //串口初始化子函數(shù)定義(定時器中斷2)
  236. void INIT_UART(void)
  237. {
  238.         ACC = P_SW1;
  239.         ACC &= ~(S1_S0 | S1_S1);        //S1_S0=0 S1_S1=0
  240.         P_SW1 = ACC;                //(P3.0/RxD, P3.1/TxD)
  241.         
  242.         if(PARITYBIT==NONE_PARITY){ SCON = 0x50; }                                                                                                                //8位可變波特率
  243.         if((PARITYBIT==ODD_PARITY)|(PARITYBIT==EVEN_PARITY)|(PARITYBIT==MARK_PARITY)){ SCON = 0xda; }        //9位可變波特率,校驗位初始為1
  244.         if(PARITYBIT==SPACE_PARITY){ SCON = 0xd2; }                                                                                                                //9位可變波特率,校驗位初始為0
  245.         
  246.         PCON = 0x80;                                     //波特率不倍增
  247.         T2L = (65536-(FOSC/4/BAUD));        //設(shè)置波特率重裝值
  248.     T2H = (65536-(FOSC/4/BAUD))>>8;
  249.     AUXR |= 0x14;                                        //T2為1T模式, 并啟動定時器2
  250.     AUXR |= 0x01;                       //選擇定時器2為串口1的波特率發(fā)生器
  251.     ES = 1;                             //使能串口1中斷
  252. }


  253. //串口發(fā)送數(shù)據(jù)子函數(shù)定義
  254. void SEND_UART(UCHAR DAT)
  255. {
  256.         SBUF=DAT;
  257.         while(!TI);        //等特數(shù)據(jù)傳送
  258.         TI=0;                //清除數(shù)據(jù)傳送標志
  259. }
復(fù)制代碼






作者: 12abcfef    時間: 2020-2-4 13:55
各連接處固定后上電  接觸松動  造成局部電壓不穩(wěn)
作者: 仰空    時間: 2020-2-4 15:41
我以前在學(xué)單片機,看著你的代碼感覺我自己要加油呀
作者: kaixin8318    時間: 2020-2-4 18:10
電路沒有虛連的情況,只要上電第一次解碼  肯定是正常的,第2次開始 有一部分按鍵的數(shù)據(jù)或者數(shù)據(jù)反碼 就會出現(xiàn)一位的錯誤
就是說解碼部分運行一次就不正常了!~
作者: kaixin8318    時間: 2020-2-4 18:12
而且我試過解碼成功發(fā)送完畢后,我從新執(zhí)行一次上電初始化的內(nèi)容也不管用




歡迎光臨 (http://www.torrancerestoration.com/bbs/) Powered by Discuz! X3.1