凌陽61單片機(jī)使用7段數(shù)碼管顯示數(shù)字時鐘的程序
#include
//中斷函數(shù)定義
void IRQ1(void) __attribute__((ISR));
void IRQ5(void) __attribute__((ISR));
void IRQ6(void) __attribute__((ISR));
enum { RUN, CHGSECOND, CHGMINUTE, CHGHOUR } clock_status; //時鐘的狀態(tài)
unsigned int hour,minute,second;
unsigned int show_hour, show_minute, show_second;
enum { NOKEY, PRESSING, PRESSED } key_status; //鍵盤按下與否的狀態(tài)
unsigned key_code;
// 7段LED數(shù)碼管的字形碼,采用高八位輸出,決定顯示的字形,如: 0、1等
const unsigned int zhixingma[] = { 0x3f00, 0x0600, 0x5b00, 0x4f00,
0x6600, 0x6d00, 0x7c00, 0x0700,
0x7f00,0x6f00 };
// 數(shù)碼管選擇的"位段碼",決定哪一位數(shù)碼管顯示
const unsigned int weiduanma[] = {0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040};
//數(shù)碼管的兩個DD引腳, 為時,中間的冒號亮
const unsigned int wei_DD = 0x0081;
void display(unsigned int wei, unsigned int number)
{
*P_IOA_Data = zhixingma[number];
//設(shè)置位段碼時,不能改變冒號的狀態(tài)
*P_IOB_Data = weiduanma[wei] | (*P_IOB_Buffer & wei_DD);
}
//取反數(shù)碼管中間的冒號
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()
{
//時鐘計數(shù)中斷
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()
{// 數(shù)碼管閃爍
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;
}
}
評論