#单片机可调节时钟

lcd显示模块

lcd.h文件

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
#ifndef _lcd_H_
#define _lcd_H_

#include <reg51.h>
#include <intrins.h>

#define uchar unsigned char
#define uint unsigned int

// LCD引脚定义
#define LCDDATA P3
sbit RS = P2^0;
sbit RW = P2^1;
sbit E = P2^2;

// 函数声明
void delay(uint j);
void check_busy(void);
void write_command(uchar com);
void write_data(uchar dat);
void lcd_initial(void);
void string(uchar ad,uchar *s);
void lcd_writeCGRAM(void);
void lcd_CG_Disp(void);
void write_sfm(uchar ad, uchar dat);

#endif

lcd.c

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
#include "lcd.h"


// 自定义字符数据(安、工、大)
uchar code agd[] = {
0x04,0x1f,0x11,0x0a,0x1f,0x04,0x1B,0x00, // 安
0x00,0x1f,0x04,0x04,0x04,0x04,0x1f,0x00, // 工
0x04,0x04,0x1f,0x04,0x04,0x0a,0x11,0x00 // 大
};

void delay(uint j) //1ms延时子程序
{
uchar i=250;
for(;j>0;j--)
{
while(--i);
i=249;
while(--i);
i=250;
}
}

void check_busy(void) { //检查忙标志函数
uchar dt;
do
{
LCDDATA =0xff;
E=0;
RS=0;
RW=1;
E=1;
dt= LCDDATA;
}while(dt&0x80);
E=0;
}

void write_command(uchar com) { //写命令函数,写地址命令即移动光标的命令
check_busy();
E=0;
RS=0;
RW=0;
LCDDATA =com;
E=1;
_nop_( );
E=0;
delay(1);
}
void write_data(uchar dat) //写数据函数
{
check_busy();
E=0;
RS=1;
RW=0;
LCDDATA =dat;
E=1;
_nop_();
E=0;
delay(1);
}

void lcd_initial(void) //液晶显示器初始化函数
{
delay(100);
write_command(0x38); //写入命令0x38:8位两行显示,5×7点阵字符
write_command(0x0c); //写入命令0x0C:开整体显示,光标关,无黑块
write_command(0x06); //写入命令0x06:光标右移
write_command(0x01); //写入命令0x01:清屏
delay(1);
}

void string(uchar ad,uchar *s) { //输出显示字符串的函数
write_command(ad);
//定位显示起始位置,第1行:0x80+序号,
//第2行: 0x80+0x40+序号
while(*s>0)
{
write_data(*s++); //输出字符串,且指针增1
delay(1); //字符串以0为结束符
}
}


void lcd_writeCGRAM(void)
{
uchar i;
write_command(0x40+0x00);
//设置自定义字符库地址指针
for (i=0;i<24;i++)
{
write_data(agd[i]); //写数据到CGRAM
}
}

void lcd_CG_Disp(void)
{
write_command(0x80+0x02);
//设定第二行显示,
write_data(0x00); //显示安,在CGRAM中的序号
delay(100);
write_data(0x01); //显示工
delay(100);
write_data(0x02); //显示大
delay(100);
}

void write_sfm(uchar ad, uchar dat)
{
write_command(ad);//确定显示位置
write_data(dat/10%10+0x30);//高位
write_data(dat/1%10+0x30);//低位
} // dat是时、分、秒,不会大于60

时钟调节模块

adjust.h文件

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
#ifndef _adjust_H_
#define _adjust_H_

#include <reg51.h>
#include <intrins.h>
#include <lcd.h>

sbit k1=P1^0;
sbit k2=P1^1;
sbit k3=P1^2;
sbit k4=P1^3;
sbit k5=P1^4;

void keyscan(void);
void adjust_value(bit add_sub);
void move_cursor(void);
void display(void);
extern uchar int_time;
extern uchar second;
extern uchar minute;
extern uchar hour;

extern bit adjust_mode;
extern uchar cursor_pos;
extern bit blink_flag;
extern uchar blink_count;
extern bit time_display;

#endif

adjust.c文件

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
#include "adjust.h"

uchar int_time = 0;
uchar second = 55;
uchar minute = 59;
uchar hour = 23;

bit adjust_mode =0;
uchar cursor_pos = 0;
bit blink_flag = 0;
uchar blink_count = 0;
bit time_display =1;

void keyscan(void) //键盘扫描
{

static bit key_state = 1; //是否按
static uint key_count = 0; //计数
static char pressed_key =0; //键值


if((k1==0)||(k2==0)||(k3==0)||(k4==0)||(k5==0)) //
{
if(key_state)
{
key_state=0;
key_count=0;

if(k1==0) pressed_key=1;
else if(k2==0) pressed_key=2;
else if(k3==0) pressed_key=3;
else if(k4==0) pressed_key=4;
else if(k5==0) pressed_key=5;

}

else
{
key_count++;
if(key_count>=2) //消抖
{
if(key_count>=30) //长按
{
if(key_count%5==0)
{
if(pressed_key==3 && adjust_mode) adjust_value(1);
if(pressed_key==4 && adjust_mode) adjust_value(0);
}
}


}
}
}


else
{
if(!key_state)
{
key_state = 1;
if(key_count > 2 && key_count< 30) //短按
{
switch(pressed_key)
{
case 1:
if(adjust_mode == 0)
{
adjust_mode = 1;
cursor_pos = 0;
blink_flag = 1;
time_display=1;


}
break;

case 2:
if(adjust_mode)
{
move_cursor();
}
break;

case 3:
if(adjust_mode)
{
adjust_value(1);
}
break;

case 4:
if(adjust_mode)
{
adjust_value(0);
}
break;

case 5:
if(adjust_mode)
{
adjust_mode = 0;

}
break;

}

}
pressed_key = 0;
}
key_count = 0;
}
}



void adjust_value(bit add_sub) //调整时分秒
{

uchar *time_var; //指针变量
uchar max_value;



switch(cursor_pos)
{
case 0:
time_var=&hour;
max_value=23;
break;
case 1:
time_var=&minute;
max_value=59;
break;
case 2:
time_var=&second;
max_value=59;
break;
default:
return;
}

if(add_sub)
{
(*time_var)++;
if(*time_var >= max_value) *time_var=0;
}

else
{
if(*time_var==0) *time_var=max_value;
else (*time_var)--; //格式正确
}
}


void move_cursor(void) //光标调整函数
{
cursor_pos++;
if(cursor_pos>2) cursor_pos=0;
}


void display(void)
{

lcd_CG_Disp();
string(0x80 + 0x06,"ZHANG HAO");
string(0xC0 + 0x06,":");
string(0xC0 + 0x09,":");

write_command(0xC0 + 0x01); // 第一行右侧 调试信息
if(adjust_mode)
{
write_data('A'); // Adjust mode
}
else
{
write_data('N'); // Normal mode
write_data(' ');
}

if(blink_flag)
{
time_display= !time_display;
blink_flag=0;
}

if(cursor_pos==0 && !time_display && adjust_mode)
{
write_command(0xC4);
write_data(' ');
write_data(' ');

}
else
{
write_sfm(0xC4,hour);
}

if(cursor_pos==1 && !time_display && adjust_mode)
{
write_command(0xC7);
write_data(' ');
write_data(' ');

}
else
{
write_sfm(0xC7,minute);
}

if(cursor_pos==2 && !time_display && adjust_mode)
{
write_command(0xCA);
write_data(' ');
write_data(' ');

}
else
{
write_sfm(0xCA,second);
}
}

main.c

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
#include <reg51.h>
#include <lcd.h>
#include "adjust.h"

void main()
{
lcd_initial();
lcd_writeCGRAM();

TMOD = 0x01;
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;
EA=1;
ET0=1;
TR0=1;



while(1)
{

display();
}
}


void T0_interserve(void) interrupt 1 using 1
{
TH0=(65536-50000)/256;
TL0=(65536-50000)%256;

blink_count++;
if(blink_count>=6)
{
blink_count=0;
blink_flag=1;
}

int_time++;

if(int_time==20)
{
int_time=0;
if(!adjust_mode)
{
second++;
if(second==60)
{
minute++;
second=0;
if(minute==60)
{
hour++;
minute=0;
if(hour==24) hour=0;

}

}

}

}
keyscan();
}