51单片机超声波避障小车

本文最后更新于:2022年5月29日 上午

入坑小项目 —— 自己动手制作51单片机超声波避障小车。

L298N的+12V接电池正极,+5V接单片机的VCC,GND接单片机的GND和电池的负极。

实物图片

V1jSwn.md.jpg

主程序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
#include <reg52.h>	   //52芯片配置文件
#include <intrins.h> //包含nop等系统函数
#include "bst_car.h" //包含bst—v51智能小车头文件

unsigned char pwm_val_left =0;//变量定义
unsigned char pwm_val_right =0;
unsigned char push_val_left =4;// 左电机占空比N/20 //速度调节变量 0-20。。。0最小,20最大
unsigned char push_val_right=4;// 右电机占空比N/20

bit Right_PWM_ON=1; //右电机PWM开关
bit Left_PWM_ON =1; //左电机PWM开关

unsigned int time=0;//用于存放定时器时间值
unsigned long S=0;//用于存放距离的值
bit flag =0; //量程溢出标志位
char a=0;

//=========================================================================================================================
void delay(unsigned int z)
{
unsigned int i,j;
for(i=z;i>0;i--) //i=z即延时约z毫秒
for(j=112;j>0;j--);
}

void Delay10us(unsigned char i) //10us延时函数 启动超声波模块时使用
{
unsigned char j;

do{
j = 10;
do{
_nop_();
}while(--j);
}while(--i);
}


void StartModule() //启动超声波模块
{
TX=1; //启动一次模块
Delay10us(2);
TX=0;
}

void Forward(void)//前进
{
push_val_left=5; //速度调节变量 0-20。。。0最小,20最大
push_val_right=5;
Left_moto_go; //左电机往前走
Right_moto_go; //右电机往前走
}

void Stop(void) //停车
{
Left_moto_Stop;
Right_moto_Stop;
}

void back(void) //后退
{
push_val_left=5; //速度调节变量 0-20。。。0最小,20最大
push_val_right=5;
Left_moto_back;
Right_moto_back;
}

void Turn_Right(void) //向右旋转
{
push_val_left=5; //速度调节变量 0-20。。。0最小,20最大
push_val_right=5;
Left_moto_go;
Right_moto_back;
}
//=========================================================================================================================
/********距离计算程序***************/
void conut1(void)
{
time=TH1*256+TL1;
TH1=0;
TL1=0;

//此时time的时间单位决定于晶振的频率,外接晶振为11.0592MHZ
//那么1us声波能走多远的距离呢?1s=1000ms=1000000us
// 340/1000000=0.00034米
//0.00034米/1000=0.34毫米 也就是1us能走0.34毫米
//但是,我们现在计算的是从超声波发射到反射接收的双路程,
//所以我们将计算的结果除以2才是实际的路程
S=time*0.17+10;//此时计算到的结果为毫米,并且是精确到毫米的后两位了,有两个小数点
}

void Conut(void)
{

conut1();
//========避障部分===========================================
if(S<=240) //////////////////////////// 刹车障碍物距离 跟车速有关 可更改
{
a++;
if(a>=2)
{
a=0;
FM=0;
Stop();
back(); //后退缓冲
delay(230);////////////////////////////////////////// 后退缓冲时间 跟车速有关 可更改

B:Turn_Right();
delay(50); /////////////////////////////////// 旋转角度 跟环境复杂程度有关 可更改
Stop();
delay(100); //////////////////////////////////// 旋转顿挫时间 视觉效果 可更改
StartModule();
while(RX==0);
TR1=1; //开启计数
while(RX); //当RX为1计数并等待
TR1=0; //关闭计数
conut1();


if(S>340) // 可直行方向无障碍物距离 跟环境有关 可更改
{

Turn_Right();
delay(90);
Stop(); //微调前进方向 避免车宽对前进影响
delay(200);
FM=1;
Forward();
}
else
{
goto B; //若没转到空旷方向 回到B点 继续旋转一次
}

}
else
{
Forward(); //无障碍物 直行
}

}

else
{
a=0;
Forward(); //无障碍物 直行
}
//=======================================

}

/********************************************************/
void zd0() interrupt 3 //T0中断用来计数器溢出,超过测距范围
{
flag=1; //中断溢出标志
RX=0;
}

/********超声波高电平脉冲宽度计算程序***************/
void Timer_Count(void)
{
TR1=1; //开启计数
while(RX); //当RX为1计数并等待
TR1=0; //关闭计数
Conut(); //计算

}

// 左电机调速
/*调节push_val_left的值改变电机转速,占空比*/
void pwm_out_left_moto(void)
{
if(Left_PWM_ON)
{
if(pwm_val_left<=push_val_left)
{
ENA=1;
}
else
{
ENA=0;
}
if(pwm_val_left>=20)
pwm_val_left=0;
}
else
{
ENA=0; //若未开启PWM则EN1=0 左电机 停止
}
}

/******************************************************************/
/* 右电机调速 */
void pwm_out_right_moto(void)
{
if(Right_PWM_ON)
{
if(pwm_val_right<=push_val_right) //20ms内电平信号 111 111 0000 0000 0000 00
{
ENB=1; //占空比6:20
}
else
{
ENB=0;
}
if(pwm_val_right>=20)
pwm_val_right=0;
}
else
{
ENB=0; //若未开启PWM则EN2=0 右电机 停止
}
}

//TIMER0中断服务子函数产生PWM信号
void timer0()interrupt 1 using 2
{
TH0=0XFC; //1Ms定时
TL0=0X66;
pwm_val_left++;
pwm_val_right++;
pwm_out_left_moto();
pwm_out_right_moto();
}

/********************************************************/
void keyscan(void) //按键扫描函数
{
A: if(K4==0) //判断是否有按下信号
{
delay(10); //延时10ms
if(K4==0) //再次判断是否按下
{
FM=0; //蜂鸣器响
while(K4==0); //判断是否松开按键
FM=1; //蜂鸣器停止
}
else
{
goto A; //跳转到A重新检测
}
}
else
{
goto A; //跳转到A重新检测
}
}
/********************************************************/

/*************主程序********************/
void main(void)
{

unsigned int a;

TMOD=TMOD|0x10; //设T0为方式1,GATE=1;
EA=1; //开启总中断
TH1=0;
TL1=0;
ET1=1;
TH0=0XFC; //1ms定时
TL0=0X66;
TR0=1;
ET0=1; //允许T0中断
keyscan() ; //按键扫描


//=======================================================================================================================
while(1)
{
RX=1;
StartModule(); //启动模块
for(a=951;a>0;a--)
{
if(RX==1)
{
Timer_Count(); //超声波高电平脉冲宽度计算函数
}
}
}
}

bst_car.h头文件代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#ifndef __BSTCAR_H__
#define __BSTCAR_H__

/************BST-V51智能小车头文件*************/

//定义小车驱动模块输入IO口
sbit IN1=P1^2;
sbit IN2=P1^3;
sbit IN3=P1^6;
sbit IN4=P1^7;
sbit ENA=P1^4;
sbit ENB=P1^5;



//定义按键
sbit K4=P3^5;


//蜂鸣器驱动口定义
sbit FM=P2^5;


sbit TX=P2^1; //超声波模块Trig 控制端
sbit RX=P2^0; //超声波模块Echo 接收端


#define Left_moto_go {IN1=0,IN2=1;} //左电机向前走
#define Left_moto_back {IN1=1,IN2=0;} //左边电机向后转
#define Left_moto_Stop {ENA=0;} //左边电机停转
#define Right_moto_go {IN3=1,IN4=0;} //右边电机向前走
#define Right_moto_back {IN3=0,IN4=1;} //右边电机向后走
#define Right_moto_Stop {ENB=0;} //右边电机停转



#endif

51单片机超声波避障小车
https://kevinloongc.github.io/posts/d7663396.html
作者
Kevin Loongc
发布于
2019年4月20日
许可协议