51单片机 多路超声波测距和报警 +Proteus仿真

51单片机 多路超声波测距和报警 +Proteus仿真


  • Proteus仿真
    在这里插入图片描述

Proteus仿真电路搭建注意事项

  • 蜂鸣器采用的是有源蜂鸣器,选择DC直流驱动的蜂鸣器,供电电压选择5V,默认调用出来的是12V,需要修改。

在这里插入图片描述

  • 元器件列表
    在这里插入图片描述

实例代码

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
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
#include <reg52.h>
#include <intrins.h>

#define uchar unsigned char // 以后unsigned char就可以用uchar代替
#define uint unsigned int // 以后unsigned int 就可以用uint 代替

sfr ISP_DATA = 0xe2; // 数据寄存器
sfr ISP_ADDRH = 0xe3; // 地址寄存器高八位
sfr ISP_ADDRL = 0xe4; // 地址寄存器低八位
sfr ISP_CMD = 0xe5; // 命令寄存器
sfr ISP_TRIG = 0xe6; // 命令触发寄存器
sfr ISP_CONTR = 0xe7; // 命令寄存器

sbit LcdRs_P = P1^1; // 1602液晶的RS管脚
sbit LcdRw_P = P1^2; // 1602液晶的RW管脚
sbit LcdEn_P = P1^3; // 1602液晶的EN管脚
//sbit Trig1\_P = P2^5; // 超声波模块1的Trig管脚
//sbit Echo1\_P = P2^6; // 超声波模块1的Echo管脚
sbit Trig2_P = P3^5; // 超声波模块2的Trig管脚
sbit Echo2_P = P3^6; // 超声波模块2的Echo管脚
sbit Trig3_P = P3^2; // 超声波模块3的Trig管脚
sbit Echo3_P = P3^3; // 超声波模块3的Echo管脚
sbit Trig4_P = P1^4; // 超声波模块4的Trig管脚
sbit Echo4_P = P1^5; // 超声波模块4的Echo管脚
sbit KeySet_P = P2^2; // 设置按键的管脚
sbit KeyDown_P = P2^1; // 减按键的管脚
sbit KeyUp_P = P2^0; // 加按键的管脚
sbit Buzzer_P = P2^3; // 蜂鸣器的管脚
//sbit Led1\_P = P2^4; // 传感器1报警灯
sbit Led2_P = P3^4; // 传感器2报警灯
sbit Led3_P = P1^6; // 传感器3报警灯
sbit Led4_P = P1^0; // 传感器4报警灯

uint gAlarm; // 报警距离变量



/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 单片机内部EEPROM不使能
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void ISP\_Disable()
{
ISP_CONTR = 0;
ISP_ADDRH = 0;
ISP_ADDRL = 0;
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 从单片机内部EEPROM读一个字节,从0x2000地址开始
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
unsigned char EEPROM\_Read(unsigned int add)
{
ISP_DATA = 0x00;
ISP_CONTR = 0x83;
ISP_CMD = 0x01;
ISP_ADDRH = (unsigned char)(add>>8);
ISP_ADDRL = (unsigned char)(add&0xff);
// 对STC89C51系列来说,每次要写入0x46,再写入0xB9,ISP/IAP才会生效
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
\_nop\_();
ISP\_Disable();
return (ISP_DATA);
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 往单片机内部EEPROM写一个字节,从0x2000地址开始
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void EEPROM\_Write(unsigned int add,unsigned char ch)
{
ISP_CONTR = 0x83;
ISP_CMD = 0x02;
ISP_ADDRH = (unsigned char)(add>>8);
ISP_ADDRL = (unsigned char)(add&0xff);
ISP_DATA = ch;
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
\_nop\_();
ISP\_Disable();
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 擦除单片机内部EEPROM的一个扇区
// 写8个扇区中随便一个的地址,便擦除该扇区,写入前要先擦除
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void Sector\_Erase(unsigned int add)
{
ISP_CONTR = 0x83;
ISP_CMD = 0x03;
ISP_ADDRH = (unsigned char)(add>>8);
ISP_ADDRL = (unsigned char)(add&0xff);
ISP_TRIG = 0x46;
ISP_TRIG = 0xB9;
\_nop\_();
ISP\_Disable();
}



/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 毫秒级的延时函数,time是要延时的毫秒数
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void DelayMs(uint time)
{
uint i,j;
for(i=0;i<time;i++)
for(j=0;j<112;j++);
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 1602液晶写命令函数,cmd就是要写入的命令
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void LcdWriteCmd(uchar cmd)
{
LcdRs_P = 0;
LcdRw_P = 0;
LcdEn_P = 0;
P0=cmd;
DelayMs(2);
LcdEn_P = 1;
DelayMs(2);
LcdEn_P = 0;
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 1602液晶写数据函数,dat就是要写入的数据
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void LcdWriteData(uchar dat)
{
LcdRs_P = 1;
LcdRw_P = 0;
LcdEn_P = 0;
P0=dat;
DelayMs(2);
LcdEn_P = 1;
DelayMs(2);
LcdEn_P = 0;
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 液晶光标定位函数
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void LcdGotoXY(uchar line,uchar column)
{
// 第一行
if(line==0)
LcdWriteCmd(0x80+column);
// 第二行
if(line==1)
LcdWriteCmd(0x80+0x40+column);
}



/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 液晶输出字符串函数
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void LcdPrintStr(uchar \*str)
{
while(\*str!='\0')
LcdWriteData(\*str++);
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 液晶输出数字
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void LcdPrintNum(uint num)
{
LcdWriteData(num/100+0x30); // 百位
LcdWriteData(num%100/10+0x30); // 十位
LcdWriteData(num%10+0x30); // 个位
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 1602液晶功能初始化
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void LcdInit()
{
LcdWriteCmd(0x38); // 16\*2显示,5\*7点阵,8位数据口
LcdWriteCmd(0x0C); // 开显示,不显示光标
LcdWriteCmd(0x06); // 地址加1,当写入数据后光标右移
LcdWriteCmd(0x01); // 清屏
}



/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 1602液晶显示内容初始化
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void LcdShowInit()
{
LcdGotoXY(0,0); // 定位到第0行第0列
LcdPrintStr("L: R: "); // 第0行显示“ U ”
LcdGotoXY(1,0); // 定位到第1行第0列
LcdPrintStr("D: "); // 第1行显示“ L D R ”
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 计算传感器1测量到的距离
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
/\*
uint GetDistance1(void)
{
uint ss; // 用于记录测得的距离

TH0=0;
TL0=0;

Trig1\_P=1; // 给超声波模块1一个开始脉冲
DelayMs(1);
Trig1\_P=0;

while(!Echo1\_P); // 等待超声波模块1的返回脉冲
TR0=1; // 启动定时器,开始计时
while(Echo1\_P); // 等待超声波模块1的返回脉冲结束
TR0=0; // 停止定时器,停止计时

ss=((TH0\*256+TL0)\*0.034)/2; // 距离cm=(时间us \* 速度cm/us)/2
return ss;
}
\*/

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 计算传感器2测量到的距离
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
uint GetDistance2(void)
{
uint ss; // 用于记录测得的距离

TH0=0;
TL0=0;

Trig2_P=1; // 给超声波模块2一个开始脉冲
DelayMs(1);
Trig2_P=0;

while(!Echo2_P); // 等待超声波模块2的返回脉冲
TR0=1; // 启动定时器,开始计时
while(Echo2_P); // 等待超声波模块2的返回脉冲结束
TR0=0; // 停止定时器,停止计时

ss=((TH0\*256+TL0)\*0.034)/2; // 距离cm=(时间us \* 速度cm/us)/2
return ss;
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 计算传感器3测量到的距离
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
uint GetDistance3(void)
{
uint ss; // 用于记录测得的距离

TH0=0;
TL0=0;

Trig3_P=1; // 给超声波模块3一个开始脉冲
DelayMs(1);
Trig3_P=0;

while(!Echo3_P); // 等待超声波模块3的返回脉冲
TR0=1; // 启动定时器,开始计时
while(Echo3_P); // 等待超声波模块3的返回脉冲结束
TR0=0; // 停止定时器,停止计时

ss=((TH0\*256+TL0)\*0.034)/2; // 距离cm=(时间us \* 速度cm/us)/2
return ss;
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 计算传感器4测量到的距离
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
uint GetDistance4(void)
{
uint ss; // 用于记录测得的距离

TH0=0;
TL0=0;

Trig4_P=1; // 给超声波模块4一个开始脉冲
DelayMs(1);
Trig4_P=0;

while(!Echo4_P); // 等待超声波模块4的返回脉冲
TR0=1; // 启动定时器,开始计时
while(Echo4_P); // 等待超声波模块4的返回脉冲结束
TR0=0; // 停止定时器,停止计时

ss=((TH0\*256+TL0)\*0.034)/2; // 距离cm=(时间us \* 速度cm/us)/2
return ss;
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 按键扫描
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void KeyScanf()
{
if(KeySet_P==0) // 判断是否有按键按下
{
LcdGotoXY(0,0); // 光标定位
LcdPrintStr(" Alarm Set "); // 第0行显示“ Alarm Set ”
LcdGotoXY(1,0); // 光标定位
LcdPrintStr(" alarm= cm "); // 第1行显示“ alarm= cm ”
LcdGotoXY(1,8); // 光标定位
LcdPrintNum(gAlarm); // 显示当前的报警值

DelayMs(10); // 消除按键按下的抖动
while(!KeySet_P); // 等待按键释放
DelayMs(10); // 消除按键松开的抖动

while(1)
{
/\* 报警值减的处理 \*/
if(KeyDown_P==0)
{
if(gAlarm>2) // 报警值大于2才能减1
gAlarm--; // 报警值减1
LcdGotoXY(1,8); // 光标定位
LcdPrintNum(gAlarm); // 刷新修改后的报警值
DelayMs(300); // 延时
}

/\* 报警值加的处理 \*/
if(KeyUp_P==0)
{
if(gAlarm<400) // 报警值小于400才能加1
gAlarm++; // 报警值加1
LcdGotoXY(1,8); // 光标定位
LcdPrintNum(gAlarm); // 刷新修改后的报警值
DelayMs(300); // 延时
}

/\* 退出报警值设置 \*/
if(KeySet_P==0)
{
break; // 退出while循环
}
}

LcdShowInit(); // 液晶恢复测量到测量界面
DelayMs(10); // 消除按键按下的抖动
while(!KeySet_P); // 等待按键释放
DelayMs(10); // 消除按键松开的抖动

Sector\_Erase(0x2000); // 保存报警距离
EEPROM\_Write(0x2000,gAlarm/100);
EEPROM\_Write(0x2001,gAlarm%100);
}
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 传感器1报警判断
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
/\*void AlarmJudge1(uint ss)
{
if(ss<gAlarm) // LED灯判断
{
Led1\_P=0;
}
else
{
Led1\_P=1;
}

if((Led2\_P==0)||(Led3\_P==0)||(Led4\_P==0)) // 蜂鸣器判断
{
Buzzer\_P=0;
}
else
{
Buzzer\_P=1;
}
}\*/


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 传感器2报警判断
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void AlarmJudge2(uint ss)
{
if(ss<gAlarm) // LED灯判断
{
Led2_P=0;
}
else
{
Led2_P=1;
}

if((Led2_P==0)||(Led3_P==0)||(Led4_P==0)) // 蜂鸣器判断
{
Buzzer_P=0;
}
else
{
Buzzer_P=1;
}
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 传感器3报警判断
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void AlarmJudge3(uint ss)
{
if(ss<gAlarm) // LED灯判断
{
Led3_P=0;
}
else
{
Led3_P=1;
}

if((Led2_P==0)||(Led3_P==0)||(Led4_P==0)) // 蜂鸣器判断
{
Buzzer_P=0;
}
else
{
Buzzer_P=1;
}
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 传感器4报警判断
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void AlarmJudge4(uint ss)
{
if(ss<gAlarm) // LED灯判断
{
Led4_P=0;
}
else
{
Led4_P=1;
}

if((Led2_P==0)||(Led3_P==0)||(Led4_P==0)) // 蜂鸣器判断
{
Buzzer_P=0;
}
else
{
Buzzer_P=1;
}
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 报警值初始化
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void AlarmInit()
{
gAlarm=EEPROM\_Read(0x2000)\*100+EEPROM\_Read(0x2001); // 从EEPROM读取报警值

if((gAlarm==0)||(gAlarm>400)) // 如果读取到的报警值异常(等于0或大于400则认为异常)
{
gAlarm=25; // 重新赋值报警值为25
}
}


/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
// 主函数
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void main()
{
uchar i; // 循环变量
uint dist; // 保存测量结果

LcdInit(); // 液晶功能初始化
LcdShowInit(); // 液晶显示内容初始化
AlarmInit(); // 报警值初始化

TMOD = 0x01; // 选择定时器0,并且确定是工作方式1(为了超声波模块测量距离计时用的)

//Trig1\_P=0; // 初始化触发引脚为低电平
Trig2_P=0;
Trig3_P=0;
Trig4_P=0;

while(1)
{
/\*传感器1\*/
/\* dist=GetDistance1(); // 读取超声波模块1测量到的距离
LcdGotoXY(0,7); // 光标定位
LcdPrintNum(dist); // 显示传感器1测量到的距离
AlarmJudge1(dist); // 判断传感器1的测量距离是否需要报警

/\*延时并扫描按键\*/
/\* for(i=0;i<15;i++)
{
KeyScanf();
DelayMs(10);
}

/\*传感器2\*/
dist=GetDistance2(); // 读取超声波模块2测量到的距离
LcdGotoXY(0,9); // 光标定位
LcdPrintNum(dist); // 显示传感器2测量到的距离
AlarmJudge2(dist); // 判断传感器2的测量距离是否需要报警

/\*延时并扫描按键\*/
for(i=0;i<15;i++)
{
KeyScanf();
DelayMs(10);
}

/\*传感器3\*/
dist=GetDistance3(); // 读取超声波模块3测量到的距离
LcdGotoXY(1,2); // 光标定位
LcdPrintNum(dist); // 显示传感器3测量到的距离
AlarmJudge3(dist); // 判断传感器3的测量距离是否需要报警

/\*延时并扫描按键\*/
for(i=0;i<15;i++)
{
KeyScanf();
DelayMs(10);
}

/\*传感器4\*/
dist=GetDistance4(); // 读取超声波模块4测量到的距离
LcdGotoXY(0,2); // 光标定位
LcdPrintNum(dist); // 显示传感器4测量到的距离
AlarmJudge4(dist); // 判断传感器4的测量距离是否需要报警

/\*延时并扫描按键\*/
for(i=0;i<15;i++)
{
KeyScanf();
DelayMs(10);
}
}
}

仿真文件和程序代码

1
2
3
链接:https://pan.baidu.com/s/1aDeD32KMzT7B8pw4LLYfmw 
提取码:0snr