基于STC89C52RC单片机的红外遥控小车,c程序+硬件。

											  /*小车用遥控器控制程序 (有差速)
 L298N的IN1234对应单片机的P1.0123
*/
#include      //包含头文件,一般情况不需要改动,头文件包含特殊功能寄存器的定义h
#define DataPort P0    //定义数据端口 程序中遇到DataPort 则用P0 替换
sbit IR=P3^2;          //红外接口标志 ,ir是红外辐射 的意思
sbit dula=P2^6;        //定义锁存使能端口 段锁存
sbit wela=P2^7;        //                 位锁存

sbit in1=P1^0;
sbit in2=P1^1;
sbit in3=P1^2;
sbit in4=P1^3;

int PWM,time=0,go;

unsigned char code DuanMa[14]={0x3f,0x06,0x5b,0x4f,0x40,0x38,0x31};// 显示段码值0~9
unsigned char  irtime,gao_num,di_num,l,r,back,stop;//红外、PWM用全局变量

bit irpro_ok,irok;      //标志位,处理完成irpro_ok=1,接收完成irok=1
unsigned char IRcord[4];  //红外码值有4个(客户码1+客2+操作码+操作反码),4*8=32位
unsigned char irdata[33]; //32位红外码值+1位引导码,也就是接受一次需要存储的字节数

void Ir_work(void);       //红外散转函数声明
void Ircordpro(void);     //红外码值处理函数声明

void delay(int i)       //延时i ms
{
  int j,k;
  for(j=i;j>0;j--)
    for(k=110;k>0;k--);
}  


void tim0_isr (void) interrupt 1 using 1
{
  irtime++;  //用于计数2个下降沿之间的时间
}


/*------------------------------------------------
                  外部中断0中断处理
------------------------------------------------*/
void EX0_ISR (void) interrupt 0         //外部中断0服务函数
{
  static unsigned char  i;             //接收红外信号处理
  static bit startflag;                //是否开始处理标志位

if(startflag)
   {
    if(irtime<63&&irtime>=33)//引导码 TC9012的头码,9ms+4.5ms
                        i=0;
            irdata[i]=irtime;//存储每个电平的持续时间,用于以后判断是0还是1
            irtime=0;
            i++;
             if(i==33)
                {
                 irok=1;
                 i=0;
                }
          }
     else
        {
        irtime=0;
        startflag=1;
        }

}


/*------------------------------------------------
                定时器初始化
------------------------------------------------*/
void TIM0init(void)//定时器0初始化
{

  TMOD=0x12;//定时器0工作方式2,TH0是重装值,TL0是初值
  TH0=0x00; //重载值
  TL0=0x00; //初始化值
  ET0=1;    //开中断
  TR0=1;    //启动定时器0

    TH1=0xff;
    TL1=0x67;
    ET1=1;
    TR1=1;
}


/*------------------------------------------------
                  外部中断0初始化
------------------------------------------------*/
void EX0init(void)
{
 IT0 = 1;   //指定外部中断0下降沿触发,INT0 (P3.2)
 EX0 = 1;   //使能外部中断
 EA = 1;    //开总中断
}


/*------------------------------------------------
                红外码值处理
------------------------------------------------*/
void Ircordpro(void)//红外码值处理函数
{ 
  unsigned char i, j, k;
  unsigned char cord,value;

  k=1;
  for(i=0;i<4;i++)      //处理4个字节
     {
      for(j=1;j<=8;j++) //处理1个字节8位
         {
          cord=irdata[k];
          if(cord>7)//大于某值为1,这个和晶振有绝对关系,这里使用12M计算,此值可以有一定误差
             value|=0x80;
          if(j<8)
            {
             value>>=1;
            }
           k++;
         }
     IRcord[i]=value;
     value=0;     
     } 
     irpro_ok=1;//处理完毕标志位置1
}


/*------------------------------------------------
                  解码散转处理
------------------------------------------------*/

void Ir_work(void)//红外散转程序,解码后用以选择执行指令
{
       switch(IRcord[2])//判断第三个数码值
             {
             case 0x0c:DataPort=DuanMa[1];go=1;PWM=10;break;//1 速度,并显示相应的按键值    0x3f,0x06,0x5b,0x4f,0x40,0x38,0x31
             case 0x18:DataPort=DuanMa[2];go=2;PWM=30;break;//2
             case 0x5e:DataPort=DuanMa[3];go=3;PWM=50;break;//3

             case 0x1C:DataPort=DuanMa[0];go=5;PWM=0;break;//8 停车
        
             case 0x52:DataPort=DuanMa[4];go=8;PWM=20;break;//8 倒退

             case 0x08:DataPort=DuanMa[5];go=4;PWM=20;break;//转弯控制 左转
             case 0x5A:DataPort=DuanMa[6];go=6;PWM=20;break; //转弯控制 右转
             default:break;
             }                                          
             irpro_ok=0;//处理完成标志
}

/*------------------------------------------------
                    主函数
------------------------------------------------*/
void main(void)
{
    EX0init(); //初始化外部中断
    TIM0init();//初始化定时器

    DataPort=0xfe; //取位码 第一位数码管选通,即二进制1111 1110
    wela=1;      //位锁存
    wela=0;
    P1=0xff;
    while(1)//主循环
    {
        if(irok)                        //如果接收好了进行红外处理
        {   
            Ircordpro();                    //调用红外码值处理函数
            irok=0;                     //标志位置零
        }

        if(irpro_ok)                   //如果处理好后进行工作处理,如按对应的按键后显示对应的数字等
        {
            Ir_work();                 //调用红外散转处理函数
        }
    }
}


/*------------------------------------------------
                    PWM调速
------------------------------------------------*/
void timer1() interrupt 3 using 1
{
    TR1=0;//赋初值时,关闭定时器
    TH1=0xff;//(65536-10)/256;//赋初值定时
    TL1=0xf7;//(65536-10)%256;//0.01ms
    TR1=1;//打开定时器

    time++;
    switch(go)
    {
        case 5:
        if(PWM==0)
        {
            in1=1;in2=1;in3=1;in4=1;
        }
        break;
        /*前进 1档,2档,3档*/
        case 1:
        if(time>=100)  //1khz
        {
            time=0;
        }
        if(time<=PWM)  
        {
            in1=0;in2=1;in3=0;in4=1;
        } 
        else
        {
            in1=0;in2=0;in3=0;in4=0;    
        }
        break;      
        case 2:
        if(time>=100)  //1khz
        {
            time=0;
        }   
        if(time<=PWM)  
        {
            in1=0;in2=1;in3=0;in4=1;
        }
        else
        {
            in1=0;in2=0;in3=0;in4=0;    
        }
        break;
        case 3:
        if(time>=100)  //1khz
        {
            time=0;
        }   
        if(time<=PWM)  
        {
            in1=0;in2=1;in3=0;in4=1;
        } 
        else
        {
            in1=0;in2=0;in3=0;in4=0;    
        }
        break;
        case 4:
        if(time>=100)  //1khz
        {
            time=0;
        }
        if(time<=PWM)  
        {
            in1=0;in2=0;in3=0;in4=1;
            if(time<=PWM-15)
            {
                in1=0;in2=1;in3=0;in4=0;    
            }
        } 

        else
        {
            in1=0;in2=0;in3=0;in4=0;    
        }
        break;
        case 6:
        if(time>=100)  //1khz
        {
            time=0;
        }
        if(time<=PWM)  
        {
            in1=0;in2=1;in3=0;in4=0;
            if(time<=PWM-15)
            {
                in1=0;in2=0;in3=0;in4=1;
            }
        } 
        else
        {
            in1=0;in2=0;in3=0;in4=0;    
        }
        break;
        case 8:
        if(time>=100)  //1khz
        {
            time=0;
        }   
        if(time<=PWM)
        {
            in1=1;in2=0;in3=1;in4=0;
        } 
        else
        {
            in1=0;in2=0;in3=0;in4=0;
        }
        break;
        default:break;   
    }
}

你可能感兴趣的:(基于STC89C52RC单片机的红外遥控小车,c程序+硬件。)