led电子钟控制程序.c
来自「一款LED电子钟控制程序 本产品能根据用户设定的时间」· C语言 代码 · 共 545 行
C
545 行
/*
定时器,可以设置小时和分钟;
可以设置开始时间,和结束时间,在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-9
char 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 + =
减小字号Ctrl + -
显示快捷键?