• 51单片机-蓝牙遥控智能小车-红外循迹(代码+硬件连接)


      前几天弄了个基于51芯片的蓝牙红外小车,因为是新手也没有人教,网上的资料也不够齐全(很多都是跳过新手那一步,比如说接线),做的过程中遇到很多问题,做的比较艰难,因而写一篇记录整个过程的文章,希望能够给新手提供一些帮助同时也做一个总结。

    组装完成的小车,比较丑。

    效果图

     

    1.材料(可以在淘宝上买得到)

      1.4wd小车一台,包含马达,两个底盘,和螺丝等(要自己组装,)

      

      2.  L298N电机驱动模块两个,用来控制马达的转速,方向,停止与否。

        

      3. 51单片机最小系统板一个和STC89C52RC芯片一个

       

      4.HC-05蓝牙模块一个(蓝牙遥控)和usb转TTL转接模块一个(用于设置和调试蓝牙模块)

      

      

       5. 4路红外循迹模块(黑白循迹)

      

       6. 18650电池四个和18650电池盒和杜邦线若干。

    我用的材料就是以上这些。

    2. 组装

      第二个难点就是组装,难在如何接线。

      1.先把四个马达和车轮装在一起,组装成一个小车框架。

      2.L298N电机的接线

      

       一个L298N有四个输出口(out1,out2,out3,out4)接马达,每两个输出口控制一个马达,因此可以控制两个马达,12v接口接电源正极,5v接口是给最小系统板供电,所以5v接系统板5v口。四个IO输入口(in1,in2,in3,in4)通过芯片控制输出口。两个使能端口(A,B),只有高电平时电机才有有效,低电平时电机不转

    转。因为有两个电机只有一个供电源所以两个电机要并联连接在一起。

    下面是电机的控制表,当使能端位低电平(0)时电机处于停止状态,当输出口为(00或11)时处于制动状态,阻止电机转动。

       L298N无效,无法驱动马达的原因(1.电压不够,起码要7v以上。2.使能端没有处于高电平状态 。3.L298N或马达坏了).

      3.蓝牙的接线

      蓝牙接在最小系统板,蓝牙的TXD(发送口)口接系统板的RXD(接收口)口,RXD口接TXD口也就是交叉连接,发送口对接收口。

      在接在系统板之前,要对蓝牙进行一些设置(名称,密码,波特率),这时就要用到usb转TTL模块。

      

      接在电脑上,打开串口调试助手(软件在后面的链接),进入AT模式 (进入方法,蓝牙模块上面有个按钮,在usb口插入电脑前,长按不放,插入电脑即可,如果看到蓝牙模块上的灯在快速闪烁,说明已经进入AT模式,慢闪是工作模式)。

      

      

      比如设置名字hello,密码123456

      AT+NAME=hello

      AT+PSWD=123456

      发送以上两个命令即可,之后打开手机的蓝牙试试能不能连接成功。

      4.红外的接线

      红外模块的接线很简单,按照引脚上的说明,一一对应接在系统板上即可。

    3.代码

      代码大概分成三个模块,蓝牙遥控模块,红外循迹模块,PWM调速模块。

      1.蓝牙那部分还需要在手机下载一个蓝牙助手用来控制小车,我的是在小米商城下载的,有广告,并不是很好用,但又找不到好的,只好将就一下。如果会android编程的,可以自己写一个。下面那些命令都是自定义,你可以根据需要,自己定制,写代码的时候对应就行。
      

      代码如下,已写好注释。

      

      1 #include<reg52.h>
      2 #include<intrins.h>
      3 
      4 sbit LEA=P1^0;//左边轮的使能端A
      5 sbit LEB=P1^1;//左边轮的使能端B
      6 //左前轮
      7 sbit LIN1=P1^2;//
      8 sbit LIN2=P1^3;//
      9 //左后轮
     10 sbit LIN3=P1^4;
     11 sbit LIN4=P1^5;
     12 
     13 sbit REA=P3^2;//右边轮使能端A
     14 sbit REB=P3^3;//右边轮使能端B
     15 //右前轮
     16 sbit RIN1=P3^4;
     17 sbit RIN2=P3^5;
     18 //右后轮
     19 sbit RIN3=P3^6;
     20 sbit RIN4=P3^7;
     21 
     22 //方向控制
     23 void delay(int time);//延时函数
     24 void forward();//前进
     25 void back();//后退
     26 void stop();//停止
     27 void start();//启动
     28 void turnLeft();//左转
     29 void turnRight();//右转
     30 
     31 
     32 //蓝牙模块
     33 //定时器1用作串口发生器,用于与蓝牙通信
     34 void time1Init();//定时器1的初始化
     35 void processMsg();//处理蓝牙接收到的信息
     36 
     37 //红外模块
     38 //从右到左
     39 //in1是最右边的红外灯
     40 sbit in1=P2^0;
     41 sbit in2=P2^1;
     42 sbit in3=P2^2;
     43 sbit in4=P2^3;
     44 int isTrace=0;//是否开启循迹功能
     45 void trace();//红外循迹
     46 
     47 
     48 //PWM调速
     49 //通过控制使能端高低电平输出的时间从而控制速度
     50 int count=0; //用于计数
     51 int pwm=20;      //表示启动的时间,20表示启动20ms
     52 void time0Init();//定时器0的初始化.
     53                 //用于控制高低电平的时间
     54                 //定时器比较准确
     55 void go();//启动 使能端为高电平 1
     56 void pause();//停止    使能端为低电平 0
     57 void time0Fun();//定时器0的中断函数
     58 
     59 
     60 
     61 
     62 int main()
     63 {
     64 
     65     EA=1;//打开总中断
     66     time1Init();//定时器1初始化
     67     time0Init();//定时器0初始化
     68     start();//使车的方向一开始向前
     69 
     70     while(1)
     71     {
     72         if(isTrace)
     73             trace();
     74         if(count>=100) //100ms一个周期
     75             count=0;
     76         if(count<pwm) //pwm表示启动的时间         
     77                       //pwm越大 速度越快
     78             go();
     79         else if(count>=pwm)
     80             pause();
     81     }
     82     return 0;
     83 }
     84 
     85 
     86 void delay(int time)//延时函数
     87 {
     88     int i;
     89     for(i=0;i<time;i++)
     90     {
     91         _nop_();//在晶振12M下
     92                 //一个nop函数延时1us
     93     }
     94 }
     95 void forward()//前进
     96 {
     97     //前进,所有轮正转
     98     LIN1=0;
     99     LIN2=1;
    100 
    101     LIN3=0;
    102     LIN4=1;
    103 
    104     RIN1=0;
    105     RIN2=1;
    106 
    107     RIN3=0;
    108     RIN4=1;
    109 }
    110 void back()//后退
    111 {
    112       //前进,所有轮反转
    113     LIN1=1;
    114     LIN2=0;
    115 
    116     LIN3=1;
    117     LIN4=0;
    118 
    119     RIN1=1;
    120     RIN2=0;
    121 
    122     RIN3=1;
    123     RIN4=0;
    124 }
    125 void turnLeft()//左转
    126 {
    127     //左转  左边的轮正转,右边轮反转
    128     LIN1=0;
    129     LIN2=1;
    130 
    131     LIN3=0;
    132     LIN4=1;
    133 
    134     RIN1=1;
    135     RIN2=0;
    136 
    137     RIN3=1;
    138     RIN4=0;
    139     delay(5000);//延时5ms 控制转弯的角度
    140 
    141 }
    142 void turnRight()//右转
    143 {
    144     //右转,左边轮反转,右边轮正转
    145     LIN1=1;
    146     LIN2=0;
    147 
    148     LIN3=1;
    149     LIN4=0;    
    150 
    151     RIN1=1;
    152     RIN2=0;
    153 
    154     RIN3=1;
    155     RIN4=0;
    156     delay(5000);//延时5ms 控制转弯的角度
    157 }
    158 void stop()//停止
    159 {
    160     //停止,全部高电平或低电平
    161     LIN1=0;
    162     LIN2=0;
    163 
    164     LIN3=0;
    165     LIN4=0;    
    166 
    167     RIN1=0;
    168     RIN2=0;
    169 
    170     RIN3=0;
    171     RIN4=0;
    172 }
    173 
    174 void start()
    175 {
    176     forward();//一开始,前进方向
    177 }
    178 
    179 //定时器1用作串口发生器,用于与蓝牙通信
    180 void time1Init()//定时器1的初始化
    181 {
    182     TMOD=0x20;//定时器1,工作模式2,8位自动重装模式
    183     TH1=0xfd;//9600波特率,要与蓝牙的一致
    184     TL1=0xfd;
    185     //串口通信方式1
    186     SM0=0;
    187     SM1=1;
    188     PCON=0x00;//波特率不加倍
    189     SCON=0x50;//工作方式一
    190     REN=1;//允许接收
    191     ES=1;//开启串口中断
    192     TR1=1;//启动定时1
    193 
    194 }
    195 void processMsg() interrupt 4 //中断4
    196 //处理蓝牙接收到的信息
    197 {
    198     char ch;
    199     //等待接收完毕
    200     while(!RI)//当RI为0时没有接收完毕
    201         ;        //为1时接收完毕
    202     //信息存存在sbuf中
    203     ch=SBUF;//获取接收的信息
    204     switch(ch)
    205     {
    206         case 'f':  //前进
    207             forward();
    208             break;
    209         case 'b': //后退
    210             back();
    211             break;
    212         case 'l': //左转
    213             turnLeft();
    214             break;
    215         case 'r': //右转
    216             turnRight();
    217             break;
    218         case 's':    //停止
    219             stop();
    220             break;
    221         case 'o':
    222             start();
    223             break;//启动
    224         case 't': //开启循迹功能
    225             isTrace=1;
    226             break;
    227         case '1':  //一档
    228             pwm=20;
    229             break;
    230         case '2':  //二档
    231             pwm=60;
    232             break;
    233         case '3': //三档
    234             pwm=100;
    235             break;
    236         default:
    237             break;
    238     }
    239 }
    240 void trace()//红外循迹
    241 {
    242     //当红外遇到黑线时吸收红外光,输出高电平
    243     //遇到白线时反射红外,输出低电平
    244 
    245     int dir=0;//0表示直走
    246                 //1 代表左转
    247                 //2 代表右转
    248     //0 0 0 0
    249     if(in1==0&&in2==0&&in3==0&&in4==0)
    250         dir=0;
    251     //1 0 0 0
    252     else if (in1==1&&in2==0&&in3==0&&in4==0)
    253         dir=2;
    254     //1 1 0 0
    255     else if (in1==1&&in2==1&&in3==0&&in4==0)
    256         dir=2;
    257     //1 1 1 0
    258     else if (in1==1&&in2==1&&in3==1&&in4==0)
    259         dir=0;
    260     //1 1 1 1
    261     else if (in1==1&&in2==1&&in3==1&&in4==1)
    262         dir=0;
    263 
    264     //0 1 0 0
    265     else if (in1==0&&in2==1&&in3==0&&in4==0)
    266         dir=2;
    267     //0 1 1 0
    268     else if (in1==0&&in2==1&&in3==1&&in4==0)
    269         dir=0;
    270     //0 1 1 1
    271     else if (in1==0&&in2==1&&in3==1&&in4==1)
    272         dir=1;
    273     //0 0 1 0
    274     else if (in1==0&&in2==0&&in3==1&&in4==0)
    275         dir=1;
    276     //0 0 1 1
    277     else if (in1==0&&in2==0&&in3==1&&in4==1)
    278         dir=1;
    279 
    280     //1 0 1 0
    281     else if (in1==1&&in2==0&&in3==1&&in4==0)
    282         dir=1;
    283     //1 1 1 0
    284     else if (in1==1&&in2==1&&in3==1&&in4==0)
    285         dir=2;
    286     //1 0 1 1
    287     else if (in1==1&&in2==0&&in3==1&&in4==1)
    288         dir=0;
    289     //1 0 0 1
    290     else if (in1==1&&in2==0&&in3==0&&in4==1)
    291         dir=0;
    292     //0 0 0 1
    293     else if (in1==0&&in2==0&&in3==0&&in4==1)
    294         dir=1;
    295     //1 1 0 1
    296     else if (in1==1&&in2==1&&in3==0&&in4==1)
    297         dir=0;
    298     switch(dir)
    299     {
    300         case 0:
    301             forward();
    302             break;
    303         case 1:
    304             turnLeft();
    305             break;
    306         case 2:
    307             turnRight();
    308             break;
    309     }
    310 }
    311 
    312 void time0Init()//定时器0的初始化.
    313                 //用于控制高低电平的时间
    314                 //定时器比较准确
    315 {
    316     TMOD|=0x01;//工作方式一
    317                 //用或运算是为了不改变
    318                 //定时器1对应位的值。
    319     TH0=0xfc;
    320     TL0=0x66;  //定时1ms
    321 
    322     ET0=1;//开启定时器0的中断
    323     TR0=1;//启动定时器0
    324 }
    325 
    326 void go()//启动 使能端为高电平 1
    327 {
    328     LEA=1;
    329     LEB=1;
    330     REA=1;
    331     REB=1;
    332 }
    333 
    334 void pause()//停止    使能端为低电平 0
    335 {
    336     LEA=0;
    337     LEB=0;
    338     REA=0;
    339     REB=0;
    340 }
    341 
    342 void time0Fun() interrupt 1
    343 {
    344     TH0=0xfc;
    345     TL0=0x66;
    346     //1ms 中断一次,count加一
    347     count++;
    348 }

    下面是要用到的软件,包括 串口调试助手,代码编写工具KEil, 烧录软件TCICP_V6.87

    链接:https://pan.baidu.com/s/1aeZs1fKelqX3JohfM3qlGQ
    提取码:5151

    有任何问题可以找我

  • 相关阅读:
    英雄大乱斗
    深浅拷贝(copy)
    myleecode
    代码量简单统计
    pandas 模块 05
    matplotlib 模块 07
    KVC 和KVO浅谈
    iOS开发中懒加载的使用和限制
    关于空白模板插件的使用
    UIImageC处理
  • 原文地址:https://www.cnblogs.com/duichoumian/p/13661064.html
Copyright © 2020-2023  润新知