基于51单片机的小车五路寻迹程序与PWM驱动(有详细注释),下载可直接使用

/*小车采用五组红外寻迹对管,排成一排装在小车前面,经测量黑线轨道约1.7cm,两个相邻红外对管间隔设置为1.5cm左右(有效寻迹),根据轨道大致设定小车各个状态的速度占空比(需要自己慢慢调整)。

本小车使用L298N模块,带有两路驱动,

 

 

*/

# include

typedef unsigned int uint;      //对数据类型进行声明定义
typedef unsigned char uchar;
uchar Duty_left,Duty_right,j=0,i=0;//左右占空比标志,取1-100
uchar daihao;
 

//电机驱动IO口,ENA,ENB为使能端,1,2控制左边电机,3,4控制右边电机,自己查L298n驱动表
sbit IN1=P2^0;
sbit IN2=P2^1;
sbit IN3=P2^2;
sbit IN4=P2^3;
sbit ENA=P1^0;
sbit ENB=P1^1;
//寻迹口,五组红外对管,从左往右,12345
sbit left1=P1^6;
sbit left2=P1^5;
sbit mid3=P1^4;
sbit right4=P1^3;
sbit right5=P1^2;

//void delay(uint k)//k=1时,大约延时10us
//{
//    while(k--);
//}
/*定时器0初始化,通过定时器中断设置PWM调速,可以节省cpu,(当时间未到0.1ms时,cpu执行其他命令,等时间到了,在停止执行中断里命令)

*/
void time0init()
{

    
    TMOD|=0x01;//定时器T0,,工作方式都为方式1
    TH0=0xff;//定时ff9c0.1ms    fe0c0.5ms
    TL0=0x9c;
    
    EA=1;  //开启总中断
    ET0=1;//开启中断允许
    TR0=1;//开启定时器中断
    
}


//向左矫正(用于left2检测到黑线)
void correct_left()
{
    IN1=1;//电机控制小车前行
    IN2=0;
    IN3=1;
    IN4=0;
    Duty_left=11;
    Duty_right=20;
    
}
//向右校正(用于right4检测到黑线)
void correct_right()
{
    IN1=1;//电机控制小车前行
    IN2=0;
    IN3=1;
    IN4=0;
    Duty_left=20;
    Duty_right=11;

}

//小车左转赋值(用于left1检测到黑线)
void Left_turning()
{
    Duty_left=18;
    Duty_right=20;
    IN1=0;        //转弯时一个正转一个反转
    IN2=1;
    IN3=1;
    IN4=0;
}
//小车右转赋值(用于right5检测到黑线)
void Right_turning()
{
    Duty_left=18;
    Duty_right=20;
    IN1=1;
    IN2=0;
    IN3=0;
    IN4=1;
}
//小车直走前行,不拐弯速度赋值
void forward_move()
{
    Duty_left=15;
    Duty_right=17;
    
    IN1=1;
    IN2=0;
    IN3=1;
    IN4=0;
}
//红外寻迹检测,走直线时小车最多两个相邻红外对管能同时检测到黑线(10011和11001和00111和11100)
void detect_infrared() //reentrant//函数名后加reentrant可以递归调用
{
    uchar qq=0,ww=0;
    if((right5==1)&&(right4==1)&&(mid3==0)&&(left2==1)&&(left1==1))//11011
        daihao=8;
    else if((left1==1)&&(left2==1)&&(mid3==1)&&(right4==0)&&(right5==1))//11101
    daihao=7;
    else if((left1==1)&&(left2==0)&&(mid3==1)&&(right4==1)&&(right5==1))//10111
    daihao=6;
    else if((left1==0)&&(left2==1)&&(mid3==1)&&(right4==1)&&(right5==1))//01111
    daihao=5;
    else if((left1==1)&&(left2==1)&&(mid3==1)&&(right4==1)&&(right5==0))//11110
    daihao=4;
    else if((left1==1)&&(left2==0)&&(mid3==0)&&(right4==1)&&(right5==1))//10011
    daihao=3;
    else if((left1==1)&&(left2==1)&&(mid3==0)&&(right4==0)&&(right5==1))//11001
    daihao=2;
    else if((right5==1)&&(right4==1)&&(mid3==0)&&(left2==0)&&(left1==0))//00011直角弯左转
    daihao=1;    
else if((right5==0)&&(right4==0)&&(mid3==0)&&(left2==1)&&(left1==1))//11000直角弯右转 
    daihao=0;

    
    switch(daihao)
    {
        case 0:    Right_turning();break;//11000       
        case 1:    Left_turning();break;//00011       
        case 2:    correct_right();break;//11001
        case 3:    correct_left();break;//10011
        case 4:    Right_turning();break;//11110
        case 5:    Left_turning();break;//01111
        case 6:    correct_left();break;//10111
        case 7:    correct_right();break;//11101
        case 8:    forward_move();break;//11011
    }
      
}


void main()
{
    time0init();
    while(1)
    {
    detect_infrared();
        /*
        数码管显示程序编写
        */
    }
}

/*

定时器中断里设置PWM,假如10ms里分为100个0.1ms,让小车加速20个(即ENA=1),剩下的80个不动(即ENB=0),那小车就会在20个加速后,因为惯性还会再转,直到停止。因为总周期10ms,非常短,所以我们会看到电机一直在转,这就是PWM调速原理,如果让其加速50个,剩下50个不动,那么小车速度就会更快,所以调节占空比(高电平占总周期比例)即可控制速度大小。

*/
void time0() interrupt 1
{
    TH0=0xff;
    TL0=0x9c;
    i++;
    j++;
//    q++;
    if(i<=Duty_left)//设置左轮占空比,即左轮速度,
        ENA=1;
    else
        ENA=0;
    
    if(j<=Duty_right)
        ENB=1;
    else
        ENB=0;
    
    if(i==100)        //设置pwm周期=0.1ms*100=10ms,这样开头定义的变量正好表示占空比数值
    {
        i=0;//加到100后变为0,重新计数
    }
    if(j==100)        //设置pwm周期=0.1ms*100=10ms,这样开头定义的变量正好表示占空比数值
    {
        j=0;
    }

   
}

 

/*寻迹程序其实主要找全各种情况,在加以调整速度,基本能实现寻迹。

若还有不懂,可留言

2018年9月23日

你可能感兴趣的:(基于51单片机的小车五路寻迹程序与PWM驱动(有详细注释),下载可直接使用)