智能车制作

 找回密码
 注册

扫一扫,访问微社区

查看: 2952|回复: 4
打印 上一主题 下一主题

[单片机] 你们好,红外遥控车想实现有按才跑没按不跑,现在的情况是一按就一直跑,不会停,求解

[复制链接]

2

主题

5

帖子

0

精华

注册会员

Rank: 2

积分
81
威望
50
贡献
27
兑换币
27
注册时间
2013-10-19
在线时间
2 小时
跳转到指定楼层
1#
发表于 2014-3-30 18:50:04 | 只看该作者 回帖奖励 |正序浏览 |阅读模式
#include <pic.h>           //调用PIC16F87XA单片机的头文件
__CONFIG(XT&WDTDIS&LVPDIS);
#define uchar unsigned char
#define uint unsigned int
//const uchar dx[16]={0x3f,0x06,0x5b,0x4f,0x66,0x6d,0x7d,0x07,0x7f,0x6f,0x77,0x7c,0x39,0x5e,0x79,0x71}; //0-f段选显示码
//uchar sz[]={0x01,0X02,0X04,0X08,0X10,0X20,0X40,0X80};
uchar i;
void delay_ms(uint xms)
{
        int i,j;
        for(i=0;i<xms;i++)
        {for(j=0;j<71;j++);}
}
//---------------------------------------
//红外解码寄存器设置
unsigned char tmr_times;
unsigned char code_data;
unsigned char code;
unsigned char int_times;
unsigned char buf1;
bit head_ok;         
bit code_ok;
//---------------------------------------
//名称:解码错误处理函数
//---------------------------------------
void wrong(void)  //如果有错误,将相应寄存器清零,准备下一次接收
{
          int_times=0;
          tmr_times=0;
          head_ok=0;
          code_data=0;         
          code_ok=0;
          code=0;
}

//---------------------------------------   
void init()
{       
         ADCON1=0X06;
           TRISA=0;   
     TRISB=0;
     TRISC=0X04;   
     TRISE=0;
     PORTA=0;
     PORTB=0;
     PORTE=0;
     RA1=1;
     RBIE=0;
}  
void TMR0init()
{       
     OPTION=0X80;           
     TMR0IF=0;   
     TMR0IE=1;
     TMR0=131;        
     GIE=1;
     PEIE=1;
}
void ccp1init()
{

CCP1CON=0x04;                        //每个脉冲上降沿捕捉
T1CON=0x01;
TRISC2=1;               //RC2设置为输入状态
CCP1IF=0;
CCP1IE=1;                                //该捕捉允许中断
}

//名称:0或1判断函数
unsigned char one_zero(void)
{         
        //参看遥控器芯片HT6221的说明书,0编码的脉冲周期为1.12ms
        //本例中,时间中断为0.25ms,所以我们判定取大于0.75ms小于1.5ms的脉冲均为0编码
          if((tmr_times>2)&(tmr_times<7))
          {
            return 0;
          }
        //参看遥控器芯片HT6221的说明书,1编码的脉冲周期为2.24ms
        //本例中,时间中断为0.25ms,所以我们判定取大于1.75ms小于2.75ms的脉冲均为1编码
          else if((tmr_times>7)&(tmr_times<13))
          {
            return 1;
          }
          else
          {
                  return 2;
          }
        //如果脉冲周期不在0.75-1.5ms或者1.75-2.75ms区间的,我们认为是错码,返回2

}

//---------------------------------------
//名称:中断服务程序
//---------------------------------------
void interrupt ISR(void)   //PIC单片机的所有中断都是这一个入口
{
    if(T0IF==1)          //需要进一步判断是否是T0中断
    {
            T0IF=0;    //清中断标志位,以备下次中断
        TMR0=131;         //定时器中断后,要重置初值,以备下次中断                   
    //***此处用户自行添加定时器T0中断处理程序***
                tmr_times++;       //每250us计数一次
    //******************************************
    }
        if(CCP1IF==1)            //需要进一步判断是否是CCP1中断
    {
       CCP1IF=0;            //清中断标志位,以备下次中断     
                GIE=0;                                  //全局中断关掉,以避免解码过程进入其他中断         
                  int_times++;                   //捕捉中断计次       
                  if(head_ok==0)              //如果还没接收到头码,那么先判断脉冲编码是否为头码
                  {
                    //参看遥控器芯片HT6221的说明书,发射代码的头码由一个9ms的起始码和一个4.5ms的结果码组成
                        //本例中,时间中断为0.25ms,所以我们判定大于12.5ms小于14.5ms的脉冲均为13.5ms的头码编码
                    if(tmr_times>0x31&tmr_times<0x37)               
                    {
                              head_ok=1;          //有效头码标志位置一,以示头码接收完成
                              int_times=0;    //外部中断计次寄存器清零,以准备接收后面的4组共32个脉冲
                              tmr_times=0;    //定时器中断计次寄存器清零,准备开始对后面的脉冲计时
                              TMR0=131;               
                    }
                    else
                    {
                              wrong();        //如果不是有效的头码,转入错误处理程序
                    }
                  }
                  else                        //如果已经接收到头码,那么开始对后面的32个脉冲进行解码                    
                  {    TMR0=131;
                    code_data=code_data>>1; //将接收缓冲区右移一位,以准备接收下一位
                        buf1=one_zero();                    //判断编码是0或1,或者是错码
                        tmr_times=0;                      //时间中断计次寄存器清零                       
                    if(buf1==1)                        //如果是编码1
                    {
                              code_data|=0x80;          //将1移入code_data的最高位
                    }           
                        else if(buf1==0)                        //如果是编码0
                {
                              code_data&=0x7f;          //将0移入code_data的最高位
                    }   
                        else                            //编码非0非1,即为错码,
            {
                                wrong();                       //调用错误处理程序
                                return;
                        }                                                   
                    if(int_times==8)        //如果收到了8个编码脉冲,意味着低8位地址码已经接收完
                    {
                                //本遥控器的低8位地址码为0X00,这个是遥控器厂家决定的,如果要订做,可以随便改
                        if(code_data!=0x00)  //如果不是0x00 ,说明不是我们提供的遥控器,我们不予识别
                        {
                                wrong();         //调用错误处理程序      
                                        return;  
                        }                      
                    }
                    else if(int_times==16)        //如果收到了16个编码脉冲,意味着高8位地址码已经接收完
                    {
                                //本遥控器的低高8位地址码为0XFF
                        if(code_data!=0xFF)  //如果不是0xff ,说明不是我们提供的遥控器,我们不予识别
                        {
                            wrong();         //调用错误处理程序      
                                        return;
                        }                                       
                    }
                    else if(int_times==24)    //收到的第三组8位字节即为8位数据码
                    {
                              code=code_data;    //将这个8位数据码暂存至code_data1                         
                    }
                    else if(int_times==32)    //收到的第四组8位字节即为8位数据码的反码
                    {
                              int_times=0;                //清零中断次数寄存器,以便下次从头开始               
                              head_ok=0;            //将头码标志位清零,以便下次再接收时,从头码开始                                                   
                              if((code+code_data)==0xff)    //判断第三组数据和第四组数据是否互为反码                         
                              {                                 
                            code_ok=1;                      //如果互为反码,说明接收来的编码为正确,置位标志位,以通知液晶显示       
                    }                             
                    }
                  }
                         
          }  
                  GIE=1;           //开放全局中断          
}


//电机状态函数
void zheng_a() //电机A正转
{
        RB2=1; //电机A控制口ENA
        RB3=1; //电机A输入口IN1
        RB4=0; //电机A输入口IN2
}

void fan_a() //电机A反转
{
        RB2=1; //电机A控制口ENA
        RB3=0; //电机A输入口IN1
        RB4=1; //电机A输入口IN2
}

void ting_a() //电机A停
{
        RB2=1; //电机A控制口ENA
        RB3=0; //电机A输入口IN1
        RB4=0; //电机A输入口IN2
}

void zheng_b() //电机B正转
{
        RB5=1;//电机B控制口ENB
        RB6=1; //电机B输入口IN3
        RB7=0; //电机B输入口IN4
}

void fan_b() //电机B反转
{
        RB5=1;//电机B控制口ENB
        RB6=0; //电机B输入口IN3
        RB7=1; //电机B输入口IN4
}

void ting_b() //电机B停
{
        RB5=1;//电机B控制口ENB
        RB6=0; //电机输入口IN3
        RB7=0; //电机B输入口IN4
}

//---------------------------------------
//名称: 主函数
//---------------------------------------
void main(void)            //主函数,单片机开机后就是从这个函数开始运行
{
     init();
     TMR0init();
     ccp1init();
    while(1)                   //死循环,单片机初始化后,将一直运行这个死循环
    {

                if(code_ok==1)         //如果接收到了有效地的遥控器按键码
            {
                code_ok=0;     //清掉该标志位
                    if(code==0x18)     //按键2全速前进
                    {
                              
                               zheng_a();
                        zheng_b();
                        //wrong();
                        delay_ms(300);
                        if(code==0x18)
                        {
                               zheng_a();
                               zheng_b();
                        }
                        else
                        {
                                ting_a();
                                ting_b();
                        }
                    }
               if(code==0x52)     //按键8全速后退
                    {
                      
                              fan_a();
                       fan_b();
                        //wrong();
                       delay_ms(300);
                       if(code==0x52)
                       {
                               fan_a();
                           fan_b();  
                       }
                       else
                       {
                               ting_a();
                               ting_b();
                       }
                    }
               }           
        }        
}

回复

使用道具 举报

11

主题

102

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
1141
威望
552
贡献
353
兑换币
350
注册时间
2014-8-31
在线时间
118 小时
5#
发表于 2014-9-30 14:26:49 | 只看该作者
写程序的时候将while(1)给去掉就行了
回复 支持 反对

使用道具 举报

0

主题

2

帖子

0

精华

注册会员

Rank: 2

积分
66
威望
46
贡献
14
兑换币
18
注册时间
2014-7-15
在线时间
4 小时
4#
发表于 2014-8-13 16:00:21 | 只看该作者
本帖最后由 Daud 于 2014-8-13 16:02 编辑

我也是同样的问题
而且红外接收一次接受33个字,想要摁一下跑一下只能用定时器延时:(
回复 支持 反对

使用道具 举报

2

主题

5

帖子

0

精华

注册会员

Rank: 2

积分
81
威望
50
贡献
27
兑换币
27
注册时间
2013-10-19
在线时间
2 小时
3#
 楼主| 发表于 2014-3-30 22:44:28 | 只看该作者
接收器用三个管脚的vs1838b,应该没锁存的,估计是程序问题

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x
回复 支持 反对

使用道具 举报

56

主题

4914

帖子

3

精华

顶级版主

北京科技大学智能汽车队公共主页管理员

Rank: 11Rank: 11Rank: 11Rank: 11

积分
56131

特殊贡献奖章资源大师奖章论坛骨干奖章推广达人奖章优秀版主奖章热心会员奖章论坛元老奖章在线王奖章活跃会员奖章优秀会员奖章

威望
19568
贡献
13933
兑换币
3365
注册时间
2010-7-22
在线时间
11315 小时
2#
发表于 2014-3-30 18:58:16 | 只看该作者
你的接收器是不是带锁存的
回复 支持 反对

使用道具 举报

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

本版积分规则

关于我们|联系我们|小黑屋|智能车制作 ( 黑ICP备2022002344号

GMT+8, 2024-12-28 05:03 , Processed in 0.051595 second(s), 38 queries , Gzip On.

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

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