找回密码
 立即注册

QQ登录

只需一步,快速开始

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

单片机+红外解码失败哪位大神帮看一下

[复制链接]
跳转到指定楼层
楼主
ID:607737 发表于 2019-9-5 09:07 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
做的红外遥控智能小车,keil上程序没错,但运行到单片机上就是解码不出来,小车电路也没错啊,哪位大神帮看一下是不是红外解码过程中程序有问题。非常感谢!

单片机源程序如下:
  1. /*NEC协议红外通信*/
  2. #include <reg52.h>

  3. /*自定义类型名*/
  4. #define uchar unsigned char
  5. #define uint  unsigned int
  6. sbit IN1=P1^3;sbit IN2=P1^4;sbit IN3=P1^5;sbit IN4=P1^6;  //马达管脚     
  7. #define left_motor_stop    {IN1=0;IN2=0;}    //左电机停转
  8. #define left_motor_go      {IN1=1;IN2=0;}    //左电机正转
  9. #define left_motor_back    {IN1=0;IN2=1;}          //左电机反转
  10. #define right_motor_stop   {IN3=0;IN4=0;}         //右电机停转                     
  11. #define right_motor_go     {IN3=1;IN4=0;}         //右电机正转
  12. #define right_motor_back   {IN3=0;IN4=1;}         //右电机反转

  13. /*====================================
  14. 硬件接口位声明
  15. ====================================*/
  16. sbit IR = P3^2;     //定义红外脉冲数据接口        外部中断O输入口

  17. uchar IRtime;                 //检测红外高电平持续时间(脉宽)
  18. uchar IRcord[4];    //此数组用于储存分离出来的4个字节的数据(用户码2个字节+键值码2个字节)
  19. uchar IRdata[33];   //此数组用于储存红外的33位数据(第一位为引导码用户码16+键值码16)
  20. bit IRpro_ok, IRok;  //第一个用于红外接收4个字节完毕。IRok用为检测脉宽完毕

  21. void init()           //初始化定时器0 和外部中断0
  22. {
  23.         TMOD = 0x02; //定时器0工作方式2,8位自动重装
  24.         TH0 = 0x00;  //高8位装入0那么定时器溢出一次的时间是256个机器周期
  25.         TL0 = 0x00;
  26.         EA = 1;      //总中断
  27.         ET0 = 1;           //定时器0中断
  28.         TR0 = 1;     //启动定时器0

  29.         IT0 = 1;           //设置外部中断0为跳沿触发方式,来一个下降沿触发一次
  30.         EX0 = 1;           //启动外部中断0
  31. }

  32. void time0() interrupt 1   //定义定时器0
  33. {
  34.         IRtime++;                            //检测脉宽,1次为278us
  35. }

  36. void int0() interrupt 0                          //定义外部中断0
  37. {
  38.         static uchar a;                                 //        声明静态变量(在跳出函数后在回来执行的时候不会丢失数值)i用于把33次高电平的持续时间存入IRdata
  39.         static bit startflag;                //开始储存脉宽标志位
  40.         if(startflag)                                 //开始接收脉宽检测
  41.         {
  42.                 if( (IRtime < 53) && (IRtime >= 32) ) /*判断是否是引导码,底电平9000us+高4500us       
  43.                
  44.                 这个自己可以算我以11.0592来算了NEC协议的引导码低8000-10000+高4000-5000
  45.                 如果已经接收了引导码那么i不会被置0就会开始依次存入脉宽*/
  46.                         a = 0;                                 //如果是引导码那么执行i=0把他存到IRdata的第一个位
  47.                         IRdata[a] = IRtime;                   //以T0的溢出次数来计算脉宽,把这个时间存到数组里面到后面判断
  48.                         IRtime = 0;                                 //计数清零,下一个下降沿的时候在存入脉宽
  49.                         a++;                                          //计数脉宽存入的次数
  50.                         if(a == 33)                                  //如果存入34次 数组的下标是从0开始i等于33表示执行了34次
  51.                         {
  52.                                  IRok = 1;                                 //那么表示脉宽检测完毕
  53.                                 a = 0;                                  //把脉宽计数清零准备下次存入
  54.                         }
  55.                
  56.         }
  57.         else                  
  58.         {
  59.                 IRtime = 0;                                  //引导码开始进入把脉宽计数清零开始计数
  60.                 startflag = 1;                         //开始处理标志位置1
  61.         }
  62. }

  63. void IRcordpro()                                    //提取它的33次脉宽进行数据解码
  64. {
  65.         uchar i, j, k;        /*i用于处理4个字节,j用于处理一个字节中每一位,k用于33次脉宽中的哪一位
  66.         cord用于取出脉宽的时间判断是否符合1的脉宽时间*/
  67.         k = 1;                                                 //从第一位脉宽开始取,丢弃引导码脉宽
  68.         for(i = 0; i < 4; i++)
  69.         {
  70.                 for(j = 0; j < 8; j++)
  71.                 {
  72.                             //把脉宽存入cord
  73.                         if(IRdata[k] > 5)                         //如果脉宽大于我11.0592的t0溢出率为约278us*5=1390那么判断为1
  74.                         IRcord[i] |= 0x80;        /*接收的时候是先接收最低位,
  75.                         把最低位先放到value的最高位在和0x08按位或一下
  76.                         这样不会改变valua的其他位的数值只会让他最高位为1*/
  77.                         if(j < 7)   IRcord[i] >>= 1;        //value位左移依次接收8位数据。
  78.                         k++;
  79.                        
  80.                                                 //每执行一次脉宽位加1
  81.                 }
  82.         //        IRcord[i] = value;           //每处理完一个字节把它放入IRcord数组中。
  83.         //        value = 0;                            //清零value方便下次在存入数据
  84.         }
  85.         IRpro_ok = 1;                                   //接收完4个字节后IRpro ok置1表示红外解码完成       
  86. }
  87. void forward()
  88. {
  89.         left_motor_go;
  90.         right_motor_go;
  91.         P2=0x7f;      //led_forward=P2^7,前进显示灯
  92. }
  93. void backward()
  94. {
  95.         left_motor_back;
  96.         right_motor_back;
  97.         P2=0xdf;          //led_backward=P2^5
  98. }
  99. void right_run()
  100. {
  101.         left_motor_go;
  102.         right_motor_stop;
  103.         P2=0xef;          //led_right_run=P2^4

  104. }
  105. void left_run()
  106. {
  107.         left_motor_stop;
  108.         right_motor_go;
  109.         P2=0xbf;           //led_left_run=P2^6
  110. }
  111. void stop()
  112. {
  113.         left_motor_stop;
  114.         right_motor_stop;
  115.         P2=0xff;       
  116. }
  117. void main()
  118. {
  119.         init();        //执行初始化定时器0和外部中断0
  120.         while(1)        //大循环
  121.         {
  122.                 if(IRok)    //判断脉宽是否检测完毕                    
  123.                 {   
  124.                         IRcordpro();//根据脉宽解码出4个字节的数据
  125.                         IRok = 0;        //重新等待脉宽检测
  126.                         if(IRpro_ok) //判断是否解码完毕  
  127.                         {
  128.                                 switch(IRcord[2])
  129.                                 {
  130.                                         case 0x18:forward();
  131.                                         break;
  132.                                         case 0x10:left_run();
  133.                                         break;
  134.                                         case 0x38:stop();
  135.                                         break;
  136.                                         case 0x42:right_run();
  137.                                         break;
  138.                                         case 0x4A:backward();
  139.                                         break;
  140.                                 }
  141.                                 IRpro_ok = 0;
  142.                         }
  143.                 }       
  144.         }
  145. }
复制代码


文字文稿1(1).docx

14.32 KB, 下载次数: 5

代码

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

使用道具 举报

沙发
ID:277550 发表于 2019-9-5 19:52 | 只看该作者

之前使用中断+查询的方式来解码,还可以。。。。。直接解出来4字节、或更多字节的红外数据

回复

使用道具 举报

板凳
ID:425825 发表于 2019-9-6 09:32 | 只看该作者
你好!
分开调试看看吧
1、先把红外解码实现
2、加入电机控制
3、可以加我好友
回复

使用道具 举报

地板
ID:607737 发表于 2019-9-11 00:05 来自手机 | 只看该作者
来51学习 发表于 2019-9-6 09:32
你好!
分开调试看看吧
1、先把红外解码实现

不知是代码问题还是硬件问题,解码不出来
回复

使用道具 举报

5#
ID:219172 发表于 2019-9-11 09:06 | 只看该作者
我建议你做一个检测仪,这个比较简单,利用电脑的音频信号接口,然后将红外接收器与其连接,打开录音软件cool edit pro来分析接收的数据,然后根据波形来解码就可以了。你可以搜索一下。
回复

使用道具 举报

6#
ID:219172 发表于 2019-9-11 09:07 | 只看该作者
你可以在解码的过程上面,用串口将数据打印出来,这样就可以知道,解码有没有成功,在那个步骤出错了。
回复

使用道具 举报

7#
ID:282850 发表于 2019-9-11 09:30 | 只看该作者
即然程序没错,电路也没错,那就是正确的。即然不正确解码,说明还是有错。逻辑不通,仔细木检查。另外建议用硬件中断+口线接收红外,我是这样搞的。程序在家。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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