找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 1940|回复: 0
打印 上一主题 下一主题
收起左侧

单片机智能小车源程序

[复制链接]
跳转到指定楼层
楼主
ID:112047 发表于 2016-4-3 16:17 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

   /*预处理命令*/
#include<reg52.h>    //包含单片机寄存器的头文件
#include<intrins.h> //包含_nop_()函数定义的头文件
#define uchar unsigned char
#define uint  unsigned int
#define delayNOP(); {_nop_();_nop_();_nop_();_nop_();};
sbit IRIN=P3^2;         //红外接收器数据线
sbit LCD_RS = P0^7;            
sbit LCD_RW = P0^6;
sbit LCD_EN = P0^5;
uchar begin[]={"My car!"};
uchar cdis1[]={"jiansu!"};
uchar cdis2[]={"qianjin!"};
uchar cdis3[]={"jiasu!"};
uchar cdis4[]={"zuozhuang!"};
uchar cdis5[]={"STOP!"};
uchar cdis6[]={"youzhuan!"};
uchar cdis8[]={"daoche!"};
sbit M1   = P1^0;
sbit M2   = P1^1;
sbit M3   = P1^2;
sbit M4   = P1^3;
sbit EN12 = P1^4;
sbit EN34 = P1^5;
uchar IRCOM[7];
uchar m,n;
uchar t=2;
uchar g;
uchar code digit[]={"0123456789"};
uint v;
uchar count;
bit flag;
void delayxms(uchar t);
void delay(unsigned char x) ;
void delay1(int ms);
void motor();
void lcd_display();
/*
检查LCD忙状态
lcd_busy1时,忙,等待。lcd-busy0,闲,可写指令与数据
*/
bit lcd_busy()
{                          
        bit result;
        LCD_RS = 0;
        LCD_RW = 1;
        LCD_EN = 1;
        delayNOP();
        result = (bit)(P0&0x80);
        LCD_EN = 0;
        return(result);
}
/*
写指令数据到LCD
RS=LRW=LE=高脉冲,D0-D7=指令码
*/
void lcd_wcmd(uchar cmd)
{                          
   while(lcd_busy());
    LCD_RS = 0;
    LCD_RW = 0;
    LCD_EN = 0;
    _nop_();
    _nop_();
    P2 = cmd;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;  
}
/*
写显示数据到LCD
RS=HRW=LE=高脉冲,D0-D7=数据
*/
void lcd_wdat(uchar dat)
{                          
   while(lcd_busy());
    LCD_RS = 1;
    LCD_RW = 0;
    LCD_EN = 0;
    P2 = dat;
    delayNOP();
    LCD_EN = 1;
    delayNOP();
    LCD_EN = 0;
}
/*
LCD初始化设定
*/
void lcd_init()
{
    delay1(15);                  
    lcd_wcmd(0x38);      //16*2显示,5*7点阵,8位数据
    delay1(5);
    lcd_wcmd(0x38);         
    delay1(5);
    lcd_wcmd(0x38);         
    delay1(5);
    lcd_wcmd(0x0c);      //显示开,关光标
    delay1(5);
    lcd_wcmd(0x06);      //移动光标
    delay1(5);
    lcd_wcmd(0x01);      //清除LCD的显示内容
    delay1(5);
}
/*
设定显示位置
*/
void lcd_pos(uchar pos)
{                          
        lcd_wcmd(pos | 0x80);  //数据指针=80+地址变量
}
/*x显示速度提示符*/
void  display_sym(void)
{
lcd_pos(0x00);
lcd_wdat('v');
lcd_wdat('=');
}
/*显示速度数值*/
void display_vel(uint x)
{
uchar i,j,k,l;
i=x/1000;             //取千位
j=(x%1000)/100;         //取百位
k=(x%100)/10;         //取十位
l=x%10;                         //取个位
lcd_pos(0x02);
lcd_wdat(digit);
lcd_wdat(digit[j]);
lcd_wdat(digit[k]);
lcd_wdat(digit[l]);
}
/*显示速度单位*/
void display_unit(void)
{
lcd_pos(0x06);
lcd_wdat('r');
lcd_wdat('/');
lcd_wdat('m');
lcd_wdat('i');
lcd_wdat('n');
}
/*
主函数
*/
/*******************************************************************/
void main()
{
        uint a;
   
        IRIN=1;                    //I/O口初始化       
        IE=0x83;                 //允许总中断中断,使能 INT0 外部中断
        TCON=TCON|0x01;               //触发方式为脉冲负边沿触发
        lcd_init();
        TMOD=0x51;
    TH0=(65536-50000)/256;
    TL0=(65536-50000)/256;
    TR0=1;
    count=0;
    display_sym();
    display_vel(0);
    display_unit();
        lcd_pos(0x40);
        g=0;
        while(begin[g]!='\0')
        {
           lcd_wdat(begin[g]);
           g++;
         }
    while(1)
    {
      TR1=1;
      TH1=0;
      TL1=0;
      flag=0;
          display_sym();
          display_unit();
      while(flag==0);
      v=(TH1*256+TL1)*60/20;
      display_vel(v);
          motor();
          }
}
/**********************************************************/
void IR_IN() interrupt 0 using 0
{
        unsigned char j,k,N=0;
        unsigned char q=0;
        EX0 = 0;   
        delay(15);
        if (IRIN==1)
        {
                EX0 =1;
                return;
        }
                   //确认IR信号出现
        while (!IRIN)            //IR变为高电平,跳过9ms的前导低电平信号。
                delay(1);
       
        for (j=0;j<4;j++)         //收集四组数据
        {
                for (k=0;k<8;k++)        //每组数据有8
                {
                        while (IRIN)            //IR 变为低电平,跳过4.5ms的前导高电平信号。
                        {delay(1);}
                        while (!IRIN)          //IR 变为高电平
                                delay(1);
                        while (IRIN)           //计算IR高电平时长
                        {
                                delay(1);
                                N++;           
                                if (N>=30)
                                {
                                        EX0=1;
                                        return;
                                }                  //0.14ms计数过长自动离开。
                        }                        //高电平计数完毕               
                        IRCOM[j]=IRCOM[j] >> 1;     //数据最高位补“0
                        if(N>=8)
                        {
                                IRCOM[j] = IRCOM[j] | 0x80;                  //数据最高位补“1
                        }  
                        N=0;
                }
        }
       
        if(IRCOM[2]!=~IRCOM[3])
        {
                EX0=1;
                return;
        }
       
        IRCOM[5]=IRCOM[2] & 0x0F;     //取键码的低四位
        IRCOM[6]=IRCOM[2] >> 4;       //右移4次,高四位变为低四位
       
        if(IRCOM[5]>9)
        {
                IRCOM[5]=IRCOM[5]+0x37;
        }
        else
        IRCOM[5]=IRCOM[5]+0x30;
       
        if(IRCOM[6]>9)
        {
                IRCOM[6]=IRCOM[6]+0x37;
        }
        else
        IRCOM[6]=IRCOM[6]+0x30;
        q= (((IRCOM[6]&0x0f)<<4) + (IRCOM[5]&0x0f));
   
        switch(q)    //判断按键键码值
        {
                case 0x16:m=0;break; //串口发送0
                case 0x03:m=1;t++;if(t>=5)t=4;break;  //串口发送01
                case 0x18:m=2;n=2;break;              //串口发送02
                case 0x55:m=3;t--;if(t<=0)t=0;break;  //串口发送03
                case 0x08:m=4;n=4;break;              //串口发送04
                case 0x13:m=5;n=5;break;              //串口发送05
                case 0x51:m=6;n=6;break;              //串口发送06
                case 0x42:m=7;break;                  //串口发送07
                case 0x52:m=8;n=8;break;              //串口发送08
                case 0x41:m=9;break;                  //串口发送09
       
                default :break;
        }
     lcd_display();
         EX0 = 1;
          
}
/***************延时函数*****************************/
void delay(unsigned char x)    //x*0.14MS
{
        unsigned char i;
        while(x--)
        {
                for (i = 0; i<13; i++) {}
        }
}
void lcd_display()
{   
   
    g=0;
       
        switch(        m)
        {          
          case 1:  lcd_init();
                    lcd_pos(0x40);
                while(cdis1[g]!='\0')        //减速
                       {  
                                   lcd_wdat(cdis1[g]);
                          g++;
                }break;
        case 2:         lcd_init();
                    lcd_pos(0x40);                             //前进
                while(cdis2[g]!='\0')
                    {
                                  lcd_wdat(cdis2[g]);
                         g++;
                     }break;
     case 3:   lcd_init();
                    lcd_pos(0x40);                                  //加速
                while(cdis3[g]!='\0')
                    {   
                                    lcd_wdat(cdis3[g]);
                        g++;
                      }break;
        case 4:           lcd_init();
                    lcd_pos(0x40);                    //左转
                while(cdis4[g]!='\0')
                   {   
                               lcd_wdat(cdis4[g]);
                       g++;
                      }break;
        case 5:           lcd_init();
                    lcd_pos(0x40);                          //停车
                while(cdis5[g]!='\0')
                          {
                                    lcd_wdat(cdis5[g]);
                                            g++;
                            }break;
        case 6:           lcd_init();
                    lcd_pos(0x40);                         //右转
                           while(cdis6[g]!='\0')
                                {   
                                     lcd_wdat(cdis6[g]);
                                            g++;
                                } break;
        case 8:           lcd_init();
                    lcd_pos(0x40);                 //倒车
                        while(cdis8[g]!='\0')
                                {     
                                      lcd_wdat(cdis8[g]);
                                            g++;
                                }break;
        default :break;
   
}}
void motor()
{
     EN12=1;
         EN34=1;
    switch(        n)
        {   case 2:             //前进
                  M1=1;
                                   M2=0;
                              M3=1;
                               M4=0;
                   /* delayxms(5-t);
                              M1=0;
                                M3=0;
                   elayxms(t);           */
                  break;   
                 case 4:                              //左转
                     M1=0;
                           M2=0;
                                  M3=1;
                                  M4=0;
                     /*delayxms(5-t);
                      M1=0;
                  M3=0;
                 layxms(t+1);          */
                   break;                         
                 case 6:                                          //右转
                            M1=1;
                      M2=0;
                              M3=0;
                              M4=0;
                     /*delayxms(5-t);
                         M1=0;
                      M3=0;
                      layxms(t+1);                  */
                 break;          
                 case 8:                                //后退
                     M1=0;
                      M2=1;
                      M3=0;
                      M4=1;
                      /*delayxms(5-t);
                      M2=0;
                      M4=0;
                      layxms(t);          */
                   break;       
                 case 5:
                      EN12=0;
                       EN34=0;
                   break;
                default :break;
                 }
}
/*******************************************************
函数功能:定时器T0的中断服务函数
********************************************************/
void Time0(void ) interrupt 1 using 1 //定时器T0的中断编号为1,使用第1组工作寄存器
  {
    count++;          //T0每中断1次,count1
         if(count==20)     //若累计满20次,即计满1秒钟
          {
       flag=1;        //计满1秒钟标志位置1
                 count=0;       //0,重新统计中断次数
          }
    TH0=(65536-46083)/256;   //定时器T08位重新赋初值
         TL0=(65536-46083)%256;   //定时器T08位重新赋初值
       
  }  
void delay1(int ms)
{
        unsigned char y;
        while(ms--)
        {
                for(y = 0; y<250; y++)
                {
                        _nop_();
                        _nop_();
                        _nop_();
                        _nop_();
                }
        }
}
//************************************************************
void delayxms(uchar t)
{
uint i;
uchar j;
for(j=t;j>0;j--)
    for(i=80;i>0;i--);  //延时124*8+10=1002us
}

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

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

本版积分规则

小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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