前几天弄了个基于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
有任何问题可以找我