Datum:
Hi, schon wieder ein Problem was mich meine Berven kostet. Der Tiny macht mich ech zu schaffen.... Problem: in der main schleife setze ich ein bit, dieses wird aber sofort wieder zurück gesetzt. die led an dem pin blinkt nur kurz auf.
// Countdown 199 - 0 auf TOT-4301 (2,5 Stelliges 7-Segment von Pollin) // ATtiny2313 #include <avr/io.h> #define F_CPU 1000000UL #include <stdio.h> #include <util/delay.h> #include <avr/interrupt.h> #define SETBIT(ADRESS, BIT) (ADRESS |=(1<<BIT)) //Makro zum Setzen eines Bits #define CLEARBIT(ADRESS, BIT) (ADRESS &=~(1<<BIT)) //Makro zum Loeschen eines Bits #define CHECKBIT(ADRESS, BIT) (ADRESS &(1<<BIT)) //Makro zum Pruefen eines Bits volatile int leerlauf; volatile unsigned int count =0; volatile unsigned int mpx =0; volatile unsigned char seg7[]={63,6,91,79,102,109,125,7,127,111}; volatile unsigned int zeit; volatile unsigned char merker=0; volatile unsigned char spalte=1; volatile unsigned char z1; char digit[]; struct zerlegung { int zahl; int var; int zehner; int hunderter; int tausender; int zehntausender; }; struct zerlegung ziffer; ISR(TIMER0_OVF_vect) { TCNT0 = 150; count++; mpx++; if(mpx==1) // Multiplexer { merker=0; if(spalte==1) { CLEARBIT(PIND,PIND1); SETBIT(PIND,PIND0); PORTB=~seg7[digit[1]] + z1; spalte=2; merker=1; } if(spalte==2 & merker==0) { CLEARBIT(PIND,PIND0); SETBIT(PIND,PIND1); PORTB =~seg7[digit[0]] + z1; spalte=1; merker=0; } } if(mpx==1) mpx=0; } void init(void) { DDRA=0xff; DDRB=0xff; // -> PORTB 0-6 = 7-Segment a-f | PORTB 7 = halbe stelle DDRD=0b11100011 ; // -> PD0 -> Stelle 1, PD1 -> Stelle 2 // -> PD 5:7 -> Taster TCCR0B = 0x02; // Timerstart TCNT0 = 150; // Startwert nachladen, 0xFA // 250* 64us=16ms bis Overflow SREG = (1<<7); // Allgemeine Interruptfreigabe; TIMSK=(1<<TOIE0); // Freigabe Timer0 Iterrupt } int main(void) { zeit=124; init(); while(1) { if(zeit<=99) z1 = 0; if(zeit>=100) z1 = 128; if((PIND & 0b00000100) == 0b00000100) { zeit=30; } if(count >= 500) { count=0; zeit--; // Teilt eine 5 Stellige Zahl in einzelne Stellen auf // Ausgabe in der Variablen "digit[]" // digit[4] -> Erste Stelle // digit[0] -> Letzte Stelle ziffer.zahl = zeit; ziffer.zehner = ziffer.zahl / 10; ziffer.hunderter = ziffer.zahl / 100; ziffer.tausender = ziffer.zahl / 1000; ziffer.zehntausender = ziffer.zahl / 10000; digit[4] = ziffer.zehntausender; ziffer.var = ziffer.zehntausender * 10; digit[3] = ziffer.tausender - ziffer.var; ziffer.var = ziffer.tausender * 10; digit[2] = ziffer.hunderter - ziffer.var; ziffer.var = ziffer.hunderter * 10; digit[1] = ziffer.zehner - ziffer.var; ziffer.var = ziffer.zehner * 10; digit[0] = ziffer.zahl - ziffer.var; if(zeit>0) PORTD |= (1 << 5); <----------------- HIER, das Bit will nicht bleiben } leerlauf++; } } |
bei anderen µCs ist mir das noch nicht passiert.... gruß Alex
Datum:
Das ist so bei den AVRs, dass sie das der entsprechenden ISR zugehörige Flag löschen. Aber das meinst du vermutlich garnicht. Das Array "digit[]" sollte auch volatile sein, da schließlich in der ISR darauf zugegriffen wird. Dann solltest du die Größe von digit auf ein auf jeden Fall ausreichendes Maß festnageln; auf dem µC gibt es mit dieser Umgebung keine dynamische Speicherzuweisung und in der reinen Essenz der Programmiersprache C geht das auch nicht auf diese Art und Weise. mfg mf
Datum:
ja, das mit dem volatile ist mir noch nicht ganz klar...bei meinem µC Board mit nem AT90CAN128 hab ich das noch nie gebraucht.... hab den fehler aber schon gefunden: ich schreibe in der ISR: CLEARBIT(PIND,PIND1); SETBIT(PIND,PIND0); das muss so sein: CLEARBIT(PORTD,PORTD1); SETBIT(PORTD,PORTD0); .....
Datum:
Alexander G. schrieb: > ja, das mit dem volatile ist mir noch nicht ganz klar "volatile" ist ein Schlüsselwort. Flüchtig. Damit Teilst du dem Compiler mit, dass sich an der Variable auch zu Zeiten, zu denen ers nicht "sieht", etwas ändern könnte oder Fremdzugriffe stattfinden. Dies betrifft Schreiben und auch Lesen. Hier zum Beispiel wird in der "main()" viel an "digit[]" rumgeorgelt. In der ISR sehe ich aber auch noch einen Zugriff. Gerade der GCC ist dafür bekannt, im Schreiben von Variableninhalten von Registern zurück in den RAM je nach Optimierungsstufe extrem faul zu sein. Es wird dann zum spätestmöglichen Zeitpunkt; manchmal auch garnicht zurückgespeichert. Mit "volatile" behandelt der Compiler die Variable wie eine heiße Kartoffel. Idealerweise gibt es dazu beim AVR über Pointeradressierung eine elegante Methode. Das löst der Compiler dann so auf. 16Bit-Operationen sind in der Prozessorarchitektur zum Glück als atomische(=nicht unterbrechbare) Operationen realisiert. Also einfach an die Kartoffel denken. mfg mf Ja, auf PINx-Register Schreiben ist Toggeln des PORTx-Registers an den Stellen, wo Bits gesetzt sind. Das ist auch erst seit ein paar Jahren so. Hab aber auch schon elegantere Lösungen dazu gesehen. Vorteil ist, dass man sich so ein paar Zyklen spart.
Datum:
> atomische
atomare?