您的位置:首页 > 其它

凌阳61单片机使用7段数码管显示数字时钟的程序

2006-06-18 18:31 477 查看
#include <SPCE061v004.h>
#include <unspmacro.h>
//中断函数定义
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;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: