【個人筆記】基於單片機的 倒車雷達系統設計 硬件開發(仿真圖、原理圖、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 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM