📄 clock.c
字号:
/* 定时器,可以设置小时和分钟; 可以设置开始时间,和结束时间,在P3.7口输出变化情况(opto=0xFF P3.7=1, opto=0x7F P3.7=0)*/#include <reg52.h> #include <stdio.h> unsigned char sec100,sec,min,hour,day,month,flag1,temp,opto;unsigned char digit,buffer[4],onHour1,onMin1,offHour1,offMin1;char cputick,key,delay,count1;char keyflag, showdelay;unsigned char showsave;//char convert[10] = {0x3F,0x0c,0x76,0x5e,0x4d,0x5b,0x7b,0x0e,0x7f,0x5f};// 数码管的编码,需要取反输出0-9char convert[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7D, 0x07, 0x7F, 0x6F};// 各个月的天数char days[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};void pause(int); void scanLED();void manualOnOff();void savetimeOnOff1(); void setmin();void sethour();void setonHour();void setonMin();void setoffHour();void setoffMin();void setday();void setmonth();void showOnce();void savetimeOff1();void blinkset();void time();void timeToBuffer();void dateToBuffer();void blink();void offmsd();void keyexe();void keydelay();void comparetime();/*---------------------------------------------------------------------------*//* 定时器零的中断服务程序 *//*---------------------------------------------------------------------------*/void timer0int (void) interrupt 1 using 1 { TL0 = 0; TH0 |= 0xB8; // reload timer 0 with 0B800H 22.1184MHZ cputick++; time(); // update realtime clock }/*---------------------------------------------------------------------------*//* 主函数 *//*---------------------------------------------------------------------------*/void main(){ EA = 1; // 允许所有中断 ET0 = 1; // 允许定时器0中断 TMOD |= 0x01; // timer 0 run 16 bit counter TR0 = 1; // run timer 0 opto = 0xff; // 控制P3.7的输出 cputick = 0; // 每10ms加1 month = 1; // 月的初始值 day = 1; // 日的初始值 hour = 18; // 小时的初始值 min = 0; // 分钟的初始值 sec = 0; // 秒的初始值 key = -1; // 首次按键 keyflag = 0; // 设置键没有按下 flag1 = 0; showsave = 0; // 记录闪烁多少次没有按键自动恢复时间显示 onHour1 = 18; // 18:01 turn lamp on onMin1 = 01; offHour1 = 18; // 18:02 turn lamp off offMin1 = 02; count1 = 0; buffer[0] = 0x00; buffer[1] = 0x00; buffer[2] = 0x00; buffer[3] = 0x00; while(1) { while ( cputick < 1) // 如果定时器中断没有执行,则显一直 scanLED(); // 扫描显示,否则获取时间值,再显示 cputick = 0; /*----------以下每10ms执行一次---------------------------------------*/ timeToBuffer(); // 将时间值的7段码输入buffer中 offmsd(); // 关闭最高位的零显示 blink(); // 处理秒点的闪烁, 亮50*10ms blinkset(); // 处理设置时的闪烁 keyexe(); // 判断键盘按键,执行相应动作 keydelay(); // 延时50*10ms后清除不可按键标志flag1 &= ~0x80 comparetime(); // 判断是否到了开始或结束时间 /*-------------------------------------------------------------------*/ }}/*---------------------------------------------------------------------------*//* 由中断服务程序调用,主要是设置秒分时的变量值 *//*---------------------------------------------------------------------------*/void time (){ sec100++; if (sec100 >= 30) opto |= 0x20; // set P3.5 to beep off if (sec100==50||sec100==100) // 设置时的闪烁间隔 { showdelay = 25; flag1 |= 0x08; } if (sec100 >= 100) // 100 * 10 ms = 1 s { sec100 = 0; flag1 |= 0x05; // set bit 0, bit 2 temp = 50; sec++; if (sec >= 60) { sec = 0; flag1 |= 0x02; // set bit 1 min++; if (min >= 60) { min = 0; hour++; opto &= 0xDF; // clear bit P3.5 to beep if (hour >= 24) { hour = 0; day++; if (day > days[month-1]) { day = 1; month++; if (month > 12) month = 1; } } } } }}/*----------------------------------------------------------------------------*//* 扫描4个数码管和4个按键, if key pressed key = 0-3 else key = -1 *//*----------------------------------------------------------------------------*/void scanLED(){ int i; digit = 0x08; key = -1; for( i = 0; i < 4; i++) // 4-DIGIT scanning { P1 = ~buffer[i]; // send complement[segment] P3 = ~digit & opto; // send complement[digit] pause(160); // delay a while P1 = 0xff; // off LED if ((P3 & 0x10) == 0) // if key pressed P3.4 became low key = i; // save key position to key variable digit>>=1; // next digit }}/*----------------------------------------------------------------------------*//* 把时间值转换为数码管编码 *//*----------------------------------------------------------------------------*/void timeToBuffer(){ if (keyflag < 3) // 如果设置键按下的次数小于3,则显示时间 { buffer[0] = convert[min%10]; buffer[1] = convert[min/10]; buffer[2] = convert[hour%10]; buffer[3] = convert[hour/10]; } else if (keyflag < 5) // 否则显示日期 { buffer[0] = convert[day%10]; buffer[1] = convert[day/10]; buffer[2] = convert[month%10]; buffer[3] = convert[month/10]; // 屏蔽0,不显示 if (buffer[3] == convert[0]) buffer[3] = 0x00; if (buffer[1] == convert[0]) buffer[1] = 0x00; } else if (keyflag < 7) { buffer[0] = convert[onMin1%10]; buffer[1] = convert[onMin1/10]; buffer[2] = convert[onHour1%10]; buffer[3] = convert[onHour1/10]; } else { buffer[0] = convert[offMin1%10]; buffer[1] = convert[offMin1/10]; buffer[2] = convert[offHour1%10]; buffer[3] = convert[offHour1/10]; }}/*----------------------------------------------------------------------------*//* 点亮秒针 *//*----------------------------------------------------------------------------*/void blink(){ if((flag1 & 0x04) != 0) // check bit 2 if set decrement // temp until zero { temp--; if (temp != 0) { // 显示日期时不显示秒闪烁 if (keyflag < 3) { buffer[0] |= 0x80; buffer[1] |= 0x80; } } else flag1 &= ~0x04; }}/*----------------------------------------------------------------------------*//* 闪烁设置位*//*----------------------------------------------------------------------------*/void blinkset(){ if((flag1 & 0x08) != 0 && key!=3) // 如果闪烁间隔到且前后两次按键不一样,就闪烁 { showdelay--; if (showdelay != 0) { if (keyflag != 0) { // 如果是在小时和月份状态 switch (keyflag) { case 1: case 3: case 5: case 7: buffer[3] = 0x00; // 关闭显示,实现闪烁 buffer[2] = 0x00; break; case 2: buffer[0] = 0x80; // 关闭显示,实现闪烁 buffer[1] = 0x80; break; case 4: case 6: case 8: buffer[0] = 0x00; // 关闭显示,实现闪烁 buffer[1] = 0x00; break; } } } else { flag1 &= ~0x08; if (showsave++ > 20) // 如果闪烁20次都没有按键,自动恢复时间显示 { keyflag = 0; showsave = 0; } } }}/*----------------------------------------------------------------------------*//* 执行键盘命令 *//*----------------------------------------------------------------------------*/void keyexe(){ if (key != -1) { if ((flag1 & 0x80) == 0) // within 0.5 sec after 1st press // the following execution is not allowed { flag1 |= 0x80; delay = 25; switch(key) { case (0): // key position 0 manualOnOff(); // service key 0 keyflag=0; break; case (1): // key position 1 savetimeOnOff1(); // service key 1 keyflag=0; break; case (2): // key position 2 keyflag++; // keyflag 1: set hour if (keyflag>8) // 2: set min keyflag=0; // 3: set month // 4: set day break; case (3): // key position 3 showsave = 0; switch(keyflag) { case (0): dateToBuffer(); // show date break; case (1): sethour(); break; case (2): setmin(); break; case (3): setmonth(); break; case (4): setday(); break; case (5): setonHour(); break; case (6): setonMin(); break; case (7): setoffHour(); break; case (8): setoffMin(); break; } } } }}/*----------------------------------------------------------------------------*//* 显示日期 *//*----------------------------------------------------------------------------*/void dateToBuffer(){ buffer[0] = convert[day%10]; buffer[1] = convert[day/10]; buffer[2] = convert[month%10]; buffer[3] = convert[month/10]; if (buffer[3] == convert[0]) buffer[3] = 0x00; if (buffer[1] == convert[0]) buffer[1] = 0x00; showOnce();}/*----------------------------------------------------------------------------*//* 设置小时 *//*----------------------------------------------------------------------------*/void sethour(){ hour++; if ( hour== 24) hour = 0;}void setonHour(){ onHour1++; if (onHour1 == 24) onHour1 = 0;}void setoffHour(){ offHour1++; if (offHour1 == 24) offHour1 = 0;}/*----------------------------------------------------------------------------*//* 设置分钟 *//*----------------------------------------------------------------------------*/void setmin(){ min++; sec = 0; if( min == 60 ) min = 0;}void setonMin(){ onMin1++; if (onMin1 == 60) onMin1 = 0;}void setoffMin(){ offMin1++; if (offMin1 == 60) offMin1 = 0;}/*----------------------------------------------------------------------------*//* 设置日 *//*----------------------------------------------------------------------------*/void setday(){ day++; if (day > days[month-1]) day = 1;}/*----------------------------------------------------------------------------*//* 设置月 *//*----------------------------------------------------------------------------*/void setmonth(){ month++; if (month > 12) month = 1;}/*----------------------------------------------------------------------------*//* 设置开始和结束时间 *//*----------------------------------------------------------------------------*/void savetimeOnOff1(){ count1++; if (count1 == 1) { onHour1 = hour; onMin1 = min; buffer[0] = 0x00; buffer[1] = 0x54; buffer[2] = 0x5C; buffer[3] = 0x78; // show "on" at led showOnce(); } else { count1 = 0; savetimeOff1(); }}/*----------------------------------------------------------------------------*//* 保存结束时间 *//*----------------------------------------------------------------------------*/void savetimeOff1(){ offHour1 = hour; offMin1 = min; buffer[0] = 0x71; buffer[1] = 0x71; buffer[2] = 0x5C; buffer[3] = 0x78; // show "off" at led showOnce(); }/*----------------------------------------------------------------------------*//* 手工点亮 on 或者 off *//*----------------------------------------------------------------------------*/void manualOnOff(){ opto= ~opto | 0x7f; // complement bit 7 which in turn activates P3.7 if ((opto & 0x80) == 0) { buffer[0] = 0; buffer[1] = 0; buffer[2] = 0x54; buffer[3] = 0x5C; // show "on" showOnce(); } else { buffer[0] = 0; buffer[1] = 0x71; buffer[2] = 0x71; buffer[3] = 0x5C; // show "off" showOnce(); }}/*----------------------------------------------------------------------------*//* 显示数码值 *//*----------------------------------------------------------------------------*/void showOnce(){ int i; for(i=0;i<400;i++) scanLED();}/*----------------------------------------------------------------------------*//* 键盘延迟 *//*----------------------------------------------------------------------------*/void keydelay(){ if ((flag1 & 0x80) !=0) { delay--; if(delay == 0) flag1 &= ~0x80; }}/*----------------------------------------------------------------------------*//* 比较是否到了设定的开始或结束时间, 设定opto *//*----------------------------------------------------------------------------*/void comparetime(){ if((flag1 & 0x01) != 0 ) { flag1 &= ~0x01; if(hour == onHour1 && min == onMin1) opto = 0x7f; // clear P3.7 turning opto on if(hour == offHour1 && min == offMin1) opto = 0xff; // set bit P3.7 turning opto off }}/*----------------------------------------------------------------------------*//* 如果小时的最高位为零,则关闭显示零 *//*----------------------------------------------------------------------------*/void offmsd(){ if (buffer[3] == convert[0]) // if msd = '0' then put blank instead buffer[3] = 0x00;}/*----------------------------------------------------------------------------*//* 延迟 *//*----------------------------------------------------------------------------*/void pause(int j){ int i; for (i = 0; i < j; i++);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -