基于单片机的倒车雷达系统设计
仿真图
![]()
电路图
原理图
![]()
PCB图
![]()
实物图
![]()
C程序
1 #include <reg52.h>
2 #include <intrins.h>
3
4 #define uchar unsigned char // 以后unsigned char就可以用uchar代替
5 #define uint unsigned int // 以后unsigned int 就可以用uint 代替
6
7 sfr ISP_DATA = 0xe2; // 数据寄存器
8 sfr ISP_ADDRH = 0xe3; // 地址寄存器高八位
9 sfr ISP_ADDRL = 0xe4; // 地址寄存器低八位
10 sfr ISP_CMD = 0xe5; // 命令寄存器
11 sfr ISP_TRIG = 0xe6; // 命令触发寄存器
12 sfr ISP_CONTR = 0xe7; // 命令寄存器
13
14 sbit LcdRs_P = P1^1; // 1602液晶的RS管脚
15 sbit LcdRw_P = P1^2; // 1602液晶的RW管脚
16 sbit LcdEn_P = P1^3; // 1602液晶的EN管脚
17
18 sbit Trig1_P = P3^2; // 超声波模块1的Trig管脚
19 sbit Echo1_P = P3^3; // 超声波模块1的Echo管脚
20
21 sbit KeySet_P = P2^2; // 设置按键的管脚
22 sbit KeyDown_P = P2^1; // 减按键的管脚
23 sbit KeyUp_P = P2^0; // 加按键的管脚
24
25 sbit Buzzer_P = P2^3; // 蜂鸣器的管脚
26 sbit Led1_P = P3^4; // 传感器1报警灯
27
28 uint gAlarm; // 报警距离变量
29
30
31
32 /*********************************************************/
33 // 单片机内部EEPROM不使能
34 /*********************************************************/
35 void ISP_Disable()
36 {
37 ISP_CONTR = 0;
38 ISP_ADDRH = 0;
39 ISP_ADDRL = 0;
40 }
41
42
43 /*********************************************************/
44 // 从单片机内部EEPROM读一个字节,从0x2000地址开始
45 /*********************************************************/
46 unsigned char EEPROM_Read(unsigned int add)
47 {
48 ISP_DATA = 0x00;
49 ISP_CONTR = 0x83;
50 ISP_CMD = 0x01;
51 ISP_ADDRH = (unsigned char)(add>>8);
52 ISP_ADDRL = (unsigned char)(add&0xff);
53 // 对STC89C51系列来说,每次要写入0x46,再写入0xB9,ISP/IAP才会生效
54 ISP_TRIG = 0x46;
55 ISP_TRIG = 0xB9;
56 _nop_();
57 ISP_Disable();
58 return (ISP_DATA);
59 }
60
61
62 /*********************************************************/
63 // 往单片机内部EEPROM写一个字节,从0x2000地址开始
64 /*********************************************************/
65 void EEPROM_Write(unsigned int add,unsigned char ch)
66 {
67 ISP_CONTR = 0x83;
68 ISP_CMD = 0x02;
69 ISP_ADDRH = (unsigned char)(add>>8);
70 ISP_ADDRL = (unsigned char)(add&0xff);
71 ISP_DATA = ch;
72 ISP_TRIG = 0x46;
73 ISP_TRIG = 0xB9;
74 _nop_();
75 ISP_Disable();
76 }
77
78
79 /*********************************************************/
80 // 擦除单片机内部EEPROM的一个扇区
81 // 写8个扇区中随便一个的地址,便擦除该扇区,写入前要先擦除
82 /*********************************************************/
83 void Sector_Erase(unsigned int add)
84 {
85 ISP_CONTR = 0x83;
86 ISP_CMD = 0x03;
87 ISP_ADDRH = (unsigned char)(add>>8);
88 ISP_ADDRL = (unsigned char)(add&0xff);
89 ISP_TRIG = 0x46;
90 ISP_TRIG = 0xB9;
91 _nop_();
92 ISP_Disable();
93 }
94
95
96
97 /*********************************************************/
98 // 毫秒级的延时函数,time是要延时的毫秒数
99 /*********************************************************/
100 void DelayMs(uint time)
101 {
102 uint i,j;
103 for(i=0;i<time;i++)
104 for(j=0;j<112;j++);
105 }
106
107
108 /*********************************************************/
109 // 1602液晶写命令函数,cmd就是要写入的命令
110 /*********************************************************/
111 void LcdWriteCmd(uchar cmd)
112 {
113 LcdRs_P = 0;
114 LcdRw_P = 0;
115 LcdEn_P = 0;
116 P0=cmd;
117 DelayMs(2);
118 LcdEn_P = 1;
119 DelayMs(2);
120 LcdEn_P = 0;
121 }
122
123
124 /*********************************************************/
125 // 1602液晶写数据函数,dat就是要写入的数据
126 /*********************************************************/
127 void LcdWriteData(uchar dat)
128 {
129 LcdRs_P = 1;
130 LcdRw_P = 0;
131 LcdEn_P = 0;
132 P0=dat;
133 DelayMs(2);
134 LcdEn_P = 1;
135 DelayMs(2);
136 LcdEn_P = 0;
137 }
138
139
140 /*********************************************************/
141 // 液晶光标定位函数
142 /*********************************************************/
143 void LcdGotoXY(uchar line,uchar column)
144 {
145 // 第一行
146 if(line==0)
147 LcdWriteCmd(0x80+column);
148 // 第二行
149 if(line==1)
150 LcdWriteCmd(0x80+0x40+column);
151 }
152
153
154
155 /*********************************************************/
156 // 液晶输出字符串函数
157 /*********************************************************/
158 void LcdPrintStr(uchar *str)
159 {
160 while(*str!='\0')
161 LcdWriteData(*str++);
162 }
163
164
165 /*********************************************************/
166 // 液晶输出数字
167 /*********************************************************/
168 void LcdPrintNum(uint num)
169 {
170 LcdWriteData(num/100+0x30); // 百位
171 LcdWriteData(num%100/10+0x30); // 十位
172 LcdWriteData(num%10+0x30); // 个位
173 }
174
175
176 /*********************************************************/
177 // 1602液晶功能初始化
178 /*********************************************************/
179 void LcdInit()
180 {
181 LcdWriteCmd(0x38); // 16*2显示,5*7点阵,8位数据口
182 LcdWriteCmd(0x0C); // 开显示,不显示光标
183 LcdWriteCmd(0x06); // 地址加1,当写入数据后光标右移
184 LcdWriteCmd(0x01); // 清屏
185 }
186
187
188
189 /*********************************************************/
190 // 1602液晶显示内容初始化
191 /*********************************************************/
192 void LcdShowInit()
193 {
194 LcdGotoXY(0,0); // 定位到第0行第0列
195 LcdPrintStr("D: cm "); // 第0行显示"D: "
196 }
197
198
199 /*********************************************************/
200 // 计算传感器1测量到的距离
201 /*********************************************************/
202
203 uint GetDistance1(void)
204 {
205 uint ss; // 用于记录测得的距离
206
207 TH0=0;
208 TL0=0;
209
210 Trig1_P=1; // 给超声波模块1一个开始脉冲
211 DelayMs(1);
212 Trig1_P=0;
213
214 while(!Echo1_P); // 等待超声波模块1的返回脉冲
215 TR0=1; // 启动定时器,开始计时
216 while(Echo1_P); // 等待超声波模块1的返回脉冲结束
217 TR0=0; // 停止定时器,停止计时
218
219 ss=((TH0*256+TL0)*0.034)/2; // 距离cm=(时间us * 速度cm/us)/2
220 return ss;
221 }
222
223 /*********************************************************/
224 // 按键扫描
225 /*********************************************************/
226 void KeyScanf()
227 {
228 if(KeySet_P==0) // 判断是否有按键按下
229 {
230 LcdGotoXY(0,0); // 光标定位
231 LcdPrintStr(" Alarm Set "); // 第0行显示“ Alarm Set ”
232 LcdGotoXY(1,0); // 光标定位
233 LcdPrintStr(" alarm= cm "); // 第1行显示“ alarm= cm ”
234 LcdGotoXY(1,8); // 光标定位
235 LcdPrintNum(gAlarm); // 显示当前的报警值
236
237 DelayMs(10); // 消除按键按下的抖动
238 while(!KeySet_P); // 等待按键释放
239 DelayMs(10); // 消除按键松开的抖动
240
241 while(1)
242 {
243 /* 报警值减的处理 */
244 if(KeyDown_P==0)
245 {
246 if(gAlarm>2) // 报警值大于2才能减1
247 gAlarm--; // 报警值减1
248 LcdGotoXY(1,8); // 光标定位
249 LcdPrintNum(gAlarm); // 刷新修改后的报警值
250 DelayMs(300); // 延时
251 }
252
253 /* 报警值加的处理 */
254 if(KeyUp_P==0)
255 {
256 if(gAlarm<400) // 报警值小于400才能加1
257 gAlarm++; // 报警值加1
258 LcdGotoXY(1,8); // 光标定位
259 LcdPrintNum(gAlarm); // 刷新修改后的报警值
260 DelayMs(300); // 延时
261 }
262
263 /* 退出报警值设置 */
264 if(KeySet_P==0)
265 {
266 break; // 退出while循环
267 }
268 }
269
270 LcdShowInit(); // 液晶恢复测量到测量界面
271 DelayMs(10); // 消除按键按下的抖动
272 while(!KeySet_P); // 等待按键释放
273 DelayMs(10); // 消除按键松开的抖动
274
275 Sector_Erase(0x2000); // 保存报警距离
276 EEPROM_Write(0x2000,gAlarm/100);
277 EEPROM_Write(0x2001,gAlarm%100);
278 }
279 }
280
281
282 /*********************************************************/
283 // 传感器1报警判断
284 /*********************************************************/
285 void AlarmJudge1(uint ss)
286 {
287
288 if(ss<gAlarm) // LED灯判断
289 {
290 Led1_P=0;
291 Buzzer_P=1;
292 DelayMs(10);
293 Buzzer_P=0;
294 DelayMs(10);
295 }
296 else
297 {
298 Led1_P=1;
299 Buzzer_P=0;
300 }
301
302
303 }
304
305 /*********************************************************/
306 // 报警值初始化
307 /*********************************************************/
308 void AlarmInit()
309 {
310 gAlarm=EEPROM_Read(0x2000)*100+EEPROM_Read(0x2001); // 从EEPROM读取报警值
311
312 if((gAlarm==0)||(gAlarm>400)) // 如果读取到的报警值异常(等于0或大于400则认为异常)
313 {
314 gAlarm=15; // 重新赋值报警值为15
315 }
316 }
317
318
319 /*********************************************************/
320 // 主函数
321 /*********************************************************/
322 void main()
323 {
324 uchar i; // 循环变量
325 uint dist; // 保存测量结果
326
327 LcdInit(); // 液晶功能初始化
328 LcdShowInit(); // 液晶显示内容初始化
329 AlarmInit(); // 报警值初始化
330
331 TMOD = 0x01; // 选择定时器0,并且确定是工作方式1(为了超声波模块测量距离计时用的)
332
333 Trig1_P=0; // 初始化触发引脚为低电平
334
335 while(1)
336 {
337 /*传感器1*/
338 dist=GetDistance1(); // 读取超声波模块1测量到的距离
339 LcdGotoXY(0,7); // 光标定位
340 LcdPrintNum(dist); // 显示传感器1测量到的距离
341 AlarmJudge1(dist); // 判断传感器1的测量距离是否需要报警
342
343 /*延时并扫描按键*/
344 for(i=0;i<15;i++)
345 {
346 KeyScanf();
347 DelayMs(10);
348 }
349
350
351 }
352 }