簡介
這個小假期被作業支配了,最近這段時間也在忙其他東西,沒時間更新博客了。爲了讓別人知道我還在用,我就把一些瑣碎但花了我時間的東西輸出一下吧!!
介紹
這個是老師的一個小作業,出自郭天祥的《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;
}