简介
这个小假期被作业支配了,最近这段时间也在忙其他东西,没时间更新博客了。为了让别人知道我还在用,我就把一些琐碎但花了我时间的东西输出一下吧!!
介绍
这个是老师的一个小作业,出自郭天祥的《51单片机》第一版第14章。里面介绍了一个使用定时器设计的时钟。现加入更多功能。
功能
- 支持矩阵键盘直接修改
书上只能增加或减少,但这里可以用键盘直接改 - 支持光标到每个数位的切换
书上只能切换到某两位 - 支持闹钟设置
设置闹钟后,当到达指定时间会铃响5s。
演示
注意问题
设计过程中遇到的一些bug。
多文件结构
-
头文件只声明变量和函数,在c文件定义和实现函数
声明时内存未开辟空间,定义后变量才真正拥有空间 -
防止头文件的重复包含以及变量的重复定义
这里重复是指文件和变量在同一个源文件被包含两次以上,而不是被多个源文件包含文件和变量。
使用以下方式可以很方便避免重复:
#ifndef ...
#define ...
#endif
结构体
-
c51的结构体不能带有函数
本人在b站看了个c++视频说结构体和类是基本类似的,它也举了个例子在里面定义函数,然后我也在c51照做gg。 -
Error: different struct/union
这个bug就是说存在另一个结构体/联合体符合这种情况,也就是你现在的操作是你这个结构体所不能操作的,比如取里面没有的成员。
AT24C02 仿真时序
- 注意AT24C02的数据写时间
这里显示这个器件写数据的时间需要1ms,因此在写数据停止信号后要留够一定时间来写数据。如:void e2p_write_data(u8 addr, u8 dat) { u8 com = 0xa0; e2p_start(); e2p_write_byte(com); e2p_at_ack(); e2p_write_byte(addr); e2p_at_ack(); e2p_write_byte(dat); e2p_at_ack(); e2p_stop(); e2p_delayms(1); //留1ms }
主要代码
完整代码见github
void keyscan()
{
u8 i, j, tmp;
u16 cnt = 0;
for(i=0; i<2; i++)
{
P1 = ~(0x01 << i);
tmp = 0x10;
for(j=0; j<4; j++)
{
tmp = (~(0x10 << j)) & 0xf0;
if((P1 & 0xf0) == tmp)
{
delayms(5);
if((P1 & 0xf0) == tmp)
{
beep = 1;
if(time.time_sta[0] | time.time_sta[1]) //set cur_time 0~7
{
time.time6[time.time_pos] = j + i*4;
write_sfm(time6_lcd[time.time_pos], j + i*4);
}
}
while((P1 & 0xf0) == tmp);
beep = 0;
}
}
}
P1 = 0xfb;
delayms(1);
for(j=0; j<2; j++)
{
tmp = (~(0x10 << j)) & 0xf0;
if((P1 & 0xf0) == tmp)
{
delayms(5);
if((P1 & 0xf0) == tmp)
{
beep = 1;
if(time.time_sta[0] | time.time_sta[1]) //set cur_time 8~9
{
time.time6[time.time_pos] = j + 8;
write_sfm(time6_lcd[time.time_pos], j+8);
}
}
while((P1 & 0xf0) == tmp);
beep = 0;
}
}
switch(P1 & 0xf0) // ??1??
{
case 0xb0:
{
delayms(5);
if((P1 & 0xf0) == 0xb0)
{
beep = 1;
if(time.time_sta[0] || time.time_sta[1])
{
tmp = (time.time6[time.time_pos] < 9 ? ++time.time6[time.time_pos]
: time.time6[time.time_pos]);
write_sfm(time6_lcd[time.time_pos], tmp);
}
}
while((P1 & 0xf0) == 0xb0);
beep = 0;
break;
}
case 0x70:
{
delayms(5);
if((P1 & 0xf0) == 0x70)
{
beep = 1;
if(time.time_sta[0] || time.time_sta[1])
{
tmp = (time.time6[time.time_pos] > 0 ? --time.time6[time.time_pos]
: time.time6[time.time_pos]);
write_sfm(time6_lcd[time.time_pos], tmp);
}
}
while((P1 & 0xf0) == 0x70);
beep = 0;
break;
}
}
P1 = 0xf7;
delayms(1);
switch(P1 & 0xf0)
{
case 0xe0: //change position
{
delayms(5);
if((P1 & 0xf0) == 0xe0)
{
beep = 1;
if(time.time_sta[0] | time.time_sta[1])
time.time_pos = (time.time_pos + 1) % 6;
lcd_write_com(0x0c);
lcd_write_com(0x80 + 0x40 + time6_lcd[time.time_pos]);
lcd_write_com(0x0f);
}
while((P1 & 0xf0) == 0xe0);
beep = 0;
break;
}
case 0xd0:
{
delayms(5);
if((P1 & 0xf0) == 0xd0)
{
beep = 1;
if(time.time_sta[0] | time.time_sta[1])
time.time_pos = ((--time.time_pos) < 0 ? 5 : time.time_pos);
lcd_write_com(0x0c);
lcd_write_com(0x80 + 0x40 + time6_lcd[time.time_pos]);
lcd_write_com(0x0f);
}
while((P1 & 0xf0) == 0xd0);
beep = 0;
break;
}
case 0xb0: //funtion key 1: set time
{
delayms(5);
if((P1 & 0xf0) == 0xb0)
{
beep = 1;
if(time.time_sta[1] == 0)
{
while((P1 & 0xf0) == 0xb0)
{
delayms(1);
cnt++;
if(cnt >= 1000) key1_1s = 1;
}
key1_1s = 0;
if(time.time_sta[0])
{
time.time_sta[0] = 0;
time.time_pos = 5;
lcd_write_com(0x0c);
if(cnt < 1000) //press 1
time6_time(&time.cur_time, time.time6); // count time
TR0 = 1;
}
else
{
TR0 = 0;
time_time6(time.cur_time, time.time6);
time.time_sta[0]++;
lcd_write_com(0x80 + 0x40 + time6_lcd[time.time_pos]);
lcd_write_com(0x0f);
}
}
beep = 0;
}
break;
}
case 0x70: //function key2 : set clock
{
delayms(5);
if((P1 & 0xf0) == 0x70)
{
beep = 1;
if(time.time_sta[0] == 0)
{
while((P1 & 0xf0) == 0x70)
{
delayms(1);
cnt++;
if(cnt > 1000)
key2_1s = 1;
if(cnt > 3000)
key2_3s = 1;
}
key2_1s = 0;
key2_3s = 0;
if(cnt > 3000) //press very long --> activate or deactivate clock
{
time.clock_act = (~time.clock_act) & 0x01;
if(time.clock_act)
lcd_write_str(2, 10, on);
else
lcd_write_str(2, 10, off);
time.time_sta[1] = 0;
time.time_pos = 5;
lcd_write_com(0x0c);
TR0 = 1;
}
else
{
if(time.time_sta[1]) //reset and count
{
time.time_sta[1] = 0;
time.time_pos = 5;
lcd_write_com(0x0c);
if(cnt < 1000) //press last for 1s, cansel set time
time6_time(&time.clo_time, time.time6);
TR0 = 1;
}
else
{
TR0 = 0;
time_time6(time.cur_time, time.time6);
time.time_sta[1]++;
lcd_write_com(0x80 + 0x40 + time6_lcd[time.time_pos]);
lcd_write_com(0x0f);
}
}
}
beep = 0;
}
break;
}
}
}
//------------------------------------------------------------
//-----------------------------main----------------------------
void main()
{
u8 first_time;
u8 beeptime = 100; //10s
u8 code date[] = "2020-4-3 Fri";
beep = 0;
key1_1s = 0;
key2_1s = 0;
key2_3s = 0;
lcd_init();
e2p_init();
lcd_write_str(1,2,date);
lcd_write_str(2, 10, off);
first_time = e2p_read_data(0);
if(first_time != 'a')
{
e2p_write_data(0, 'a');
e2p_write_data(1, time.cur_time.hour);
e2p_write_data(2, time.cur_time.min);
e2p_write_data(3, time.cur_time.sec);
}
else
{
time.cur_time.hour = e2p_read_data(1);
time.cur_time.min = e2p_read_data(2);
time.cur_time.sec = e2p_read_data(3);
}
write_time(time.cur_time);
configTimer0(50);
while(1)
{
keyscan();
if(time.clock_act)
{
if((time.cur_time.hour == time.clo_time.hour)
&& (time.cur_time.min == time.clo_time.min)
&& (time.cur_time.sec == time.clo_time.sec))
{
TR0 = 0;
beep = 1;
while(beeptime--) delayms(50);
beep = 0;
beeptime = 100;
TR0 = 1;
time.clock_act = 0;
lcd_write_str(2, 10, off);
}
}
}
}
void int0() interrupt 1
{
static u8 cnt = 0;
if(++cnt == 20) //1s
{
cnt = 0;
time.cur_time.sec++;
e2p_write_data(3,time.cur_time.sec);
if(time.cur_time.sec >= 60)
{
time.cur_time.sec = 0;
time.cur_time.min++;
if(time.cur_time.min >= 60)
{
time.cur_time.min = 0;
time.cur_time.hour++;
if(time.cur_time.hour >= 24)
time.cur_time.hour = 0;
e2p_write_data(1, time.cur_time.hour);
}
e2p_write_data(2, time.cur_time.min);
}
write_time(time.cur_time);
}
TH0 = th0;
TL0 = tl0;
}