找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 2489|回复: 4
打印 上一主题 下一主题
收起左侧

求助!单片机红外接收异常 上电后第一次正常

[复制链接]
跳转到指定楼层
楼主
ID:325735 发表于 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];//发送红外用的   用户码 用户码 数据码

  8. uchar IRtime;          //储存检测红外高低电平持续时间
  9. uchar IRcord[4];  //储存解码后的4个字节数据
  10. uchar IRdata[33]; //包含起始码在内的33位数据
  11. bit IRpro_ok;          //解码后4个字节数据接收完成标志位
  12. bit IRok;                  //33位数据接收完成标志

  13. uchar RX_Data[]=0;        //用于串口1接收数据数组保存变量定义
  14. uchar TX_Data[]=0;

  15. //======================================================================
  16. /*        Variable definition */
  17. //======================================================================
  18. /* 串口1相关变量定义 */
  19. #define FOSC 22118400L        //系统晶振频率(单位: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接收数据计数保存变量定义
  30. UINT DAT_RX;        //用于串口1接收数据保存变量定义
  31. UINT JDE_RX;        //用于串口1接收数据判断保存变量定义
  32. UINT DAT_Check;        //用于串口1发送的HDT数据的校验和计算保存变量定义

  33. /* 串口中断变量定义 */
  34. uchar K,H;                                //用于循环计数变量定义




  35. //======================================================================
  36. /*        Function declaration */
  37. //======================================================================
  38. void INIT_UART(void);                //串口初始化子函数定义(定时器中断2)
  39. void SEND_UART(uchar DAT);        //串口发送数据子函数定义


  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;//静态变量用于存入33次数据计数
  56.         static bit startflag;//开始储存脉宽标志位
  57.         if(startflag)
  58.         {
  59.                 /*判断引导码,如果是引导码则从起始码开始存*/
  60.                 if((IRtime < 63) && (IRtime >= 33))        i = 0;                    //
  61.                 IRdata[i] = IRtime;//以TO溢出的次数来计算脉宽把这个时间存放在数组中
  62.                 IRtime = 0;//计数清零
  63.                 i++;//计数脉宽存入次数自加
  64.                 if(i == 33)           //i等于33那么就表示已经存入了33次脉宽
  65.                 {
  66.                         IRok = 1; //脉宽检查完成
  67.                         i = 0;          //把脉宽计数清零准备下次存入
  68.                 }
  69.         }
  70.         else
  71.         {
  72.                 IRtime = 0;          //定时器0计数清零
  73.                 startflag = 1;//开始处理标志位置1
  74.         }

  75.                                 
  76.                                 
  77.                                 
  78. }

  79. //把提取的33次脉宽进行解码 NEC协议
  80. void IRcordpro()
  81. {
  82.         uchar i;//i是用于计数处理4个字节
  83.         uchar j;//j用于计数处理1个字节的8位数据
  84.         uchar k;//k用于计数处理33次脉宽
  85.         k = 1;//从第一位脉宽开始处理,丢掉起始码
  86.         for(i = 0; i < 4; i++)
  87.         {
  88.                 for(j = 0; j < 8; j++)
  89.                 {
  90.                         //如果脉宽大于数据0标准的1125us那么就判定为数据1
  91.                         if(IRdata[k] > 5      
  92.                                                                                                 
  93.                                                                                                               ) IRcord[i] |= 0x80;//写1
  94.                         //只能右移7次,如果右移8次则会把第一位数据移出去
  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;        //定时计数器0, 工作方式1
  112.     TL0 = 0xF8;                //设置定时初值
  113.           TH0 = 0xE9;                //设置定时初值                //设置定时初值  255us
  114.           ET0=1;            //允许定时/计数器0 中断
  115.     TR0=1;            //启动定时/计数器0 中断
  116.         
  117.         
  118.      //上电,允许外部中断0
  119.       IT0 = 1;//设置外部中断0跳变沿触发方式
  120.       EX0 = 1;//开外部中断0中断
  121.         
  122.         
  123.     //上电,串口中断初始化
  124.     INIT_UART();        //串口中断初始化
  125.                
  126.            EA=1;                        //打开总中断
  127.         
  128.         /*===========================================================
  129.     ===========================================================*/        
  130.         while(1)
  131.         {
  132.                 uchar i; //计数串口发送字节数

  133.                
  134.                  if(IRok)//判断33次脉宽是否提取完成
  135.                 {
  136.                          IRcordpro();//根据脉宽解码出4个字节的数据
  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++) //串口发送4个字节数据

  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;   // 接收数量清零
  180.                                                                  
  181.          }

  182.                  }                 
  183.                                  
  184.                                  
  185.                                  

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


  189. /***********************************************************************/
  190. //======================================================================
  191. //        UART interrupt service routine
  192. //  数据格式: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数据
  201.                
  202.                 /* 串口1接收数据和判断数据结束 */
  203.                 if(JDE_RX==1)        //接收数据保存判断
  204.                 {
  205.                         IRtime=0;  //计时器清零
  206.                         
  207.                         if((DAT_RX==0xFA)&(CNT_RX==0))         //避免少发数据出错情况           每次接到FA 就会清空
  208.                         {
  209.                                                                                                                                                 
  210.                                 for(K=0;K<8;K++){RX_Data[K]=0;}        //串口接收的数据清0
  211.                   }
  212.                                                         
  213.                         RX_Data[CNT_RX]=DAT_RX;
  214.                         
  215.                         CNT_RX++;  //接收数量+1
  216.                         
  217.                         if(CNT_RX==5)  //接收5个字节
  218.                         {
  219.                                    
  220.                                 JDE_RX=2;                //串口接收数据判断变量置2 接收完毕
  221.                         }
  222.                         
  223.                         
  224.                         
  225.                 }
  226.                
  227.   }
  228.         //if(TI){ TI=0; }        //清除TI位
  229. }



  230. /***********************************************************************/
  231. //======================================================================
  232. //  子函数定义
  233. //======================================================================
  234. /***********************************************************************/
  235. //串口初始化子函数定义(定时器中断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));        //设置波特率重装值
  248.     T2H = (65536-(FOSC/4/BAUD))>>8;
  249.     AUXR |= 0x14;                                        //T2为1T模式, 并启动定时器2
  250.     AUXR |= 0x01;                       //选择定时器2为串口1的波特率发生器
  251.     ES = 1;                             //使能串口1中断
  252. }


  253. //串口发送数据子函数定义
  254. void SEND_UART(UCHAR DAT)
  255. {
  256.         SBUF=DAT;
  257.         while(!TI);        //等特数据传送
  258.         TI=0;                //清除数据传送标志
  259. }
复制代码





分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:689921 发表于 2020-2-4 13:55 来自手机 | 只看该作者
各连接处固定后上电  接触松动  造成局部电压不稳
回复

使用道具 举报

板凳
ID:689962 发表于 2020-2-4 15:41 | 只看该作者
我以前在学单片机,看着你的代码感觉我自己要加油呀
回复

使用道具 举报

地板
ID:325735 发表于 2020-2-4 18:10 | 只看该作者
电路没有虚连的情况,只要上电第一次解码  肯定是正常的,第2次开始 有一部分按键的数据或者数据反码 就会出现一位的错误
就是说解码部分运行一次就不正常了!~
回复

使用道具 举报

5#
ID:325735 发表于 2020-2-4 18:12 | 只看该作者
而且我试过解码成功发送完毕后,我从新执行一次上电初始化的内容也不管用
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表