OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 4181|回复: 3

c52做红外遥控小车,遥控出现了问题,求解决

[复制链接]

6

主题

14

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2016-5-24
在线时间
6 小时
发表于 2016-12-8 09:33:31 | 显示全部楼层 |阅读模式
1金钱
遥控时想实现连按重复上次操作(如连按小车前进,不按小车停止),但是现在只能实现按下走一定的延时时间后又停止再按才能走,必须要有一定频率的按键操作才能实现重复上次操作的功能,估计是重复码无法识别,求解决




#include <reg52.h>

#define u8  unsigned char
#define u16  unsigned int
sbit led=P0^0;

sbit IR_INPUT = P3^3; //红外接收引脚
bit irflag = 0; //红外接收标志,收到一帧正确数据后置 1
unsigned char ircode[4]; //红外代码接收缓冲区


unsigned char code LedChar[] = { //??????????
    0xC0, 0xF9, 0xA4, 0xB0, 0x99, 0x92, 0x82, 0xF8,
    0x80, 0x90, 0x88, 0x83, 0xC6, 0xA1, 0x86, 0x84
};
unsigned char LedBuff[4] = {
    0xC0, 0xC0, 0xC0, 0xC0
};

#define  u16  unsigned int
#define  u8   unsigned char

sbit IN1=P1^0;
sbit IN2=P1^1;
sbit IN3=P1^2;
sbit IN4=P1^3;



sbit key4 = P3^7;
sbit key3 = P3^6;
sbit key2 = P3^5;
sbit key1 = P3^4;

u8 pp;

char sum;


sbit L_PWM=P1^4;
sbit R_PWM=P1^5;


#define  L_go          IN1=1;IN2=0    //左轮进
#define  L_back        IN1=0;IN2=1    //左轮退
#define  L_stop        IN1=0;IN2=0    //左轮停

#define  R_go          IN3=1;IN4=0     //右轮进
#define  R_back        IN3=0;IN4=1     //右轮退
#define  R_stop        IN3=0;IN4=0     //右轮停止

#define  car_go        L_go;R_go       //车向前进
#define  car_back      L_back;R_back   //车倒退
#define  car_stop      L_stop;R_stop   //车停止
#define  car_lift      R_go;L_stop     //车左转
#define  car_right     L_go;R_stop     //车右转


#define  car_lift360   L_back;R_go     //可以理解为左大转弯
#define  car_right360  R_back;L_go     //可以理解为右大转弯




void delay(unsigned int t){               
        while(t--);
       
}

void delay_ms(u16 x)
{
        u8 i;
  while(x--)
  for(i=0;i<120;i++);
}



void T0_Init()
{
        TMOD&=0Xf0;
        TMOD|=0x01;
        TH0=0XFC;      //定时器0实现1ms产生一次中断,若是设置10格调速,则PWM的周期就是10ms
        TL0=0X07;
        ET0=1;
        TR0=1;
        EA=1;
       
}

void time0()interrupt 1
{
        TMOD&=0Xf0;
        TMOD|=0x01;
        TH0=0XFC;      //定时器0实现1ms产生一次中断,若是设置10格调速,则PWM的周期就是10ms
        TL0=0X07;
        pp++;
  if(pp>9) pp=0;
        if(sum!=0&&sum!=9)
        {
                if(pp<=sum)
        {        L_PWM=1;
                R_PWM=1;
  }
        else
                {
                        L_PWM=0;
                        R_PWM=0;
    }
        }
        else if(sum==0)
        {
                L_PWM=0;
                        R_PWM=0;
  }
        else if(sum==9)
        {
                L_PWM=1;
                R_PWM=1;
  }       
}




/* 初始化红外接收功能 */
void InitInfrared(){
    IR_INPUT = 1; //确保红外接收引脚被释放
    TMOD &= 0x0F; //清零 T1 的控制位
    TMOD |= 0x10; //配置 T1 为模式 1
    TR1 = 0; //停止 T1 计数
    ET1 = 0; //禁止 T1 中断
    IT1 = 1; //设置 INT1 为负边沿触发
    EX1 = 1; //使能 INT1 中断
}
/* 获取当前高电平的持续时间 */
unsigned int GetHighTime(){
    TH1 = 0; //清零 T1 计数初值
    TL1 = 0;
    TR1 = 1; //启动 T1 计数
    while (IR_INPUT){ //红外输入引脚为 1 时循环检测等待,变为 0 时则结束本循环
        //当 T1 计数值大于 0x4000,即高电平持续时间超过约 18ms 时,
        //强制退出循环,是为了避免信号异常时,程序假死在这里。
        if (TH1 >= 0x40){
            break;
        }
    }
    TR1 = 0; //停止 T1 计数
    return (TH1*256 + TL1); //T1 计数值合成为 16bit 整型数,并返回该数
}
/* 获取当前低电平的持续时间 */
unsigned int GetLowTime(){
    TH1 = 0; //清零 T1 计数初值
    TL1 = 0;
    TR1 = 1; //启动 T1 计数
    while (!IR_INPUT){ //红外输入引脚为 0 时循环检测等待,变为 1 时则结束本循环
        //当 T1 计数值大于 0x4000,即低电平持续时间超过约 18ms 时,
        //强制退出循环,是为了避免信号异常时,程序假死在这里。
        if (TH1 >= 0x40){
            break;
        }
    }
    TR1 = 0; //停止 T1 计数
    return (TH1*256 + TL1); //T1 计数值合成为 16bit 整型数,并返回该数
}
/* INT1 中断服务函数,执行红外接收及解码 */
void EXINT1_ISR() interrupt 2{
    unsigned char i, j;
    unsigned char byt;
    unsigned int time;
   
    //接收并判定引导码的 9ms 低电平
    time = GetLowTime();
    //时间判定范围为 8.5~9.5ms,
    //超过此范围则说明为误码,直接退出
    if ((time<7833) || (time>8755)){
        IE1 = 0; //退出前清零 INT1 中断标志
        return;
    }
    //接收并判定引导码的 4.5ms 高电平
    time = GetHighTime();
    //时间判定范围为 4.0~5.0ms,
    //超过此范围则说明为误码,直接退出
    if ((time<3686) || (time>4608)){
        IE1 = 0;
        return;
    }
                        else if((time>1612)&&(time<2534))
                {irflag = 1;
                        IE1 = 0;
    return;
    }
    //接收并判定后续的 4 字节数据
    for (i=0; i<4; i++){ //循环接收 4 个字节
        for (j=0; j<8; j++){ //循环接收判定每字节的 8 个 bit
            //接收判定每 bit 的 560us 低电平
            time = GetLowTime();
            //时间判定范围为 340~780us,
            //超过此范围则说明为误码,直接退出
            if ((time<313) || (time>718)){
                IE1 = 0;
                return;
            }
            //接收每 bit 高电平时间,判定该 bit 的值
            time = GetHighTime();
            //时间判定范围为 340~780us,
            //在此范围内说明该 bit 值为 0
            if ((time>313) && (time<718)){
                byt >>= 1; //因低位在先,所以数据右移,高位为 0
                //时间判定范围为 1460~1900us,
                //在此范围内说明该 bit 值为 1
            }else if ((time>1345) && (time<1751)){
                byt >>= 1; //因低位在先,所以数据右移,
                byt |= 0x80; //高位置 1
            }else{ //不在上述范围内则说明为误码,直接退出
                IE1 = 0;
                return;
            }
        }
        ircode[i] = byt; //接收完一个字节后保存到缓冲区

    }
    irflag = 1; //接收完毕后设置标志
    IE1 = 0; //退出前清零 INT1 中断标志
               
        }
               
void Date_kandle()
                {
                        if (irflag){ //接收到红外数据时刷新显示
            irflag = 0;
            LedBuff[0] = LedChar[ircode[0] >> 4]; //用户码显示
            LedBuff[1] = LedChar[ircode[0]&0x0F];
            LedBuff[2] = LedChar[ircode[2] >> 4]; //键码显示
            LedBuff[3] = LedChar[ircode[2]&0x0F];
       
                }
        }
       
                void main(){
                       
                        u8 i,tmp;
    EA = 1; //开总中断
   // T0_Init();
    InitInfrared(); //初始化红外功能                       
        //PT1=1;
   
                        while (1)
                        {
                               
                               
                                if(irflag)
                                {
                                        irflag = 0;
                                        tmp=ircode[2];
                                        switch(tmp)//led=~led;break;
                                        {
                                                case 0x40: car_go;break;
                                                case 0x19: car_back;break;
                                                case 0x07: car_lift;break;
                                                case 0x09: car_right;break;
                                                default: break;
          }
       
delay_ms(1000);
        }else car_go;
       
                        /*                                Date_kandle();
                                                for(i=0;i<4;i++)
        {
                P2=0X01<<i;   
               
                P1=LedBuff[i];
               
                delay_ms(5);
        
    }*/
}       
}

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

6

主题

14

帖子

0

精华

新手上路

积分
39
金钱
39
注册时间
2016-5-24
在线时间
6 小时
 楼主| 发表于 2016-12-8 16:53:17 | 显示全部楼层
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165369
金钱
165369
注册时间
2010-12-1
在线时间
2110 小时
发表于 2016-12-8 21:10:04 | 显示全部楼层
帮顶
回复

使用道具 举报

34

主题

805

帖子

4

精华

论坛大神

Rank: 7Rank: 7Rank: 7

积分
1863
金钱
1863
注册时间
2011-3-29
在线时间
139 小时
发表于 2016-12-8 22:31:23 | 显示全部楼层
光看代码都搞不懂你的小车是怎么走一段时间后停下来的,因为都没有调用car_stop。
而且你的宏用法有严重的问题。比如:
if(){...}else car_go;
展开来就是:
if(){...}else  L_go;R_go;
显然楼主要的不是这种代码吧?!!
业余程序玩家。
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-2-1 16:41

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

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