【个人笔记】基于单片机的 倒车雷达系统设计 硬件开发(仿真图、原理图、PCB图、实物图、C语言程序代码)

 

基于单片机的倒车雷达系统设计

仿真图

 


 

电路图

原理图

 


 

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 }

 

posted @ 2021-11-02 13:36  jianghe414  阅读(3974)  评论(1编辑  收藏  举报