智能电动小车

/**********************************************
工程名:可自动循迹、避障、精确定位的智能电动小车
说  明:本设计是基于89C52MCU的智能电动小车,系统
        启动后需要设定当前时间,紧接着选择系统模
        式-循迹、避障、定位。
        循迹模式主要利用红外反射管实现,发射管不
        断发出红外,若地面为黑线则接收管接收不到
        信号,输出高电平,当小车不在线上后接收管
        收到反射光,输出低电平,小车前头及左右各
        装一对,当左侧输出低电平时小车右转一定角
        度,当右侧输出高电平时小车左转一定角度。
        如此循环判断可实现小车循迹功能。
        臂章功能大致和循迹功能一致一致,利用前头
        的红外收发管,可判断前方是否遇到障碍,若
        遇到绕过障碍物继续前行。
        定位功能,主要是是根据需要行驶的距离计算
        需要行驶的时间。
版  权:付江云 2010年6月10日授予 杨晓梅
************************************************/
#include

//-----以下是小车行驶模模式宏定义--------------//
#define runstop  0x00
#define runhead  0x01
#define runback  0x02
#define runleft  0x03
#define runright 0x04

//-----以下是左右直流电机前进倒退控制口定义----//
sbit runheadL = P0^0;
sbit runheadR = P0^2;
sbit runbackL = P0^1;
sbit runbackR = P0^3;

//----以下是设置键端口定义---------------------//
//sbit INT0 = P3^2;
sbit keyADD = P2^1;
sbit keyDEC = P2^2;

//--以下是传感器输出端及车头左右亮灯端口定义---//
sbit leftled  = P0^7;
sbit rightled = P0^4;
sbit leftIR   = P0^6;
sbit rightIR  = P0^5;
sbit headIR   = P2^0;

//--以下是1602液晶显示的控制端口及数据口定义---//
sbit lcdrs = P2^3;
sbit lcdrw = P2^4;
sbit lcden = P2^5;
#define lcd_data P1

//--------以下是预设液晶显示内容---------------//
unsigned char code num[10] = "0123456789";
unsigned char code stunum[16] = " Fujiangyun.com ";
unsigned char code syswait[16] = " Waitting Start!";
unsigned char code sth[16] = "Please Set Hour!";
unsigned char code stm[16] = "Please Set Mine!";
unsigned char code cho[16] = "Please Chose!   ";
unsigned char code waitxj[16] = "Waitting XunJi! ";
unsigned char code waitbz[16] = "Waitting BiZhang";
unsigned char code setdwi[16] = "Please Set DWei!";
unsigned char code line1[8] = " 07cm/s.";
unsigned char code line2_1[16] = "XunJi           ";
unsigned char code line2_2[16] = "BiZhang         ";
unsigned char code line2_3[7] = "DingWi ";
unsigned char code line2_c[2] = "cm";
unsigned char code cbz[16] = "You Chose BZ.   ";
unsigned char code cxj[16] = "You Chose XJ.   ";
unsigned char code cdw[16] = "You Chose DW.   "; 

/*******以下是系统需要用到的全局变量,依次是时、分、秒
、定时器中断次数变量、系统标志变量、功能模式标志变量*/
unsigned char hour,mine,sec,tempnum,sysflag,workflag;
unsigned int  golong,dingtime;//定位模式下设定行进的距离及时间

void delayms(unsigned int z)//1毫秒延时函数
{
    unsigned int x,y;
    for(x=z;x>0;x--)
        for(y=124;y>0;y--);
}

void lcd_write_com(unsigned char com)//液晶写指令函数
{
    lcdrw = 0;
    lcdrs = 0;
    lcd_data = com;
    delayms(5);
    lcden = 1;
    delayms(5);
    lcden = 0;
}

void lcd_write_dat(unsigned char dat)//液晶写数据函数
{
    lcdrw = 0;
    lcdrs = 1;
    lcd_data = dat;
    delayms(5);
    lcden = 1;
    delayms(5);
    lcden = 0;
}

void lcd_init()//液晶初始化函数
{
    lcden = 0;
    lcd_write_com(0x38);
    lcd_write_com(0x0c);
    lcd_write_com(0x06);
    lcd_write_com(0x01);
    lcd_write_com(0x80);
}

void runmode(unsigned char mode)//小车行进模式选择函数
{
    runheadL = 0;
    runbackL = 0;
    runheadR = 0;
    runbackR = 0;
    switch(mode)
    {
        case runstop:                //停止
        {
            runheadL = 0;
            runbackL = 0;
            runheadR = 0;
            runbackR = 0;
            break;
        }
        case runhead:                //前进
        {
            runheadL = 1;
            runheadR = 1;
            break;
        }
        case runback:                //后退
        {
            runbackL = 1;
            runbackR = 1;
            break;
        }
        case runleft:                //左转
        {
            runbackL = 1;
            runheadR = 1;
            break;
        }
        case runright:                //右转
        {
            runheadL = 1;
            runbackR = 1;
            break;
        }
        default :
        {
            break;
        }
    }
}

void xunji()//循迹子程序
{
    leftled  = leftIR;
    rightled = rightIR;
    if(leftIR==0)
    {
        runmode(runright);
        delayms(10);
    }
    if(rightIR==0)
    {
        runmode(runleft);
        delayms(10);
    }
    runmode(runhead);
}

void bizhang()//避障子程序
{
    if(headIR==0)
    {
        runmode(runback);
        delayms(500);
        runmode(runleft);
        delayms(500);
    }
    runmode(runhead);
}

void dingwei(unsigned int dat)//定位子程序
{
    dat = (dat/7)*1000;//秒速为7厘米
    runmode(runhead);
    delayms(dat);
    runmode(runstop);
    sysflag = 1;
}

void main()//主函数入口
{
    unsigned char i,tempflag;
    //--------------以下是系统初始化----------------------//
    sysflag = 0;
    hour = 23;
    mine = 59;
    golong = 0;
    tempnum = 0;
    EA = 1;
    EX0 = 0;
    ET0 = 1;
    TR0 = 0;
    PT0 = 1;
    TMOD = 0x01;
    TH0 = 0x3C;
    TL0 = 0x0B0;
    //--------------系统初始化结束----------------------//
    lcd_init();        //液晶初始化调用
    //---显示初始欢迎数据-------------------//
    lcd_write_com(0x80);
    for(i=0;i<16;i++)
        lcd_write_dat(stunum[i]);
    lcd_write_com(0x80+0x40);
    for(i=0;i<16;i++)
        lcd_write_dat(syswait[i]);
    //---显示初始欢迎数据结束---------------//
    runmode(runstop);//初始化小车处于停止状态
    while(1)
    {
        if(sysflag==0)//当系统处于状态0时,判断等待按键设置时间
        {
            if(INT0==0)
            {
                delayms(5);
                if(INT0==0)
                {
                    switch(tempflag)
                    {
                        case 0:
                            tempflag = 1;
                            lcd_write_com(0x80);
                            lcd_write_dat(num[hour/10]);
                            lcd_write_dat(num[hour%10]);
                            lcd_write_dat(':');
                            lcd_write_dat(num[mine/10]);
                            lcd_write_dat(num[mine%10]);
                            for(i=0;i<11;i++)
                                lcd_write_dat(' ');
                            lcd_write_com(0x80+0x40);
                            for(i=0;i<16;i++)
                                lcd_write_dat(sth[i]);
                            break;
                        case 1:
                            tempflag = 2;
                            lcd_write_com(0x80+0x40);
                            for(i=0;i<16;i++)
                                lcd_write_dat(stm[i]);
                            break;
                        case 2:
                            TR0 = 1;
                            tempflag = 0;
                            sysflag = 1;
                            lcd_write_com(0x80+0x40);
                            for(i=0;i<16;i++)
                                lcd_write_dat(cho[i]);
                            break;
                        default :
                            break;
                    }
                    while(!INT0);
                }
            }
            if(keyADD==0)
            {
                delayms(5);
                if(keyADD==0)
                {
                    switch(tempflag)
                    {
                        case 1:
                        {
                            if(hour==23)
                                hour = 0;
                            else
                                hour++;
                            lcd_write_com(0x80);
                            lcd_write_dat(num[hour/10]);
                            lcd_write_dat(num[hour%10]);
                            break;
                        }
                        case 2:
                        {
                            if(mine==59)
                                mine = 0;
                            else
                                mine++;
                            lcd_write_com(0x80+3);
                            lcd_write_dat(num[mine/10]);
                            lcd_write_dat(num[mine%10]);
                            break;
                        }
                        default :
                            break;
                    }
                }
                while(!keyADD);
            }
            if(keyDEC==0)
            {
                delayms(5);
                if(keyDEC==0)
                {
                    switch(tempflag)
                    {
                        case 1:
                        {
                            if(hour==0)
                                hour = 23;
                            else
                                hour--;
                            lcd_write_com(0x80);
                            lcd_write_dat(num[hour/10]);
                            lcd_write_dat(num[hour%10]);
                            break;
                        }
                        case 2:
                        {
                            if(mine==0)
                                mine = 59;
                            else
                                mine--;
                            lcd_write_com(0x80+3);
                            lcd_write_dat(num[mine/10]);
                            lcd_write_dat(num[mine%10]);
                            break;
                        }
                        default :
                            break;
                    }
                }
                while(!keyDEC);
            }

        }        
        if(sysflag==1)//系统处于状态1时等待选择功能模式
        {
            if(INT0==0)
            {
                delayms(5);
                if(INT0==0)
                {
                    if(workflag!=0)
                    {
                        sysflag = 2;
                        lcd_write_com(0x80+5);
                        for(i=0;i<8;i++)
                            lcd_write_dat(line1[i]);
                        switch(workflag)
                        {
                            case 1:
                            {
                                lcd_write_com(0x80+0x40);
                                for(i=0;i<16;i++)
                                    lcd_write_dat(waitxj[i]);
                                break;
                            }
                            case 2:
                            {
                                lcd_write_com(0x80+0x40);
                                for(i=0;i<16;i++)
                                    lcd_write_dat(setdwi[i]);
                                break;
                            }
                            case 3:
                            {
                                lcd_write_com(0x80+0x40);
                                for(i=0;i<16;i++)
                                    lcd_write_dat(waitbz[i]);
                                break;
                            }
                            default :
                                break;
                        }
                    }
                }
                while(!INT0);
            }
            if(keyADD==0)
            {
                delayms(5);
                if(keyADD==0)
                {
                    switch(workflag)
                    {
                        case 0:
                        {
                            workflag = 1;
                            lcd_write_com(0x80+0x40);
                            for(i=0;i<16;i++)
                                lcd_write_dat(cxj[i]);
                            break;
                        }
                        case 1:
                        {
                            workflag = 2;
                            lcd_write_com(0x80+0x40);
                            for(i=0;i<16;i++)
                                lcd_write_dat(cdw[i]);
                            break;
                        }
                        case 2:
                        {
                            workflag = 3;
                            lcd_write_com(0x80+0x40);
                            for(i=0;i<16;i++)
                                lcd_write_dat(cbz[i]);
                            break;
                        }
                        case 3:
                        {
                            workflag = 1;
                            lcd_write_com(0x80+0x40);
                            for(i=0;i<16;i++)
                                lcd_write_dat(cxj[i]);
                            break;
                        }
                        default :
                            break;
                    }
                }
                while(!keyADD);
            }
            if(keyDEC==0)
            {
                delayms(5);
                if(keyDEC==0)
                {
                    switch(workflag)
                    {
                        case 0:
                        {
                            workflag = 3;
                            lcd_write_com(0x80+0x40);
                            for(i=0;i<16;i++)
                                lcd_write_dat(cbz[i]);
                            break;
                        }
                        case 1:
                        {
                            workflag = 3;
                            lcd_write_com(0x80+0x40);
                            for(i=0;i<16;i++)
                                lcd_write_dat(cbz[i]);
                            break;
                        }
                        case 2:
                        {
                            workflag = 1;
                            lcd_write_com(0x80+0x40);
                            for(i=0;i<16;i++)
                                lcd_write_dat(cxj[i]);
                            break;
                        }
                        case 3:
                        {
                            workflag = 2;
                            lcd_write_com(0x80+0x40);
                            for(i=0;i<16;i++)
                                lcd_write_dat(cdw[i]);
                            break;
                        }
                    }
                }
                while(!keyDEC);
            }
        }
        if(sysflag==2)//系统处于状态2时等待设置并启动相应的功能模式
        {
            if(workflag==1)
            {
                if(INT0==0)
                {
                    delayms(5);
                    if(INT0==0)
                    {
                        sysflag = 3;
                        lcd_write_com(0x80+0x40);
                        for(i=0;i<16;i++)
                            lcd_write_dat(line2_1[i]);
                        EX0 = 1;
                    }
                    while(!INT0);
                }
            }
            if(workflag==3)
            {
                if(INT0==0)
                {
                    delayms(5);
                    if(INT0==0)
                    {
                        sysflag = 3;
                        lcd_write_com(0x80+0x40);
                        for(i=0;i<16;i++)
                            lcd_write_dat(line2_2[i]);
                        EX0 = 1;
                    }
                    while(!INT0);
                }
            }
            if(workflag==2)
            {
                if(INT0==0)
                {
                    delayms(5);
                    if(INT0==0)
                    {
                        sysflag = 3;
                        lcd_write_com(0x80+0x40);
                        for(i=0;i<7;i++)
                            lcd_write_dat(line2_3[i]);
                        lcd_write_dat(num[(golong/100)%10]);
                        lcd_write_dat(num[(golong/10)%10]);
                        lcd_write_dat(num[golong%10]);
                        lcd_write_dat('c');
                        lcd_write_dat('m');
                        for(i=0;i<4;i++)
                            lcd_write_dat(' ');
                        EX0 = 1;
                    }
                    while(!INT0);
                }
                if(keyADD==0)
                {
                    delayms(5);
                    if(keyADD==0)
                    {
                        if(golong==990)
                            golong = 0;
                        else
                            golong = golong+10;
                        lcd_write_com(0x80+0x40);
                        lcd_write_dat(num[(golong/100)%10]);
                        lcd_write_dat(num[(golong/10)%10]);
                        lcd_write_dat(num[golong%10]);
                        for(i=0;i<13;i++)
                            lcd_write_dat(' ');
                        
                    }
                    while(!keyADD);
                }
                if(keyDEC==0)
                {
                    delayms(5);
                    if(keyDEC==0)
                    {
                        if(golong==0)
                            golong = 990;
                        else
                            golong = golong-10;
                        lcd_write_com(0x80+0x40);
                        lcd_write_dat(num[(golong/100)%10]);
                        lcd_write_dat(num[(golong/10)%10]);
                        lcd_write_dat(num[golong%10]);
                        for(i=0;i<13;i++)
                            lcd_write_dat(' ');
                        
                    }
                    while(!keyDEC);
                }
            }
        }
        if(sysflag==3)            ///系统处于状态3时进行相应的功能模式
        {
            switch(workflag)
            {
                case 1:
                    xunji();
                    break;
                case 2:
                    dingwei(golong);
                    break;
                case 3:
                    bizhang();
                    break;
                default :
                    break;
            }
        }
    }
}


void intt0() interrupt 0
{
    unsigned char i;
    EX0 = 0;
    runmode(runstop);
    leftled  = 1;
    rightled = 1;
    delayms(5);
    sysflag = 1;
    lcd_write_com(0x80+0x40);
    for(i=0;i<16;i++)
        lcd_write_dat(cho[i]);
    while(!INT0);
}

void intt1() interrupt 1            //定时器T0中断函数,用于实时显示
{
    TH0 = 0x3C;
    TL0 = 0x0B0;
    if(tempnum==11)
    {
        tempnum = 0;
        if(sec==59)
        {
            sec = 0;
            if(mine==59)
            {
                mine = 0;
                lcd_write_com(0x80);
                lcd_write_dat(num[hour/10]);
                lcd_write_dat(num[hour%10]);
                lcd_write_dat(':');
                lcd_write_dat(num[mine/10]);
                lcd_write_dat(num[mine%10]);
                if(hour==23)
                {
                    hour = 0;
                }
                else
                    hour++;
            }
            else
            {
                mine++;
                lcd_write_com(0x80);
                lcd_write_dat(num[hour/10]);
                lcd_write_dat(num[hour%10]);
                lcd_write_dat(':');
                lcd_write_dat(num[mine/10]);
                lcd_write_dat(num[mine%10]);
            }
        }
        else
            sec++;
    }
    else
        tempnum++;
}

《 “智能电动小车” 》 有 2 条评论

  1. Mini Dragon 的头像

    博主也是学电子的么

    1. cloud 的头像

      嗯,呵呵,对啊.

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注