Hallo an alle,
ich brauche - wer hätte es gedacht - etwas Hilfe bei einem Programm. Es handelt sich um zwei unabhängige Zähler (0...9) welche von vier Tasten in~/dekrementiert werden.
Der Zählerstand wird dann auf zwei 7-Segment Anzeigen ausgegeben. Bis jetzt erfolgt das Multiplexen und die Tasterabfrage aber nur in der main(). Das Problem ist, dass immer wenn ein Taster gedrückt wird, die Anzeigen kurz ausgeschaltet werden.
Wie kann dieses Problem gelöst werden?
Achja, das Programm ist für einen ATTiny2313:
ich brauche - wer hätte es gedacht - etwas Hilfe bei einem Programm. Es handelt sich um zwei unabhängige Zähler (0...9) welche von vier Tasten in~/dekrementiert werden.
Der Zählerstand wird dann auf zwei 7-Segment Anzeigen ausgegeben. Bis jetzt erfolgt das Multiplexen und die Tasterabfrage aber nur in der main(). Das Problem ist, dass immer wenn ein Taster gedrückt wird, die Anzeigen kurz ausgeschaltet werden.
Wie kann dieses Problem gelöst werden?
Achja, das Programm ist für einen ATTiny2313:
Code:
#include <avr/io.h>
#define F_CPU 4e6
#include <util/delay.h>
#define Modul1 PORTD, PORTD2
#define Modul2 PORTD, PORTD1
//Anschlussbelegung der 7sSeg. Anzeige am Port B
#define Summer PORTB, PORTB0
#define SEGa PORTB, PORTB1
#define SEGb PORTB, PORTB2
#define SEGc PORTB, PORTB3
#define SEGd PORTB, PORTB4
#define SEGe PORTB, PORTB5
#define SEGf PORTB, PORTB6
#define SEGg PORTB, PORTB7
#define setbit(IO) __setbit(IO)
#define __setbit(PORT, BIT) PORT |= (1<<BIT)
#define clearbit(IO) __clearbit(IO)
#define __clearbit(PORT, BIT) PORT &=~ (1<<BIT)
//Entprell-Routine übernommen von "http://www.mikrocontroller.net/attachment/67964/debounce.c"
#define debounce( port, pin ) \
({ \
static uint8_t flag = 0; /* new variable on every macro usage */ \
uint8_t i = 0; \
\
if( flag ){ /* check for key release: */ \
for(;;){ /* loop ... */ \
if( !(port & 1<<pin) ){ /* ... until key pressed or ... */ \
i = 0; /* 0 = bounce */ \
break; \
} \
_delay_us( 20 ); /* * 256 = 25ms */ \
if( --i == 0 ){ /* ... until key >25ms released */ \
flag = 0; /* clear press flag */ \
i = 0; /* 0 = key release debounced */ \
break; \
} \
} \
}else{ /* else check for key press: */ \
for(;;){ /* loop ... */ \
if( (port & 1<<pin) ){ /* ... until key released or ... */ \
i = 0; /* 0 = bounce */ \
break; \
} \
_delay_us( 20 ); /* * 256 = 25ms */ \
if( --i == 0 ){ /* ... until key >25ms pressed */ \
flag = 1; /* set press flag */ \
i = 1; /* 1 = key press debounced */ \
break; \
} \
} \
} \
i; /* return value of Macro */ \
})
volatile int8_t zaehler[2];
//Initialisierung
void init( void )
{
DDRB = 0xFF; //Port B Ausgang
PORTB = 0xFE; //Alle Pins, bis auf PB0 HIGH
DDRD = 0b0000110; //Port D Pin6,5,4,3,0 Eingänge; Pin 2,1 Ausgänge
PORTD = 0b1111111; //Alle PullUp-Widerstände 6...3 ein; Ausgänge auf HIGH (PNP Transistoren aus)
}
//Ausgabemuster für 7Segment-Anzeige
//gemeinsame Anode, clearbit schaltet Segment ein
void SiebenSegAnz(uint8_t a)
{
switch(a)
{
case 9: //Segment: gfedcba
{ //PORTB = 0b0010000x;
clearbit(SEGa);
clearbit(SEGb);
clearbit(SEGc);
clearbit(SEGd);
setbit(SEGe);
clearbit(SEGf);
clearbit(SEGg);
}break;
case 8:
{ //PORTB = 0b0000000x;
clearbit(SEGa);
clearbit(SEGb);
clearbit(SEGc);
clearbit(SEGd);
clearbit(SEGe);
clearbit(SEGf);
clearbit(SEGg);
}break;
case 7:
{ //PORTB = 0b1111000x;
clearbit(SEGa);
clearbit(SEGb);
clearbit(SEGc);
setbit(SEGd);
setbit(SEGe);
setbit(SEGf);
setbit(SEGg);
}break;
case 6:
{ //PORTB = 0b0000010x;
clearbit(SEGa);
setbit(SEGb);
clearbit(SEGc);
clearbit(SEGd);
clearbit(SEGe);
clearbit(SEGf);
clearbit(SEGg);
}break;
case 5:
{ //PORTB = 0b0010010x;
clearbit(SEGa);
setbit(SEGb);
clearbit(SEGc);
clearbit(SEGd);
setbit(SEGe);
clearbit(SEGf);
clearbit(SEGg);
}break;
case 4:
{ //PORTB = 0b0011001x;
setbit(SEGa);
clearbit(SEGb);
clearbit(SEGc);
setbit(SEGd);
setbit(SEGe);
clearbit(SEGf);
clearbit(SEGg);
}break;
case 3:
{ //PORTB = 0b0110000x;
clearbit(SEGa);
clearbit(SEGb);
clearbit(SEGc);
clearbit(SEGd);
setbit(SEGe);
setbit(SEGf);
clearbit(SEGg);
}break;
case 2:
{ //PORTB = 0b0100100x;
clearbit(SEGa);
clearbit(SEGb);
setbit(SEGc);
clearbit(SEGd);
clearbit(SEGe);
setbit(SEGf);
clearbit(SEGg);
}break;
case 1:
{ //PORTB = 0b1111001x;
setbit(SEGa);
clearbit(SEGb);
clearbit(SEGc);
setbit(SEGd);
setbit(SEGe);
setbit(SEGf);
setbit(SEGg);
}break;
case 0:
{ //PORTB = 0b1000000x;
clearbit(SEGa);
clearbit(SEGb);
clearbit(SEGc);
clearbit(SEGd);
clearbit(SEGe);
clearbit(SEGf);
setbit(SEGg);
}break;
default:
{ //PORTB = 0b0111111x;
setbit(SEGa);
setbit(SEGb);
setbit(SEGc);
setbit(SEGd);
setbit(SEGe);
setbit(SEGf);
clearbit(SEGg);
}
}
}
int main(void)
{
init();
int i=0;
zaehler[0]=9;
zaehler[1]=9;
for(;;)
{
if( debounce( PIND, PD3 ) ) zaehler[0]++;
if( debounce( PIND, PD4 ) ) zaehler[0]--;
if( debounce( PIND, PD6 ) ) zaehler[1]++;
if( debounce( PIND, PD5 ) ) zaehler[1]--;
if((zaehler[0] < 1) || (zaehler[1] < 1)) //Rücksetzen erst möglich wenn ein Zähler auf Null
{
setbit(Summer);
i++;
if (i>400) clearbit(Summer); //Summer nach 400 durchläufen wieder abschalten
//schöner wäre allerdings eine einstellbare Zeit
if( debounce( PIND, PD0 ) )
{
zaehler[0]=9;
zaehler[1]=9;
i=0;
}
if (i>450) i=410;
}
//Zähler 1
clearbit (Modul1); //Erstes Modul ein
SiebenSegAnz (zaehler[0]); //Wert von Zähler 1 ausgeben
_delay_ms(1); //Anzeige 1ms stehen lassen
setbit (Modul1); //Erstes Modus aus
//Zähler 2
clearbit (Modul2);
SiebenSegAnz (zaehler[1]);
_delay_ms(1);
setbit (Modul2);
}
}