全功能迷你电子表
作者:chuanhuibh 版本 V1.0
本电子表是基于MEGA8单片机和LED数码管为主体设计的,它功能全面,可以显示月,日,时,分,秒,还可以设定闹钟,设计时考虑到省电,还可以进入休眠状态(不显示,但时钟仍运行),以下是该表的使用说明。
12位分3页设置依次是:
时2位:分2位;
UP
LEFT_ SET_ RIGHT
DOWN
月2位:日2位;
闹钟的时2位:分2位
设置完后再按SET键即可回到正常的显示模式(时:分),若要当秒表,则按RIGHT,可实现两种显示切换。
正常显示时,按DOWN键,可以显示日期(月:日),过几秒后回到正常显示模式。按LEFT休眠,重按后苏醒。
本电子表使用3节5号电池供电一共5个键,和一个位于电路板和电池盒间的电源开关。5个键按空间位置分别是LEFT,RIGHT,UP,DOWN,以及中间的SET,位置和名字对应。
键位设置
上电后,按RIGHT键可以实现(时:分)显示到(分:秒)显示模式的切换。按SET键可以进入设置模式,一共有12位要设置,分为3页(因为是4个数码管),此时数码管显示第一位,按RIGHT依次像右移动,按UP键所显示的位会加1,加到9回0。
/* 作者 chuanhuibh
全功能电子表,
LED, 月,日,时,分,秒,闹钟
可以选择休眠,时钟运行,CPU 和大部分外设停止,
外部32768 HZ每秒中断唤醒
5键设置 ,用法见帖子说明
MEGA8 ICCAVR
*/
/*
PORTD LED的8位数据
PORTB0~3 选通
PC1~5 按键 见本帖末尾key.h
*/
#include"iom8v.h"
#include"macros.h"
#include"key.h"
const char Table[10]={0x3f,0x06,0x5b,0x4f,0x66,
0x6d,0x7d,0x07,0x7f,0x6f};
const char MONTH[12]={31,28,31,30,31,30,31,31,
30,31,30,31};
char Date[12]={1,1,1,1,2,2,2,2,3,3,3,3};
char sleep="0",wei=0,wei_1=0,second,minute,hour,
minute_s,hour_s,
month="10",data=22,page=0;
void Delay_nus(unsigned i)
{
for(;i>1;i--){;}
}
void Delay_1ms()
{unsigned i;
for(i=125;i>1;i--)
{Delay_nus(1);
}
}
void Delay_nms(unsigned i)
{
for(;i>1;i--)
{Delay_1ms();}
}
void Display(char *p)
{char i,sel=0x01;
if(sleep) return;
for(i=0;i<4;i++)
{
PORTB=~sel; // 0 表示选通
PORTD="Table"[p];
Delay_nms(2);
PORTD="0x00";
sel="sel"<<1;
}
}
void Sound(char i)
{
char n;
for(n=0;n {
PORTC&=~(1< PORTC|=(1< Delay_nms(15);
PORTC&=~(1< Delay_nms(15);
}
}
void Ring(void)
{
char temp="5";PORTD=0x00;
while(temp>0)
{
Sound(1);
Delay_nms(200);
Sound(1);
Delay_nms(200);
Sound(1);
Delay_nms(200);
Sound(1);
Delay_nms(400);
Sound(1);
temp--;
}
}
void Io_Init(Void)
{DDRD=0xFF;
PORTD=0xff;
DDRC=0x01;PORTC=0xfe;
DDRB=0x0F;
PORTB=0xff;
}
void Init_timer2(void)
{
TCCR2=0x00; //先关再操作
ASSR=(1<TCNT2=0xe0;
TCCR2=0x07; //1024 fen
SREG=SREG|0x80;
TIMSK|=(1<}
void BIN_to_CLK(char *p)
{
if(page)
{ p[3]=second%10;
p[2]=second/10;
p[1]=minute%10;
p[0]=minute/10;
}
else{
p[3]=minute%10;
p[2]=minute/10;
p[1]=hour%10;
p[0]=hour/10;
}
}
void DATA_to_CLK(char *p)
{
p[7]=data%10;
p[6]=data/10;
p[5]=month%10;
p[4]=month/10;
}
char Key_Value(void)
{
char temp,value;
temp=PINC&0x3e;
//
Delay_nms(8);
if(temp==(PINC&0x3e))//延时后键值未变,消抖成功
switch(temp)
{
case 0x3c: value="SET"; break;
case 0x3a: value="DEC"; break;
case 0x36: value="ADD"; break;
case 0x2e: value="LEFT"; break;
case 0x1e: value="RIGHT"; break;
default: value="ERROR";
}
while(temp==(PINC&0x3e));//直到键松开
Delay_nms(25);
return value;
}
void Display_wei(char i)
{PORTD=Table[Date[wei_1]];PORTB=~(1<}
void Key_Process()
{char temp, n;
temp=Key_Value();
if(temp==DEC)
{for(n=0;n<150;n++)
{
DATA_to_CLK(Date);
Display(Date+4);
}
return;
}
else if(temp==LEFT)
{
if(sleep==0) {
sleep="1";
MCUCR="0x90";
asm("SLEEP");
}
else sleep="0";
return;
}
else if(temp==RIGHT)
{if (page==0) page="1";
else page="0";
}
if(temp!=SET)
return;
wei_1=0;Display_wei(wei_1);
while(1)
{
temp="Key"_Value();
switch(temp)
{
case SET: hour="Date"[1]+Date[0]*10;
minute="Date"[3]+Date[2]*10;
month="Date"[5]+Date[4]*10;
data="Date"[7]+Date[6]*10;
hour_s=Date[8]*10+Date[9];
minute_s=Date[10]*10+Date[11];
return;
case RIGHT: if(wei_1<11) wei_1++;
else wei_1=0;
wei="wei"_1%4;
break;
case ADD: if(Date[wei_1]<9) Date[wei_1]++;
else Date[wei_1]=0;
break;
default: break;
}
Display_wei(wei_1);
}
/**/
}
void main(void)
{
Io_Init();
Init_timer2();
TIMSK =1<SEI();
// Sound(1);
while(1)
{
BIN_to_CLK(Date);
Display(Date) ;
if((PINC&0x3e)!=0x3e) Key_Process();
if(sleep) {MCUCR=0x90;asm("SLEEP");}
}
}
#pragma interrupt_handler Timer2:5
void Timer2(void)
{TCNT2=0xe0;
second++;
//sleep=0;
MCUCR=0x00;
//Sound(1);
if(second==60)
{minute++;second=0;
if(minute==minute_s&&hour==hour_s&&hour!=0&&minute!=0)
Ring();}
if(minute==60)
{hour++;minute=0;
}
if(hour==24)
{hour=0;data++;}
if(data==MONTH[month])
{data=1;month++;}
}
key.h
#define SET 0x01
#define LEFT 0x02
#define RIGHT 0x03
#define ADD 0x04
#define DEC 0x05
#define ERROR 0x06
文章评论(0条评论)
登录后参与讨论