功能:
实现软件万年历功能,并自动识别闰年,A屏每显示5秒种就自动切换到B屏,B屏再显示5秒种就自动切换到C屏,C屏再显示5秒种就自动切换到A屏,通过按键在A屏、B屏和C屏之间切换
,可通过按键手动设定和调整时间,当调整时对应调整位要有闪烁功能,有闹钟功能,可设置几点几分闹钟,当前时间等于闹钟时间时,用点亮LED指示,直到某个键(自定义)被按下时,熄灭LED灯
***************************************************/
#include
unsigned char cnt; // 计数器
unsigned char tian; // 天寄存器
unsigned char key_code; // 按键值
unsigned char flag; // 换屏标志位
unsigned char twinkle_num; // 闪烁标志位
unsigned char function_flag; // 加减功能标志位
unsigned char function_ping1,function_ping2,function_ping3; // 每屏闪烁位
unsigned char change_num; // 闪屏时间定时
unsigned char change_ping; // 三屏计数位
unsigned char clock_flag; // 闹钟标志位
unsigned char ping_flag; // 按键跟踪闪屏标志位
unsigned char num_flag; // 按键计数闪屏标志位
unsigned char tian_flag; // 天判断标志位
unsigned char run_flag; // 闰年判断标志位
unsigned int key_num = 150; // 按键消逗延时时间
unsigned int year = 2008; // 年
unsigned char month = 2; // 月
unsigned char day = 28; // 日
unsigned char hour = 23; // 小时
unsigned char min = 59; // 分
unsigned char sec = 57; // 秒
unsigned char nao_hour = 0; // 闹钟时
unsigned char nao_min = 0; // 闹钟分
unsigned char nao_sec = 0; // 闹钟秒
const unsigned char tianshu[13] =
{0,31,28,31,30,31,30,31,31,30,31,30,31}; // 每月天数表
char digit[12] = // 液晶显示段码表
{
0x7b,
0x12,
0x4f,
0x1f,
0x36,
0x3d,
0x7d,
0x13,
0x7f,
0x3F,
0x00
};
void init_clk(void); // 初始化时钟
void key_scan(void); // 按键扫描
void key_value(void); // 按键值确定
void rtc(void); // 时钟扫描函数
void rtc_show(void); // rtc扫描函数
void leap_year(void); // 闰年判定函数
void main(void)
{
init_clk(); // 时钟初始化
while(1)
{
key_scan(); // 按键扫描
key_value(); // 键值确定
rtc_show(); // RTC显示
leap_year(); // 闰年判定
if((sec == nao_sec) && (min == nao_min) && (hour == nao_hour)) // 闹钟判定
{
clock_flag = 1; // 闹钟标志位置一
}
}
}
void init_clk(void)
{
unsigned char i;
WDTCTL = WDTPW + WDTHOLD; // 关闭看门狗
FLL_CTL0 |= XCAP14PF; // 选择14PF电容
IE2 |= BTIE; // 开启基本定时器中断
BTCTL = BT_ADLY_250 + BTFRFQ1; // 250ms 16分频
LCDCTL = LCDON + LCD4MUX + LCDP2; // STK LCD 4Mux, S0-S14
P5SEL = 0xFC; // 选择P5口第二功能
P1DIR |= 0x01; // P1.0选择输出
_EINT(); // 开总中断
for (i=0; i<19; i++)
{
LCDMEM[i] = 0; //清LCD缓冲区
}
}
void key_scan(void)
{
static unsigned int num; // 按键消抖计数器
if((P1IN&0x0e) != 0x0e) // 如果不等于表示有键按下
{
num++; // 消逗计数器加
key_code = 0; // 键值清零
}
else
{
num = 0; // 按键抖动,键值清零
key_code = 0; // 键值清零
}
if(num == key_num ) // 键值确定
{
num = 0; // 消逗寄存器清零
twinkle_num = 0; // 闪烁清零
key_code = ((P1IN&0x0e)>>1)^0x07; // 键值转换
}
}
void key_value(void)
{
if(key_code == 0x01) // 第一个键被按下
{
function_flag = 1; // 功能键标志位置一
clock_flag = 2; // 关闭闹钟
if(change_ping == 0) // 第一屏
{
function_ping1 ++; // 数值闪烁加
if(function_ping1 == 4) // 闪烁到第三位
{
if(tian_flag == 1)
{
function_ping1 = 1; //
}
else
{
function_ping1 = 0; // 清零
function_flag = 0; // 功能键清零
}
}
change_num = 0; // 换屏计数器
}
if(change_ping == 1) // 第二屏
{
function_ping2++; // 数值闪烁加
if(function_ping2 == 4)
{
function_ping2 = 0;
function_flag = 0; // 清零 // 功能标志位清零
}
change_num = 20; // 换屏时间计数器
}
if(change_ping == 2) // 第三屏
{
function_ping3++; // 数值闪烁加
if(function_ping3 == 4)
{
function_ping3 = 0; // 清零
function_flag = 0; // 功能标志位清零
}
change_num = 40; // 换屏计数器
}
}
if((key_code == 0x02) && (function_flag == 1)) // 加法
{
clock_flag = 2; // 关闭闹钟
if(function_ping2 == 1) // 秒闪烁
{
sec++; // 秒加
if(sec == 60) // 秒是否等于60
sec = 0; // 秒数清零
}
if(function_ping2 == 2) // 分闪烁
{
min++; // 分加
if(min == 60) // 分是否等于60
min = 0; // 分清零
}
if(function_ping2 == 3) // 小时闪烁
{
hour++; // 小时加
if(hour == 24) // 小时是否等于24
hour = 0; // 小时清零
}
if(function_ping1 == 1) // 日闪烁
{
day++; // 日加加
if(day > tian) // 日是否大于天
day = 1; // 日等于1
}
if(function_ping1 == 2) // 月闪烁
{
month++; // 月加加
tian = tianshu[month];
if(day > tian)
{
tian_flag = 1;
}
else
tian_flag = 0;
if(month == 13) // 月是否等于13
month = 1; // 月等于1
}
if(function_ping1 == 3) // 年闪烁
{
year++; // 年加加
if((year%4 != 0)||(year0 != 0) || (year@0 == 0))
{
tian = tianshu[month];
if(day > tian)
{
tian_flag = 1;
}
else
tian_flag = 0;
}
if(year == 2100) // 年是否等于2100
year = 2000; // 年到2000
}
if(function_ping3 == 1) // 闹钟秒闪烁
{
nao_sec++; // 闹钟秒加加
if(nao_sec == 60) // 闹钟秒是否等于60
nao_sec = 0; // 闹钟秒清零
}
if(function_ping3 == 2) // 闹钟分闪烁
{
nao_min++; // 闹钟分加加
if(nao_min == 60) // 闹钟分是否等于60
nao_min = 0; // 闹钟分清零
}
if(function_ping3 == 3) // 闹钟小时闪烁
{
nao_hour++; // 闹钟小时加加
if(nao_hour == 24) // 闹钟小时是否等于24
nao_hour = 0; // 闹钟小时清零
}
} [page]
if((key_code == 0x04) && (function_flag == 1)) // 减法
{
clock_flag = 2; // 清除闹钟标志位
if(function_ping2 == 1)
{
sec--; // 秒减减
if(sec == 0xff) // 秒是否等于0
sec = 59; // 秒等于60
}
if(function_ping2 == 2)
{
min--; // 分减减
if(min == 0xff) // 分是否等于0
min = 59; // 分等于60
}
if(function_ping2 == 3)
{
hour--; // 小时减减
if(hour == 0xff) // 小时是否等于0
hour = 23; // 小时等于24
}
if(function_ping1 == 1)
{
day--; // 天减减
if(day == 0) // 天是否等于0
day = tian; // 天等于30/31/28/29
}
if(function_ping1 == 2)
{
month--; // 月减减
if(month == 0) // 月是否等于0
month = 12; // 月等于13
tian = tianshu[month];
if(day > tian)
tian_flag = 1;
else
tian_flag = 0;
}
if(function_ping1 == 3)
{
year--; // 年减减
if(year ==1999) // 年是否等于1999
year = 2100; // 年等于2100
if((year%4 != 0)||(year0 != 0) || (year@0 == 0))
{
tian = tianshu[month];
if(day > tian)
{
tian_flag = 1;
}
else
tian_flag = 0;
}
}
if(function_ping3 == 1)
{
nao_sec--; // 闹钟秒减减
if(nao_sec == 0xff) // 闹钟秒是否等于0
nao_sec = 59; // 闹钟秒等于60
}
if(function_ping3 == 2)
{
nao_min--; // 闹钟分减减
if(nao_min == 0xff) // 闹钟分是否等于0
nao_min = 59; // 闹钟分等于60
}
if(function_ping3 == 3)
{
nao_hour--; // 闹钟小时减减
if(nao_hour == 0xff) // 闹钟小时是否等于0
nao_hour = 23; // 闹钟小时等于24
}
}
if((key_code == 0x02) && (function_flag == 0)) // 没有功能键按下时
{
clock_flag = 2; // 清除闹钟标志位
flag = 1; // 换屏标志位被按下
if(num_flag == 1) // 换屏位1
ping_flag = 1;
if(num_flag == 2) // 换屏位2
ping_flag = 2;
if(num_flag == 3) // 换屏位3
ping_flag = 3;
}
if((key_code == 0x04) && (function_flag == 0))
{
clock_flag = 2; // 清除闹钟标志位
}
key_code = 0; // 键值清零
}
void leap_year(void)
{
tian = tianshu[month]; // 读出每月天数表
if(day tian)
tian_flag = 0;
if(month == 2)
{
if((year%4 == 0)&&(year0 != 0) || (year@0 == 0)) // 判断是否是闰年
{
tian = 29; // 闰年2月天数修正
}
else
{
tian = 28; // 闰年2月天数修正
}
}
}
void rtc()
{
if(++sec 60) // 秒加一
return;
sec = 0;
if(++min 60) // 分加一
return;
min = 0;
if(++hour 24) // 小时加一
return;
hour = 0;
if(++day = tian) // 天数加一
return;
day = 1; // 月加一
if(++month = 12)
return;
month = 1;
if(++year 2100) // 年加一
return;
year = 2000;
}
void rtc_show(void)
{
if((function_ping1 != 0) && (function_ping2 == 0) && (function_ping3 == 0))
{
change_ping = 0; // 第一屏
}
else if((function_ping1 == 0) && (function_ping2 != 0) && (function_ping3 == 0))
{
change_ping = 1; // 第二屏
}
else if((function_ping1 == 0) && (function_ping2 == 0) && (function_ping3 != 0))
{
change_ping = 2; // 第三屏
}
if(change_ping == 1)
{
if(function_ping2 == 0) // 正常显示
{
LCDMEM[0] = digit[sec];
LCDMEM[1] = digit[sec/10];
LCDMEM[2] = digit[min];
LCDMEM[3] = digit[min/10];
LCDMEM[4] = digit[hour];
LCDMEM[5] = digit[hour/10];
}
if(function_ping2 == 1) // 秒闪烁
{
if(twinkle_num == 0) // 闪烁标志位
{
LCDMEM[0] = digit[sec];
LCDMEM[1] = digit[sec/10];
}
else
{
LCDMEM[0] = 0;
LCDMEM[1] = 0;
}
LCDMEM[2] = digit[min];
LCDMEM[3] = digit[min/10];
LCDMEM[4] = digit[hour];
LCDMEM[5] = digit[hour/10];
}
if(function_ping2 == 2) // 分闪烁
{
if(twinkle_num == 0)
{
LCDMEM[2] = digit[min];
LCDMEM[3] = digit[min/10];
}
else
{
LCDMEM[2] = 0;
LCDMEM[3] = 0;
}
LCDMEM[0] = digit[sec];
LCDMEM[1] = digit[sec/10];
LCDMEM[4] = digit[hour];
LCDMEM[5] = digit[hour/10];
}
if(function_ping2 == 3) // 小时闪烁
{
if(twinkle_num == 0)
{
LCDMEM[4] = digit[hour];
LCDMEM[5] = digit[hour/10];
}
else
{
LCDMEM[4] = 0;
LCDMEM[5] = 0;
}
LCDMEM[0] = digit[sec];
LCDMEM[1] = digit[sec/10];
LCDMEM[2] = digit[min];
LCDMEM[3] = digit[min/10];
}
}
if(change_ping == 0)
{
if(function_ping1 == 0) // 正常显示
{
LCDMEM[0] = digit[(day)];
LCDMEM[1] = digit[(day)/10];
LCDMEM[2] = digit[(month)];
LCDMEM[3] = digit[(month)/10];
LCDMEM[4] = digit[year];
LCDMEM[5] = digit[(year/10)];
}
if(function_ping1 == 1) // 天闪烁
{
if(twinkle_num == 0)
{
LCDMEM[0] = digit[day];
LCDMEM[1] = digit[day/10];
}
else
{
LCDMEM[0] = 0;
LCDMEM[1] = 0;
}
LCDMEM[2] = digit[(month)];
LCDMEM[3] = digit[(month)/10];
LCDMEM[4] = digit[year];
LCDMEM[5] = digit[(year/10)];
}
if(function_ping1 == 2) // 月闪烁
{
if(twinkle_num == 0)
{
LCDMEM[2] = digit[(month)];
LCDMEM[3] = digit[(month)/10];
}
else
{
LCDMEM[2] = 0;
LCDMEM[3] = 0;
}
LCDMEM[0] = digit[day];
LCDMEM[1] = digit[day/10];
LCDMEM[4] = digit[year];
LCDMEM[5] = digit[(year/10)];
}
if(function_ping1 == 3) // 年闪烁
{
if(twinkle_num == 0)
{
LCDMEM[4] = digit[year];
LCDMEM[5] = digit[(year/10)];
}
else
{
LCDMEM[4] = 0;
LCDMEM[5] = 0;
}
LCDMEM[0] = digit[(day)];
LCDMEM[1] = digit[(day)/10];
LCDMEM[2] = digit[(month)];
LCDMEM[3] = digit[(month)/10];
}
} [page]
if(change_ping == 2)
{
if(function_ping3 == 0) // 正常显示
{
LCDMEM[0] = digit[nao_sec];
LCDMEM[1] = digit[nao_sec/10];
LCDMEM[2] = digit[nao_min];
LCDMEM[3] = digit[nao_min/10];
LCDMEM[4] = digit[nao_hour];
LCDMEM[5] = digit[nao_hour/10];
}
if(function_ping3 == 1) // 闹钟秒闪烁
{
if(twinkle_num == 0)
{
LCDMEM[0] = digit[nao_sec];
LCDMEM[1] = digit[nao_sec/10];
}
else
{
LCDMEM[0] = 0;
LCDMEM[1] = 0;
}
LCDMEM[2] = digit[nao_min];
LCDMEM[3] = digit[nao_min/10];
LCDMEM[4] = digit[nao_hour];
LCDMEM[5] = digit[nao_hour/10];
}
if(function_ping3 == 2) // 闹钟分闪烁
{
if(twinkle_num == 0)
{
LCDMEM[2] = digit[nao_min];
LCDMEM[3] = digit[nao_min/10];
}
else
{
LCDMEM[2] = 0;
LCDMEM[3] = 0;
}
LCDMEM[0] = digit[nao_sec];
LCDMEM[1] = digit[nao_sec/10];
LCDMEM[4] = digit[nao_hour];
LCDMEM[5] = digit[nao_hour/10];
}
if(function_ping3 == 3) // 闹钟小时闪烁
{
if(twinkle_num == 0)
{
LCDMEM[4] = digit[nao_hour];
LCDMEM[5] = digit[nao_hour/10];
}
else
{
LCDMEM[4] = 0;
LCDMEM[5] = 0;
}
LCDMEM[0] = digit[nao_sec];
LCDMEM[1] = digit[nao_sec/10];
LCDMEM[2] = digit[nao_min];
LCDMEM[3] = digit[nao_min/10];
}
}
}
#pragma vector=BASICTIMER_VECTOR
__interrupt void basic_timer (void)
{
if(clock_flag == 1) // 闹钟存在
P1OUT ^= BIT0; // LED闪烁
if(clock_flag == 2) // 闹钟清除
P1OUT &= ~BIT0; // 关闭LED
cnt++; // 1s计数器加
if(cnt == 4) // 是否等于4
{
rtc(); // 秒加一
cnt = 0; // 清零
}
change_num++; // 换屏计数器
twinkle_num = ~twinkle_num; // 闪烁标志位
if(change_num == 60) // 屏幕切换计数器到时复位
{
change_num = 0; //
}
if(((change_num > 0) && (change_num 20) || (change_num == 0)) || ((ping_flag == 1) && (flag == 1)))
{
if((ping_flag == 1) && (flag == 1)) // 按键时在第一屏
{
change_num = 20; // 切换到第二屏
flag = 0; // 按键标志位清零
}
change_ping = 0; // 第一屏
num_flag = 1; // 屏切换标志位1
}
if(((change_num > 20) && (change_num 40) || (change_num == 20)) || ((ping_flag == 2) && (flag == 1)))
{
if((ping_flag == 2) && (flag == 1)) // 按键时在第二屏
{
change_num = 40; // 切换到第三屏
flag = 0;
}
change_ping = 1; // 第二屏
num_flag = 2; // 屏切换标志位2
}
if(((change_num > 40) && (change_num 60) || (change_num == 40)) || ((ping_flag == 3) && (flag == 1)))
{
if((ping_flag == 3) && (flag == 1)) // 按键时在第二屏
{
change_num = 0; // 切换到第1屏
flag = 0;
}
change_ping = 2; // 第三屏
num_flag = 3; // 屏切换标志位3
}
}