记录一下单片机大作业,
项目介绍:
我们小组在经过了半个学期的计算机系统设计的学习后,并结合了平时停车场的管理模式,使用C51单片机和各个模块完成了一个停车场的管理系统。该套系统模拟了当汽车进入停车时的收费提示液晶屏,我们这里使用了16个按键来模拟停车位,主要由以下功能:
(1)该系统可以提醒管理员该停车场是否剩余停车位;
(2)当汽车停入汽车位时开始计算停车时间,并显示车位占用量和余量;
(3)当汽车离开停车位时在液晶屏上显示期间该车停车的总时间与停车费,重置车位的状态,并显示车位占用量和余量。
(4)温度传感器测温(一直测温的状态,超过温度的时候响)
使用液晶屏用到的函数调用
流程图:
源码:
复制代码
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#include <reg52.h> #include <intrins.h> #include <stdio.h> #define uchar unsigned char #define uint unsigned int #define LCDDATA P0 sbit led_red = P2^4; //红色led引脚定义 sbit led2_green = P2^3; //绿色led引脚定义 sbit led3_red = P3^4; //火警控制灯 //LCD1602引脚定义 //采用8位并行方式,DB0~DB7连接至LCDDATA0~LCDDATA7 sbit RS=P2^0; //数据指令控制 sbit RW=P2^1; //读写选择(0写1读) sbit CS=P2^2; //使能信号 uchar code KeyCodeTable[]={0x11,0x12,0x14,0x18,0x21,0x22,0x24,0x28,0x41,0x42,0x44,0x48,0x81,0x82,0x84,0x88};// 设定键值 uchar i_,j_; static int a[16]; unsigned int n; static int timeStart[16]; //static int timeStop[16]; 无需此数组 static int timeCount = 0; static uchar timer = 0; static uint temp;//测得温度 sbit buzzer=P3^3;//蜂鸣器引脚 sbit DQ=P3^7;//ds18b20 端口 //功能:延时1毫秒 //说明:当晶振为12M时,j<112;当晶振为11.0592M时,j<122 void Delay_xms(uint x) { uint i,j; for(i=0;i<x;i++) for(j=0;j<112;j++); } //功能:12us延时 //STC89C52为1T单片机,即1个时钟/机器周期,速度为AT89C52的12倍 void Delay_xus(uint t) { for(;t>0;t--) { _nop_(); //_nop_(); 指令的延迟时间为 1us。可以较为精确得控制延迟时间。 } } uchar Keys_Scan() //按键扫描函数 { uchar sCode,kCode,i,k; //定义变量 P1 = 0xf0; //P1口接按键,P1口赋值0xf0表示屏蔽低四位 if((P1&0xf0)!=0xf0) //判断高四位是否有按键按下 { Delay_xus(200); if((P1&0xf0)!=0xf0) //消抖 再判断 { sCode = 0xfe; for(k=0;k<4;k++) { P1 = sCode; if((P1&0xf0)!=0xf0) //判断高四位是否有按键按下 { kCode = ~P1; //将P1口取反后的值赋给变量 for(i=0;i<16;i++) //循环16次进行判断 { if(kCode == KeyCodeTable[i]) //判断变量是数组中的第几个,并返回序号值 return i; } } else sCode = _crol_(sCode,1); //变量左移一位并在左边补1,_cror_代表右移 } } } return -1; //返回无效值 } //定时器的初始化,并开启计时 void Timer0_init(){ TMOD = 0x01; //定时选择模式一 TF0 = 1; //溢出标志位 TR0 = 1; //启动定时器 TH0=0xFC; //定时器高八位 TL0=0x17; //定时器低八位 ET0=1; //51单片机的定时器0允许中断 EA=1; //总中断开关 PT0=0; //中断优先级 } //温度感应初始化 void Init_DS18B20(void) { uchar x=0; DQ = 1; //拉高总线,等待 Delay_xms(8); DQ = 0; //单片机将DQ拉低 Delay_xms(80); //精确延时 大于 480us DQ = 1; //拉高总线,等待 Delay_xms(10); x=DQ; //稍做延时后 如果x=0则初始化成功 x=1则初始化失败 Delay_xms(5); } uchar ReadOneChar(void) // DS18B20读一个字节 { uchar i=0; uchar dat = 0; for (i=8;i>0;i--) { DQ = 0; // 给脉冲信号 dat>>=1; //右移一位 DQ = 1; // 给脉冲信号,主机在读时隙期间必须释放总线 if(DQ) dat|=0x80;//补最高位为1 Delay_xms(5); } return(dat); } /*DS18B20写一个字节*/ void WriteOneChar(uchar dat) //DS18B20写一个字节 { uchar i=0; for (i=8; i>0; i--) { DQ = 0; DQ = dat&0x01;//取最低位 Delay_xms(5); DQ = 1; dat>>=1;//左移 } Delay_xms(5); } /*DS18B20读取温度*/ uint ReadTemperature(void) //DS18B20读取温度 { uchar a=0; uint b=0; uint t=0; Init_DS18B20();//DS18B20初始化 WriteOneChar(0xCC); // 跳过读序号列号的操作 WriteOneChar(0x44); // 启动温度转换 Delay_xms(200); //延时以求信号的稳定 Init_DS18B20(); //DS18B20再次初始化 WriteOneChar(0xCC); //跳过读序号列号的操作 WriteOneChar(0xBE); //读取温度寄存器等(共可读9个寄存器) 前两个就是温度 a=ReadOneChar(); //低位 b=ReadOneChar(); //高位 b<<=8; //b左移8位 t=a+b; //把a与b结合,放在16位的t中 return(t); } //控制LCD写时序 void LCD_en_write(void) { CS=1;//高电平激活,使能信号打开 Delay_xus(20); CS=0;//关闭使能信号 //Delay_xus(200); //每个单元字符显示的时间间隔 } //写指令函数,控制显示位置 void Write_Instruction(uchar command) { RS=0;//数据选择(高电位位置的选择) RW=0; LCDDATA=command; LCD_en_write();//写入指令数据 } //写数据函数 void Write_Data(uchar Wdata) { RS=1; RW=0; LCDDATA=Wdata; LCD_en_write();//写入数据 } //初始地址设置函数 void LCD_SET_XY(uchar Y,uchar X) { uchar address; if(Y==0) address=0x80+X;//Y=0,表示在第一行显示,地址基数为0x80 else address=0xc0+X;//Y非0时,表时在第二行显示,地址基数为0xC0 0x80+0x40 Write_Instruction(address);//写指令,设置显示初始地址 } //写入单片机操作(同时设置地址,以及数值) void LCD_write_char(uchar X,uchar Y,uchar Wdata) { LCD_SET_XY(X,Y);//写地址 Write_Data(Wdata);//写入当前字符并显示 } //清屏函数 void LCD_clear(void) { Write_Instruction(0x01);//清除DDRAM的所有单元(清屏),光标移动到屏幕左上角 Delay_xms(5); //等待一段时间,等待液晶传入指令到寄存器并执行 } //液晶屏初始化函数 void LCD_init(void) { Write_Instruction(0x38); //8位总线 双行显示 5*7点阵(最常用的模式) Delay_xms(15); Write_Instruction(0x01); //清屏 Delay_xms(15); Write_Instruction(0x0C); //开显示,光标、闪烁都关闭 } //设置液晶屏初始值,LCD1602初始化显示“Welcome! My car park” void Display_init(void) { uchar txt1[]="Welcome!"; uchar txt2[]="My car park"; for(i_=4;i_<=11;i_++){ LCD_write_char(0,i_,txt1[i_-4]); } for(i_=3;i_<=13;i_++){ LCD_write_char(1,i_,txt2[i_-3]); } } void Display_page0(){ uchar table[]={"Time:"}; uchar table1[]={"Temprature:"}; for(i_=0;i_<5;i_++){ LCD_write_char(0,i_,table[i_]); } for(i_=0;i_<11;i_++){ LCD_write_char(1,i_,table1[i_]); } } //设置液晶初始显示, //LCD1602显示主界面“The total is:16” //总数量为:16 “Empt:XX”空车位:XX “Full:XX”满车位:XX void Display_page1(void) { uchar txt1[]="The total is:16"; uchar txt2[]="Empt: Full:"; for(i_=0;i_<=14;i_++){ LCD_write_char(0,i_,txt1[i_]); } for(i_=0;i_<=13;i_++){ LCD_write_char(1,i_,txt2[i_]); } } //控制led灯的闪烁 void led_init(void) { led_red=1;led2_green=1; Delay_xms(500); led_red=0;led2_green=0; Delay_xms(500); led_red=1;led2_green=1; Delay_xms(500); led2_green=0; } void main() { unsigned char KeyNO = -1; //定义按键状态标志位 unsigned char k; uchar intime; static uchar i=0,j=0; //i:车位使用数量 j:车位剩余数量 Delay_xms(50); //这里通过测试需要一个缓冲,也就是一个延迟,来保证程序的稳定 LCD_init(); //LCD初始化 LCD_clear(); //清屏 Display_init(); //初始化显示 while(1) { Timer0_init(); KeyNO = Keys_Scan(); //获取当前按钮设置键值 k=KeyNO; if(KeyNO != -1) { for(n=0;n<16;n++){ if(n == k){ a[n]++; if (a[n] == 1) //该按键第一次按下,该车位车入库 { i++; //车位减一 timeStart[n]=timer; //开始收费的时间 led_init(); //指示灯闪烁指示入库成功 temp=ReadTemperature();//读取温度值 temp=temp%100; if(temp>20){ buzzer=1; led3_red=0; }else{ buzzer=0; led3_red=1; } } else if (a[n] == 2) //该按键第二次按下,该车位车出库 { a[n] = 0; //标志复位 i--; //车位加一 //timeStop[n]=timer; //停止收费的时间 LCD_clear(); //intime = timeStop[n]-timeStart[n]; intime = timer - timeStart[n];//获取停的时间 Display_page0(); LCD_write_char(0,13,intime/10+'0'); //在LCD1602上显示已停车位数量的十位 LCD_write_char(0,14,intime%10+'0'); LCD_write_char(1,13,temp/10+'0'); LCD_write_char(1,14,temp%10+'0'); Delay_xms(50); led_init(); //指示灯闪烁指示出库成功 } break; } } if(i==16) {led_red=0;led2_green=1;} //如果车位停满了,则红灯常亮,绿灯熄灭 else{led_red=1;led2_green=0;} //如果车位还有空余,则绿灯常量,红灯熄灭 LCD_clear(); //LCD1602清屏 Display_page1(); //显示界面一 //注意这里需要+‘0’,否则无法显示 LCD_write_char(1,13,i/10+'0'); //在LCD1602上显示已停车位数量的十位 LCD_write_char(1,14,i%10+'0'); //在LCD1602上显示已停车位数量的个位 j=16-i; //计算剩余车位 LCD_write_char(1,5,j/10+'0'); //在LCD1602上显示剩余车位数量的十位 LCD_write_char(1,6,j%10+'0'); //在LCD1602上显示剩余车位数量的个位 } } } //定时器中断 void Timer0_routine() interrupt 1 { TH0=0xD8; TL0=0xEF; timeCount++; if(timeCount>=10000){ timeCount=0; timer++; } }
附上部分资料:
最后感谢小组内各个成员的分工与配合!
最后
以上就是勤奋水壶最近收集整理的关于51单片机大作业 停车场管理系统的全部内容,更多相关51单片机大作业内容请搜索靠谱客的其他文章。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复