51单片机 DHT11+ DS1302+LCD1602温湿度监测系统

51单片机 DHT11+ DS1302+LCD1602温湿度监测系统


该监测系统实现的主要功能是,当监测到温湿度传感器的数据值超出设定的上下限值时会触发蜂鸣器发声,并且指示灯会亮起。
在这里插入图片描述

  • 本电路包含的主要器件

主控:AT89C51、用于读取时间的DS1302,用于显示的LCD1602,DHT11温湿度传感器,超温报警的蜂鸣器,

主程序代码

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
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
#include "reg52.H"
#include "stdio.h"
#include "intrins.h"
#include <math.h>

#define uchar unsigned char
#define uint unsigned int

#define DB P0//液晶并行数据接口
sbit RS = P2^0;//液晶指令数据信号
sbit RW = P2^1;//液晶读写信号
sbit E = P2^2;//液晶使能信号

sbit T_IO=P1^2; //clk为DS1302的时钟信号线
sbit T_CLK=P1^7; //DAT为DS1302的I/O数据线
sbit T_RST=P2^3; //RST为DS1302的RST信号线

uchar bdata datbyte;
sbit datbyte0=datbyte^0;
sbit datbyte7=datbyte^7;

uchar time_1302[7]={0x00,0x00,0x00,0x03,0x07,0x03,0x08};//设置时间初始值数组
// 秒 分 时 号 月份 星期 年
//DS1302函数声明
void get\_1302(uchar time[]);
void write\_ds1302(uchar dat);
uchar r\_1302(uchar add);
void w\_1302(uchar add,uchar dat);
uchar read\_ds1302(void);
void init\_1302(uchar \*time);
void change();
uchar times[9];//保存时间
uchar date[11];//保存日期

unsigned char key_value;//获取到按键的值

sbit Data=P1^1; //温湿度IO
signed char humi_value;//湿度
signed char temp_value;//温度

unsigned char now_window;//当前显示窗口
unsigned char curr_menu;
#define normal\_mode 0x10//显示模式
#define set\_mode 0x20//设置模式

signed char AlarmTL=10; // 温度下限默认报警值
signed char AlarmTH=30; // 温度上限默认报警值
signed char AlarmHL=40; // 湿度下限默认报警值
signed char AlarmHH=80; // 湿度上限默认报警值

unsigned char i;
unsigned char cnt_100ms,cnt_500ms =0;
unsigned char time_100ms_flag;
//unsigned char open\_del;//开锁成功延时计数
//unsigned char open\_flag;//锁状态标志
sbit beep = P1^0;

sbit LedTL_P = P1^3; // 温度过低报警指示灯
sbit LedTH_P = P1^4; // 温度过高报警指示灯
sbit LedHL_P = P1^5; // 湿度过低报警指示灯
sbit LedHH_P = P1^6; // 湿度过高报警指示灯

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\* 函 数 名 : delay\_ms
\* 函数功能 : 延时函数,延时1ms
\* 输 入 : cnt
\* 输 出 : 无
\* 说 名 : 该函数是在12MHZ晶振下,12分频单片机的延时。
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void delay\_ms(unsigned int cnt) //
{
unsigned int x;
for( ; cnt>0; cnt--)
{
for(x=110; x>0; x--);//软件延时为1MS
}
}
#if 0
void delay\_us(unsigned int cnt) //
{
while(cnt--);
}
#endif
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\*\* 函数名:time\_init
\*\* 描述 :定时器初始化
\*\* 输入 :无
\*\* 输出 :无
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void time\_init(void)
{
TMOD |= 0x01;//time0 工作方式为1
TH0 = 0xf8;//装载初值
TL0 = 0x2f;//装载初值,为2ms(65535-63535)
TR0 = 1;//开启定时器
ET0 = 1;//打开中断
EA=1;
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\*\* 函数名:key\_scan
\*\* 描述 :按键扫描
\*\* 输入 :无
\*\* 输出 :无
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void key\_scan(void)
{
static unsigned char key_in_flag = 0;//按键按下标志
unsigned char key_l;//存储扫描到行列值。
key_value = 20;//按键值清除
if((P3 & 0x0f) != 0x0f)//按键按下
{
delay\_ms(1);//按键消抖动
if(((P3 & 0x0f) != 0x0f) && (key_in_flag == 1))
{
key_in_flag = 0;//松手检测防止一直触发
P3 = 0x0f;
//delay\_ms(1);//按键消抖动
key_l = P3;//扫描得到按键值
switch(key_l)
{
//获取按键值
case 0x0e:
{
key_value = 1;
}
break;
case 0x0d:
{
key_value = 2;
}
break;
case 0x0b:
{
key_value = 3;
}
break;
//case 0x70:
//break;
}
}
}
else
{
key_in_flag = 1;//(按键松开标志)
}

}

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\* 函 数 名 : LcdWriteCom
\* 函数功能 : 向LCD写入一个字节的命令
\* 输 入 : u8com
\* 输 出 : 无
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void lcd\_wri\_com(unsigned char com) //写入命令
{
E = 0; //使能清零
RS = 0; //选择写入命令
RW = 0; //选择写入

DB = com;
delay\_ms(1);

E = 1; //写入时序
delay\_ms(5);
E = 0;
}

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\* 函 数 名 : LcdWriteData
\* 函数功能 : 向LCD写入一个字节的数据
\* 输 入 : u8dat
\* 输 出 : 无
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/

void lcd\_wri\_data(unsigned char dat)//写入数据
{
E = 0; //使能清零
RS = 1; //选择写入数据
RW = 0; //选择写入
DB = dat;
delay\_ms(1);
E = 1; //写入时序
delay\_ms(5);
E = 0;
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\* 函 数 名 : WriString
\* 函数功能 : 刷新屏幕显示
\* 输 入 : hang,add,\*p
\* 输 出 : 无
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void wri\_string(unsigned char y,unsigned char x,unsigned char \*p)
{
if(y==1)//如果选择第一行
lcd\_wri\_com(0x80+x);//选中地址
else
lcd\_wri\_com(0xc0+x);//选中地址
while(\*p)
{
lcd\_wri\_data(\*p);//写入数据
p++;
}
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\* 函 数 名 : lcd\_write\_char
\* 函数功能 :
\* 输 入 :
\* 输 出 : 无
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void lcd\_write\_char(unsigned char y, unsigned char x, unsigned char dat) //列x=0~15,行y=0,1
{
unsigned char temp_l, temp_h;
if(y==1)//如果选择第一行
lcd\_wri\_com(0x80+x);//选中地址
else
lcd\_wri\_com(0xc0+x);//选中地址
temp_l = dat % 10;
temp_h = dat / 10;
lcd\_wri\_data(temp_h + 0x30); //convert to ascii
lcd\_wri\_data(temp_l + 0x30);
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*光标控制\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void lcd1602\_guanbiao(unsigned char y, unsigned char x,unsigned char on_off)
{
if(on_off == 1) //开光标
{
if(y==1)//如果选择第一行
lcd\_wri\_com(0x80+x);
else
lcd\_wri\_com(0xc0+x);//将光标移动到秒个位
lcd\_wri\_com(0x0f);//显示光标并且闪烁
}
else
{
if(y==1)//如果选择第一行
lcd\_wri\_com(0x80+x);
else
lcd\_wri\_com(0xc0+x);//将光标移动到秒个位
lcd\_wri\_com(0x0c); //关光标
}
}

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\* 函 数 名 : LcdInit()
\* 函数功能 : 初始化LCD屏
\* 输 入 : 无
\* 输 出 : 无
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void lcd\_init(void) //LCD初始化子程序
{
lcd\_wri\_com(0x38);//置功能8位双行
lcd\_wri\_com(0x0c);//显示开关光标
lcd\_wri\_com(0x06);//字符进入模式屏幕不动字符后移
delay\_ms(5);//延时5ms
lcd\_wri\_com(0x01); //清屏
wri\_string(1,0,times);//初始化显示
wri\_string(1,6,date);
wri\_string(2,0,"H: %RH T: C ");//初始化显示
}
void DHT11\_delay\_us(unsigned char n)
{
while(--n);
}

void DHT11\_delay\_ms(unsigned int z)
{
unsigned int i,j;
for(i=z;i>0;i--)
for(j=110;j>0;j--);
}

void DHT11\_start()
{
Data=1;
DHT11\_delay\_us(2);
Data=0;
DHT11\_delay\_ms(30); //延时18ms以上
Data=1;
DHT11\_delay\_us(30);
}

unsigned char DHT11\_rec\_byte() //接收一个字节
{
unsigned char i,dat=0;
for(i=0;i<8;i++) //从高到低依次接收8位数据
{
while(!Data); 等待50us低电平过去
DHT11\_delay\_us(8); //延时60us,如果还为高则数据为1,否则为0
dat<<=1; //移位使正确接收8位数据,数据为0时直接移位
if(Data==1) //数据为1时,使dat加1来接收数据1
dat+=1;
while(Data); //等待数据线拉低
}
return dat;
}

void DHT11\_receive() //接收40位的数据
{
unsigned char R_H,R_L,T_H,T_L,RH,RL,TH,TL,revise;
DHT11\_start();
if(Data==0)
{
while(Data==0); //等待拉高
DHT11\_delay\_us(40); //拉高后延时80us
R_H=DHT11\_rec\_byte(); //接收湿度高八位
R_L=DHT11\_rec\_byte(); //接收湿度低八位
T_H=DHT11\_rec\_byte(); //接收温度高八位
T_L=DHT11\_rec\_byte(); //接收温度低八位
revise=DHT11\_rec\_byte(); //接收校正位

DHT11\_delay\_us(25); //结束

if((R_H+R_L+T_H+T_L)==revise) //校正
{
RH=R_H;
RL=R_L;
TH=T_H;
TL=T_L;
}
humi_value = RH;
temp_value = TH;
}
}


void AlarmJudge(void)
{
if(temp_value>AlarmTH)// 温度是否过高
{
LedTH_P=0;
LedTL_P=1;
}
else if(temp_value<AlarmTL)// 温度是否过低
{
LedTL_P=0;
LedTH_P=1;
}
else// 温度正常
{
LedTH_P=1;
LedTL_P=1;
}

if(humi_value>AlarmHH)// 湿度是否过高
{
LedHH_P=0;
LedHL_P=1;
}
else if(humi_value<AlarmHL) // 湿度是否过低
{
LedHL_P=0;
LedHH_P=1;
}
else // 湿度正常
{
LedHH_P=1;
LedHL_P=1;
}

if((LedHH_P==0)||(LedHL_P==0)||(LedTH_P==0)||(LedTL_P==0)) // 蜂鸣器判断,只要至少1个报警灯亮,蜂鸣器就报警
{
for(i=0;i<3;i++)
{
beep=0;
delay\_ms(20);
beep=1;
delay\_ms(20);
}
}
}

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\*\* 函数名:key\_service
\*\* 描述 :按键服务函数
\*\* 输入 :无
\*\* 输出 :无
\*\* 调用 :主程序
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void key\_service(void)
{
switch (now_window)
{
case normal_mode:
{
if (key_value == 1)
{
now_window = set_mode;
curr_menu = 0;
wri\_string(1,0,"T: - ");//初始化显示
wri\_string(2,0,"H: - ");//初始化显示
lcd\_write\_char(1,2,AlarmTL);
lcd\_write\_char(1,6,AlarmTH);
lcd\_write\_char(2,2,AlarmHL);
lcd\_write\_char(2,6,AlarmHH);
lcd1602\_guanbiao(1,3,1);
}
}
break;
case set_mode:
{
if (key_value == 1)
{
++curr_menu;
if (curr_menu==1)
{
lcd1602\_guanbiao(1,7,1);
}
else if(curr_menu==2)
{
lcd1602\_guanbiao(2,3,1);
}
else if(curr_menu==3)
{
lcd1602\_guanbiao(2,7,1);
}
if(curr_menu>3)
{
curr_menu = 0;
lcd1602\_guanbiao(2,7,0);
now_window = normal_mode;
wri\_string(1,0,times);//初始化显示
wri\_string(1,6,date);
wri\_string(2,0,"H: %RH T: C ");//初始化显示
lcd\_write\_char(2,2,humi_value);
lcd\_write\_char(2,11,temp_value);
lcd\_wri\_com(0xcd);
lcd\_wri\_data(0xdf);
}
}
if (key_value == 2)
{
if(curr_menu==0)
{
if(++AlarmTL>99)
{
AlarmTL = 0;
}
lcd\_write\_char(1,2,AlarmTL);
lcd1602\_guanbiao(1,3,1);
}
else if (curr_menu==1)
{
if(++AlarmTH>99)
{
AlarmTH = 0;
}
lcd\_write\_char(1,6,AlarmTH);
lcd1602\_guanbiao(1,7,1);
}
else if(curr_menu==2)
{
if(++AlarmHL>99)
{
AlarmHL = 0;
}
lcd\_write\_char(2,2,AlarmHL);
lcd1602\_guanbiao(2,3,1);
}
else if(curr_menu==3)
{
if(++AlarmHH>99)
{
AlarmHH = 0;
}
lcd\_write\_char(2,6,AlarmHH);
lcd1602\_guanbiao(2,7,1);
}
}
if (key_value == 3)
{
if(curr_menu==0)
{
if(--AlarmTL<0)
{
AlarmTL = 99;
}
lcd\_write\_char(1,2,AlarmTL);
lcd1602\_guanbiao(1,3,1);
}
else if (curr_menu==1)
{
if(--AlarmTH<0)
{
AlarmTH = 99;
}
lcd\_write\_char(1,6,AlarmTH);
lcd1602\_guanbiao(1,7,1);
}
else if(curr_menu==2)
{
if(--AlarmHL<0)
{
AlarmHL = 99;
}
lcd\_write\_char(2,2,AlarmHL);
lcd1602\_guanbiao(2,3,1);
}
else if(curr_menu==3)
{
if(--AlarmHH<0)
{
AlarmHH = 99;

}
lcd\_write\_char(2,6,AlarmHH);
lcd1602\_guanbiao(2,7,1);
}
}
}
break;
}
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\*\* 函数名:超温报警函数
\*\* 描述 :定时闪烁函数
\*\* 输入 : 无
\*\* 输出 :无
\*\* 调用 :中断调用
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void time\_service(void)
{
if(time_100ms_flag)
{
time_100ms_flag = 0;
if (++cnt_500ms>5)
{
cnt_500ms = 0;
if(now_window == normal_mode)
{
EA = 0;
DHT11\_receive();
EA = 1;
lcd\_write\_char(2,2,humi_value);
lcd\_write\_char(2,11,temp_value);
AlarmJudge();//报警函数
}
}

}

}

/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\*\* 函数名:init\_all\_hardware
\*\* 描述 :初始化所有硬件,及其变量参数。
\*\* 输入 :无
\*\* 输出 :无
\*\* 调用 :主程序
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void init\_all\_hardware(void)
{

time\_init();//定时器初始化
lcd\_init();
lcd\_write\_char(2,2,humi_value);
lcd\_write\_char(2,11,temp_value);
lcd\_wri\_com(0xcd);
lcd\_wri\_data(0xdf);
key_value = 20;
now_window = normal_mode;
cnt_100ms = 0;
time_100ms_flag = 0;
curr_menu = 0;
}
void main(void)
{
get\_1302(time_1302);//获取时间
change(); //时间转换
init\_all\_hardware();//初始化硬件,IO和定时器
while(1)
{
get\_1302(time_1302);//获取时间
change(); //时间转换
key\_scan();//按键扫描
key\_service();//按键服务处理函数
time\_service();//时间处理函数
}
}
/\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*
\*\* 函数名:time0\_interrupt
\*\* 描述 :按键扫描函数
\*\* 输入 :无
\*\* 输出 :无
\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*/
void time0\_interrupt() interrupt 1
{
TF0 = 0;//清除标志
TR0 = 0;
if (++cnt_100ms>50)
{
cnt_100ms = 0;
time_100ms_flag = 1;
}
TR0 = 1;
TH0 = 0xf8;
TL0 = 0x2f;//装载初值2ms(65535-63535)
}


//DS1302相关函数
/\*==========================================
D S 1 3 0 2 初 始 化
===========================================\*/

void init\_1302(uchar \*time)
{uchar i, add;
//uchar time\_bcd[7];
add=0x80;//0写入,1读出
w\_1302(0x8e,0x00);
for(i=0;i<7;i++)
{w\_1302(add,\*time);
add+=2;
time++;
}
w\_1302(0x8e,0x80);
}

//===========================
// 读取当前时间
//===========================

void get\_1302(uchar time[])
{uchar i;
uchar add=0x81;
w\_1302(0x8e,0x00);
for(i=0;i<7;i++)
{
time[i]=r\_1302(add);
add+=2;
}
w\_1302(0x8e,0x80);
}
/\*=================================
DS1302写入一个字节(上升沿有效)
=================================\*/

void write\_ds1302(uchar dat)
{uchar i;
datbyte=dat;
for(i=0;i<8;i++)
{T_IO=datbyte0;
T_CLK=1;
T_CLK=0;
datbyte=datbyte>>1;
}
}

/\*=======================================
DS1302读取一个字节(下降沿有效)
=======================================\*/

uchar read\_ds1302(void)
{uchar i;

for(i=0;i<8;i++)
{datbyte=datbyte>>1;
datbyte7=T_IO;
T_CLK=1;
T_CLK=0;
}
return(datbyte);
}

/\*=========================================
指定位置读取数据
=========================================\*/

uchar r\_1302(uchar add)
{uchar temp,dat1,dat2;
T_RST=0;
T_CLK=0;
T_RST=1;
write\_ds1302(add);
temp=read\_ds1302();
T_CLK=1;
T_RST=0;
dat1=temp/16;
dat2=temp%16;
temp=dat1\*10+dat2;
return(temp);
}

/\*==========================================
指定位置写入数据
==========================================\*/

void w\_1302(uchar add,uchar dat)
{
T_RST=0;
T_CLK=0;
T_RST=1;
write\_ds1302(add);
write\_ds1302(dat/10<<4|dat%10);
T_CLK=1;
T_RST=0;
}
//DS1302数值转换
void change()
{
// 时 间 的 转 换
times[0]=time_1302[2]/10+'0';
times[1]=time_1302[2]%10+'0';
times[2]=':';
times[3]=time_1302[1]/10+'0';
times[4]=time_1302[1]%10+'0';
// times[5]=':';
// times[6]=time\_1302[0]/10+'0';
// times[7]=time\_1302[0]%10+'0';
times[5]='\0';
// 日 期 的 转 换
date[0]='2';
date[1]='0';
date[2]=time_1302[6]/10+'0';
date[3]=time_1302[6]%10+'0';
date[4]='/';
date[5]=time_1302[4]/10+'0';
date[6]=time_1302[4]%10+'0';
date[7]='/';
date[8]=time_1302[3]/10+'0';
date[9]=time_1302[3]%10+'0';
date[10]='\0';
}

程序源码和仿真资源

1
2
3
链接:https://pan.baidu.com/s/1kDU3q0mhIuVC72\_2CqBjsw 
提取码:vcij