#include
#include
//中止函数界说
void IRQ1(void) __attribute__((ISR));
void IRQ5(void) __attribute__((ISR));
void IRQ6(void) __attribute__((ISR));
enum { RUN, CHGSECOND, CHGMINUTE, CHGHOUR } clock_status; //时钟的状况
unsigned int hour,minute,second;
unsigned int show_hour, show_minute, show_second;
enum { NOKEY, PRESSING, PRESSED } key_status; //键盘按下与否的状况
unsigned key_code;
// 7段LED数码管的字形码,选用高八位输出,决议显现的字形,如: 0、1等
const unsigned int zhixingma[] = { 0x3f00, 0x0600, 0x5b00, 0x4f00,
0x6600, 0x6d00, 0x7c00, 0x0700,
0x7f00,0x6f00 };
// 数码管挑选的”位段码”,决议哪一位数码管显现
const unsigned int weiduanma[] = {0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040};
//数码管的两个DD引脚, 为时,中心的冒号亮
const unsigned int wei_DD = 0x0081;
void display(unsigned int wei, unsigned int number)
{
*P_IOA_Data = zhixingma[number];
//设置位段码时,不能改动冒号的状况
*P_IOB_Data = weiduanma[wei] | (*P_IOB_Buffer & wei_DD);
}
//取反数码管中心的冒号
void opposite_dots()
{
*P_IOB_Data = wei_DD ^ (*P_IOB_Buffer);
}
void delay(unsigned int howlong)
{
while(howlong–){
unsigned int temp = 0x00ff;
*P_Watchdog_Clear = 1;
while(temp–);
}
}
void init()
{
INT_OFF();
*P_IOA_Dir = 0xff00;
*P_IOA_Attrib = 0xff00;
*P_IOB_Dir = 0x00ff;
*P_IOB_Attrib = 0x00ff;
*P_TimerA_Data = 0xffff – 256;
*P_TimerA_Ctrl = C_SourceA_1 | C_SourceB_256Hz;
*P_INT_Ctrl = C_IRQ1_TMA | C_IRQ6_TMB2 | C_IRQ5_2Hz;
INT_IRQ();
}
void change_clock()
{
unsigned int key_code = get_key();
static unsigned int max;
switch(key_code){ // key_code == 0 will do nothing
case 1:
switch( clock_status ){
case CHGSECOND:
if(++second == 60) second = 0;
break;
case CHGMINUTE:
if(++minute == 60) minute = 0;
break;
case CHGHOUR:
if(++hour == 24) hour =0;
break;
default:
break;
}
break;
case 2:
switch( clock_status ){
case CHGSECOND:
if(–second == 0) second = 59;
break;
case CHGMINUTE:
if(–minute == 0) minute = 59;
break;
case CHGHOUR:
if(–hour == 0) hour = 23;
break;
default:
break;
}
break;
case 3:
switch( clock_status ){
case RUN:
clock_status = CHGSECOND;
break;
case CHGSECOND:
clock_status = CHGMINUTE;
break;
case CHGMINUTE:
clock_status = CHGHOUR;
break;
case CHGHOUR:
clock_status = RUN;
break;
}
break;
default:
break;
}
}
int main()
{
init();
while(1){
change_clock();
if(show_second){
display(5, second % 10);
delay(1);
display(4, second / 10);
delay(1);
}
if(show_minute){
display(3, minute % 10);
delay(1);
display(2, minute / 10);
delay(1);
}
if(show_hour){
display(1, hour % 10);
delay(1);
display(0, hour / 10);
delay(1);
}
}
}
void IRQ1()
{
//时钟计数中止
if( (C_IRQ1_TMA & *P_INT_Ctrl) != 0 )
{ if( clock_status == RUN )
{ second++;
if(second >= 60 ) second=0, minute++;
if(minute >= 60 ) minute=0, hour++;
if(hour >= 24 ) hour=0;
}
*P_INT_Clear = C_IRQ1_TMA;
}
}
void IRQ5()
{// 数码管闪耀
if( (C_IRQ5_2Hz & *P_INT_Ctrl) != 0)
{
switch(clock_status){
case RUN:
opposite_dots();
show_hour = show_minute = show_second = 0xffff;
break;
case CHGSECOND:
show_second ^= 0xffff;
show_minute = show_hour = 0xffff;
break;
case CHGMINUTE:
show_minute ^= 0xffff;
show_second = show_hour = 0xffff;
break;
case CHGHOUR:
show_hour ^= 0xffff;
show_second = show_minute = 0xffff;
break;
}
*P_INT_Clear = C_IRQ5_2Hz;
}
}
void IRQ6()
{ // 每10ms扫描一次键盘
static unsigned int old_key = 0;
static unsigned int key_count = 0;
unsigned int current_key;
if( (C_IRQ6_TMB2 & *P_INT_Ctrl) != 0)
{ current_key = *P_IOA_Data & 0x0007;
if( current_key != 0)
{ //有按键
if( key_status == NOKEY )
{ old_key = current_key;
key_count++;
key_status = PRESSING;
}else{
if( current_key == old_key) //不持平,颤动
{
if( ++key_count >= 5)
//有>5次扫描的值持平,阐明不是颤动,判别按键值
{ if(current_key == 0x0001) key_code = 1;
if(current_key == 0x0002) key_code = 2;
if(current_key == 0x0004) key_code = 3;
}
}else{
// 颤动
old_key = 0;
key_count = 0;
key_status = NOKEY;
}
}
}else{ //无按键
old_key = 0;
key_count = 0;
if( key_status == PRESSING ) key_status = PRESSED; //按键释放了
}
*P_INT_Clear = C_IRQ6_TMB2;
}
}