如何制作atmega 128电子表和秒表?
How to make atmega 128 electronic watch and stopwatch?
`#include <mega128.h>
unsigned int KEYs_NUMs = 0, FLAG_RUNs = 0, TIME_DAYs = 1, TIME_HOUR = 0, TIME_MINs = 0, TIME_SECs = 0, TIME_10ms = 0, TIME_CNTs = 0 ;
unsigned int TIME_TMR0 = 0, TIME_IMSI, SEGs_NUMs = 0 ;
unsigned int TIME_S0, TIME_S1, TIME_M0, TIME_M1, TIME_H0, TIME_H1 ;
unsigned int IMSI = 0, DAT5 = 0, DAT4 = 0, DAT3 = 0, DAT2 = 0, DAT1 = 0, DAT0 = 0 ;
unsigned int mode = 0 ;
unsigned char SEG7[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7C, 0x07, 0x7F, 0x67} ;
unsigned char FNDs[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7C, 0x07, 0x7F, 0x67} ;
interrupt [EXT_INT4] void ext_int4_isr(void)
{
KEYs_NUMs += 1 ;
if(KEYs_NUMs == 1) { mode = 1 ; }
else { mode = 0 ; KEYs_NUMs = 0 ; }
}
interrupt [EXT_INT5] void ext_int5_isr(void)
{
if(mode == 1)
{
KEYs_NUMs += 1 ;
if(KEYs_NUMs == 1) { FLAG_RUNs = 1 ; }
else if(KEYs_NUMs == 2) { FLAG_RUNs = 0 ; }
else { FLAG_RUNs = 1 ; KEYs_NUMs = 1 ; }
}
}
interrupt [EXT_INT6] void ext_int6_isr(void)
{
if(mode == 1)
{
KEYs_NUMs -= 1 ;
if(KEYs_NUMs == 1) { TIME_MINs = 0, TIME_SECs = 0, TIME_10ms = 0, TIME_CNTs = 0 ; }
}
}
interrupt [EXT_INT7] void ext_int7_isr(void)
{
}
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0 = 0x06 ;
// Place your code here
TIME_TMR0 += 1 ; // 1ms
if(TIME_TMR0 >= 1000)
{ TIME_TMR0 = 0 ; TIME_SECs += 1 ; }
if(TIME_SECs > 59)
{ TIME_SECs = 0 ; TIME_MINs += 1 ; }
if(TIME_MINs > 59)
{ TIME_MINs = 0 ; TIME_HOUR += 1 ; }
if(TIME_HOUR > 23)
{ TIME_HOUR = 0 ; TIME_DAYs += 1 ; }
if(TIME_DAYs > 31)
{ TIME_DAYs = 1 ; }
TIME_IMSI = TIME_HOUR ;
TIME_H1 = TIME_IMSI/10 ;
TIME_H0 = TIME_IMSI - TIME_H1*10 ;
TIME_IMSI = TIME_MINs ;
TIME_M1 = TIME_IMSI/10 ;
TIME_M0 = TIME_IMSI - TIME_M1*10 ;
TIME_IMSI = TIME_SECs ;
TIME_S1 = TIME_IMSI/10 ;
TIME_S0 = TIME_IMSI - TIME_S1*10 ;
if(SEGs_NUMs > 6) { SEGs_NUMs = 0 ; }
SEGs_NUMs += 1 ;
if(SEGs_NUMs == 1)
{
PORTA.5 = 1 ; PORTA.4 = 1 ; PORTA.3 = 1 ; PORTA.2 = 1 ; PORTA.1 = 1 ;
PORTD = SEG7[TIME_S0] ;
PORTA.0 = 0 ;
}
else if(SEGs_NUMs == 2)
{
PORTA.5 = 1 ; PORTA.4 = 1 ; PORTA.3 = 1 ; PORTA.2 = 1 ; PORTA.0 = 1 ;
PORTD = SEG7[TIME_S1] ;
PORTA.1 = 0 ;
}
else if(SEGs_NUMs == 3)
{
PORTA.5 = 1 ; PORTA.4 = 1 ; PORTA.3 = 1 ; PORTA.1 = 1 ; PORTA.0 = 1 ;
PORTD = SEG7[TIME_M0] ;
PORTA.2 = 0 ;
}
else if(SEGs_NUMs == 4)
{
PORTA.5 = 1 ; PORTA.4 = 1 ; PORTA.2 = 1 ; PORTA.1 = 1 ; PORTA.0 = 1 ;
PORTD = SEG7[TIME_M1] ;
PORTA.3 = 0 ;
}
else if(SEGs_NUMs == 5)
{
PORTA.5 = 1 ; PORTA.3 = 1 ; PORTA.2 = 1 ; PORTA.1 = 1 ; PORTA.0 = 1 ;
PORTD = SEG7[TIME_H0] ;
PORTA.4 = 0 ;
}
else
{
PORTA.4 = 1 ; PORTA.3 = 1 ; PORTA.2 = 1 ; PORTA.1 = 1 ; PORTA.0 = 1 ;
PORTD = SEG7[TIME_H1] ;
PORTA.5 = 0 ;
}
if(TIME_TMR0 < 500) { PORTA.7 = 1 ; } // LED off
else { PORTA.7 = 0 ; } // LED on
}
void main(void)
{
DDRA=(1<<DDA7) | (0<<DDA6) | (1<<DDA5) | (1<<DDA4) | (1<<DDA3) | (1<<DDA2) | (1<<DDA1) | (1<<DDA0);
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);
DDRD=(1<<DDD7) | (1<<DDD6) | (1<<DDD5) | (1<<DDD4) | (1<<DDD3) | (1<<DDD2) | (1<<DDD1) | (1<<DDD0);
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
// Timer/Counter 0 initialization
ASSR=0<<AS0;
TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (1<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x06; OCR0=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (1<<TOIE0);
ETIMSK=(0<<TICIE3) | (0<<OCIE3A) | (0<<OCIE3B) | (0<<TOIE3) | (0<<OCIE3C) | (0<<OCIE1C);
// External Interrupt(s) initialization
EICRA=(0<<ISC31) | (0<<ISC30) | (0<<ISC21) | (0<<ISC20) | (0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EICRB=(1<<ISC71) | (0<<ISC70) | (1<<ISC61) | (0<<ISC60) | (1<<ISC51) | (0<<ISC50) | (1<<ISC41) | (0<<ISC40);
EIMSK=(1<<INT7) | (1<<INT6) | (1<<INT5) | (1<<INT4) | (0<<INT3) | (0<<INT2) | (0<<INT1) | (0<<INT0);
EIFR=(1<<INTF7) | (1<<INTF6) | (1<<INTF5) | (1<<INTF4) | (0<<INTF3) | (0<<INTF2) | (0<<INTF1) | (0<<INTF0);
// Globally enable interrupts
#asm("sei")
while (1)
{
if(mode == 1)
{
if(FLAG_RUNs) { TIME_CNTs += 1 ; } // 1ms
if(TIME_CNTs > 99 ) { TIME_CNTs = 0 ; TIME_SECs += 1 ; }
if(TIME_SECs > 59 ) { TIME_SECs = 0 ; TIME_MINs += 1 ; }
if(TIME_MINs > 59 ) { TIME_MINs = 0 ; }
TIME_10ms = TIME_CNTs/10 ;
SEGs_NUMs ++ ;
if(SEGs_NUMs > 5) { SEGs_NUMs = 0 ; }
switch(SEGs_NUMs)
{
case 0 : PORTA.0 = 0 ; PORTA.1 = 1 ; PORTA.2 = 1 ; PORTA.3 = 1 ; PORTA.4 = 1 ;
PORTA.5 = 1 ;
PORTD = FNDs[DAT0] ; break;
case 1 : PORTA.0 = 1 ; PORTA.1 = 0 ; PORTA.2 = 1 ; PORTA.3 = 1 ; PORTA.4 = 1 ;
PORTA.5 = 1 ;
PORTD = FNDs[DAT1] ; break;
case 2 : PORTA.0 = 1 ; PORTA.1 = 1 ; PORTA.2 = 0 ; PORTA.3 = 1 ; PORTA.4 = 1 ;
PORTA.5 = 1 ;
PORTD = FNDs[DAT2] ; break;
case 3 : PORTA.0 = 1 ; PORTA.1 = 1 ; PORTA.2 = 1 ; PORTA.3 = 0 ; PORTA.4 = 1 ;
PORTA.5 = 1 ;
PORTD = FNDs[DAT3] ; break;
case 4 : PORTA.0 = 1 ; PORTA.1 = 1 ; PORTA.2 = 1 ; PORTA.3 = 1 ; PORTA.4 = 0 ;
PORTA.5 = 1 ;
PORTD = FNDs[DAT4] ; break;
case 5 : PORTA.0 = 1 ; PORTA.1 = 1 ; PORTA.2 = 1 ; PORTA.3 = 1 ; PORTA.4 = 1 ;
PORTA.5 = 0 ;
PORTD = FNDs[DAT5] ; break;
}
IMSI = TIME_MINs ;
DAT5 = IMSI/10 ;
DAT4 = IMSI - DAT5*10 ;
IMSI = TIME_SECs ;
DAT3 = IMSI/10 ;
DAT2 = IMSI - DAT3*10 ;
IMSI = TIME_10ms ;
DAT1 = IMSI/10 ;
DAT0 = IMSI - DAT1*10 ;
}
}
}
` 我编写了一个代码,通过将时钟代码放入定时器中断并将秒表代码放入 'while' 来按下模式按钮来更改模式。如果您更改模式,它会根据经过的时间移动到秒表,如果您启动秒表,计数器会从分钟数字开始计时。当您重置时钟并 return 时,时钟从头开始计数。即使我改变了模式,我怎样才能保持定时器运行?以及如何防止计时器的时间被传输到秒表?
根据问题的评论:
interrupt [EXT_INT4] void ext_int4_isr(void)
{
// just toggle the mode, no need for counting any occurrences...
mode = !mode; // alternatively mode = 1 - mode
if(mode)
{
// reset the stop watch on having been enabled:
flagRuns = 0;
// reset the counter as well!
// TODO: common function for!
// should work calling ext_int6_isr directly, too
}
}
interrupt [EXT_INT5] void ext_int5_isr(void)
{
// can toggle unconditionally, as the flag is not evaluated if not
// in stop watch mode and is reset upon ENTERING the mode (this changed
// compared to your original version!)
flagRuns = !flagRuns;
}
interrupt [EXT_INT6] void ext_int6_isr(void)
{
if(mode && !flagRuns)
{
// reset, common function, see above
}
}
您很可能需要声明跨 ISR 和主例程或跨不同 ISR volatile
写入和读取的变量,以避免缓存效应。
`#include <mega128.h>
unsigned int KEYs_NUMs = 0, FLAG_RUNs = 0, TIME_DAYs = 1, TIME_HOUR = 0, TIME_MINs = 0, TIME_SECs = 0, TIME_10ms = 0, TIME_CNTs = 0 ;
unsigned int TIME_TMR0 = 0, TIME_IMSI, SEGs_NUMs = 0 ;
unsigned int TIME_S0, TIME_S1, TIME_M0, TIME_M1, TIME_H0, TIME_H1 ;
unsigned int IMSI = 0, DAT5 = 0, DAT4 = 0, DAT3 = 0, DAT2 = 0, DAT1 = 0, DAT0 = 0 ;
unsigned int mode = 0 ;
unsigned char SEG7[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7C, 0x07, 0x7F, 0x67} ;
unsigned char FNDs[10] = {0x3F, 0x06, 0x5B, 0x4F, 0x66, 0x6D, 0x7C, 0x07, 0x7F, 0x67} ;
interrupt [EXT_INT4] void ext_int4_isr(void)
{
KEYs_NUMs += 1 ;
if(KEYs_NUMs == 1) { mode = 1 ; }
else { mode = 0 ; KEYs_NUMs = 0 ; }
}
interrupt [EXT_INT5] void ext_int5_isr(void)
{
if(mode == 1)
{
KEYs_NUMs += 1 ;
if(KEYs_NUMs == 1) { FLAG_RUNs = 1 ; }
else if(KEYs_NUMs == 2) { FLAG_RUNs = 0 ; }
else { FLAG_RUNs = 1 ; KEYs_NUMs = 1 ; }
}
}
interrupt [EXT_INT6] void ext_int6_isr(void)
{
if(mode == 1)
{
KEYs_NUMs -= 1 ;
if(KEYs_NUMs == 1) { TIME_MINs = 0, TIME_SECs = 0, TIME_10ms = 0, TIME_CNTs = 0 ; }
}
}
interrupt [EXT_INT7] void ext_int7_isr(void)
{
}
interrupt [TIM0_OVF] void timer0_ovf_isr(void)
{
TCNT0 = 0x06 ;
// Place your code here
TIME_TMR0 += 1 ; // 1ms
if(TIME_TMR0 >= 1000)
{ TIME_TMR0 = 0 ; TIME_SECs += 1 ; }
if(TIME_SECs > 59)
{ TIME_SECs = 0 ; TIME_MINs += 1 ; }
if(TIME_MINs > 59)
{ TIME_MINs = 0 ; TIME_HOUR += 1 ; }
if(TIME_HOUR > 23)
{ TIME_HOUR = 0 ; TIME_DAYs += 1 ; }
if(TIME_DAYs > 31)
{ TIME_DAYs = 1 ; }
TIME_IMSI = TIME_HOUR ;
TIME_H1 = TIME_IMSI/10 ;
TIME_H0 = TIME_IMSI - TIME_H1*10 ;
TIME_IMSI = TIME_MINs ;
TIME_M1 = TIME_IMSI/10 ;
TIME_M0 = TIME_IMSI - TIME_M1*10 ;
TIME_IMSI = TIME_SECs ;
TIME_S1 = TIME_IMSI/10 ;
TIME_S0 = TIME_IMSI - TIME_S1*10 ;
if(SEGs_NUMs > 6) { SEGs_NUMs = 0 ; }
SEGs_NUMs += 1 ;
if(SEGs_NUMs == 1)
{
PORTA.5 = 1 ; PORTA.4 = 1 ; PORTA.3 = 1 ; PORTA.2 = 1 ; PORTA.1 = 1 ;
PORTD = SEG7[TIME_S0] ;
PORTA.0 = 0 ;
}
else if(SEGs_NUMs == 2)
{
PORTA.5 = 1 ; PORTA.4 = 1 ; PORTA.3 = 1 ; PORTA.2 = 1 ; PORTA.0 = 1 ;
PORTD = SEG7[TIME_S1] ;
PORTA.1 = 0 ;
}
else if(SEGs_NUMs == 3)
{
PORTA.5 = 1 ; PORTA.4 = 1 ; PORTA.3 = 1 ; PORTA.1 = 1 ; PORTA.0 = 1 ;
PORTD = SEG7[TIME_M0] ;
PORTA.2 = 0 ;
}
else if(SEGs_NUMs == 4)
{
PORTA.5 = 1 ; PORTA.4 = 1 ; PORTA.2 = 1 ; PORTA.1 = 1 ; PORTA.0 = 1 ;
PORTD = SEG7[TIME_M1] ;
PORTA.3 = 0 ;
}
else if(SEGs_NUMs == 5)
{
PORTA.5 = 1 ; PORTA.3 = 1 ; PORTA.2 = 1 ; PORTA.1 = 1 ; PORTA.0 = 1 ;
PORTD = SEG7[TIME_H0] ;
PORTA.4 = 0 ;
}
else
{
PORTA.4 = 1 ; PORTA.3 = 1 ; PORTA.2 = 1 ; PORTA.1 = 1 ; PORTA.0 = 1 ;
PORTD = SEG7[TIME_H1] ;
PORTA.5 = 0 ;
}
if(TIME_TMR0 < 500) { PORTA.7 = 1 ; } // LED off
else { PORTA.7 = 0 ; } // LED on
}
void main(void)
{
DDRA=(1<<DDA7) | (0<<DDA6) | (1<<DDA5) | (1<<DDA4) | (1<<DDA3) | (1<<DDA2) | (1<<DDA1) | (1<<DDA0);
PORTA=(0<<PORTA7) | (0<<PORTA6) | (0<<PORTA5) | (0<<PORTA4) | (0<<PORTA3) | (0<<PORTA2) | (0<<PORTA1) | (0<<PORTA0);
DDRD=(1<<DDD7) | (1<<DDD6) | (1<<DDD5) | (1<<DDD4) | (1<<DDD3) | (1<<DDD2) | (1<<DDD1) | (1<<DDD0);
PORTD=(0<<PORTD7) | (0<<PORTD6) | (0<<PORTD5) | (0<<PORTD4) | (0<<PORTD3) | (0<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);
// Timer/Counter 0 initialization
ASSR=0<<AS0;
TCCR0=(0<<WGM00) | (0<<COM01) | (0<<COM00) | (0<<WGM01) | (1<<CS02) | (0<<CS01) | (0<<CS00);
TCNT0=0x06; OCR0=0x00;
// Timer(s)/Counter(s) Interrupt(s) initialization
TIMSK=(0<<OCIE2) | (0<<TOIE2) | (0<<TICIE1) | (0<<OCIE1A) | (0<<OCIE1B) | (0<<TOIE1) | (0<<OCIE0) | (1<<TOIE0);
ETIMSK=(0<<TICIE3) | (0<<OCIE3A) | (0<<OCIE3B) | (0<<TOIE3) | (0<<OCIE3C) | (0<<OCIE1C);
// External Interrupt(s) initialization
EICRA=(0<<ISC31) | (0<<ISC30) | (0<<ISC21) | (0<<ISC20) | (0<<ISC11) | (0<<ISC10) | (0<<ISC01) | (0<<ISC00);
EICRB=(1<<ISC71) | (0<<ISC70) | (1<<ISC61) | (0<<ISC60) | (1<<ISC51) | (0<<ISC50) | (1<<ISC41) | (0<<ISC40);
EIMSK=(1<<INT7) | (1<<INT6) | (1<<INT5) | (1<<INT4) | (0<<INT3) | (0<<INT2) | (0<<INT1) | (0<<INT0);
EIFR=(1<<INTF7) | (1<<INTF6) | (1<<INTF5) | (1<<INTF4) | (0<<INTF3) | (0<<INTF2) | (0<<INTF1) | (0<<INTF0);
// Globally enable interrupts
#asm("sei")
while (1)
{
if(mode == 1)
{
if(FLAG_RUNs) { TIME_CNTs += 1 ; } // 1ms
if(TIME_CNTs > 99 ) { TIME_CNTs = 0 ; TIME_SECs += 1 ; }
if(TIME_SECs > 59 ) { TIME_SECs = 0 ; TIME_MINs += 1 ; }
if(TIME_MINs > 59 ) { TIME_MINs = 0 ; }
TIME_10ms = TIME_CNTs/10 ;
SEGs_NUMs ++ ;
if(SEGs_NUMs > 5) { SEGs_NUMs = 0 ; }
switch(SEGs_NUMs)
{
case 0 : PORTA.0 = 0 ; PORTA.1 = 1 ; PORTA.2 = 1 ; PORTA.3 = 1 ; PORTA.4 = 1 ;
PORTA.5 = 1 ;
PORTD = FNDs[DAT0] ; break;
case 1 : PORTA.0 = 1 ; PORTA.1 = 0 ; PORTA.2 = 1 ; PORTA.3 = 1 ; PORTA.4 = 1 ;
PORTA.5 = 1 ;
PORTD = FNDs[DAT1] ; break;
case 2 : PORTA.0 = 1 ; PORTA.1 = 1 ; PORTA.2 = 0 ; PORTA.3 = 1 ; PORTA.4 = 1 ;
PORTA.5 = 1 ;
PORTD = FNDs[DAT2] ; break;
case 3 : PORTA.0 = 1 ; PORTA.1 = 1 ; PORTA.2 = 1 ; PORTA.3 = 0 ; PORTA.4 = 1 ;
PORTA.5 = 1 ;
PORTD = FNDs[DAT3] ; break;
case 4 : PORTA.0 = 1 ; PORTA.1 = 1 ; PORTA.2 = 1 ; PORTA.3 = 1 ; PORTA.4 = 0 ;
PORTA.5 = 1 ;
PORTD = FNDs[DAT4] ; break;
case 5 : PORTA.0 = 1 ; PORTA.1 = 1 ; PORTA.2 = 1 ; PORTA.3 = 1 ; PORTA.4 = 1 ;
PORTA.5 = 0 ;
PORTD = FNDs[DAT5] ; break;
}
IMSI = TIME_MINs ;
DAT5 = IMSI/10 ;
DAT4 = IMSI - DAT5*10 ;
IMSI = TIME_SECs ;
DAT3 = IMSI/10 ;
DAT2 = IMSI - DAT3*10 ;
IMSI = TIME_10ms ;
DAT1 = IMSI/10 ;
DAT0 = IMSI - DAT1*10 ;
}
}
}
` 我编写了一个代码,通过将时钟代码放入定时器中断并将秒表代码放入 'while' 来按下模式按钮来更改模式。如果您更改模式,它会根据经过的时间移动到秒表,如果您启动秒表,计数器会从分钟数字开始计时。当您重置时钟并 return 时,时钟从头开始计数。即使我改变了模式,我怎样才能保持定时器运行?以及如何防止计时器的时间被传输到秒表?
根据问题的评论:
interrupt [EXT_INT4] void ext_int4_isr(void)
{
// just toggle the mode, no need for counting any occurrences...
mode = !mode; // alternatively mode = 1 - mode
if(mode)
{
// reset the stop watch on having been enabled:
flagRuns = 0;
// reset the counter as well!
// TODO: common function for!
// should work calling ext_int6_isr directly, too
}
}
interrupt [EXT_INT5] void ext_int5_isr(void)
{
// can toggle unconditionally, as the flag is not evaluated if not
// in stop watch mode and is reset upon ENTERING the mode (this changed
// compared to your original version!)
flagRuns = !flagRuns;
}
interrupt [EXT_INT6] void ext_int6_isr(void)
{
if(mode && !flagRuns)
{
// reset, common function, see above
}
}
您很可能需要声明跨 ISR 和主例程或跨不同 ISR volatile
写入和读取的变量,以避免缓存效应。