Hi zusammen, folgendes Programm ist sozusagen mein erster Gehversuch mit avr-gcc (ich komme eher aus der anwendungsentwicklung von PCs): http://rafb.net/p/x9GtzP51.html Das Programm läuft nicht so wie ich es mir dachte. (Bei tastendruck soltle die led blinken bei erneuten tastendruck sollte sie aufhöhren) es passiert aber nach einem tastendruck nix... würde ich die led nur mit timer und interuppt blinken lasen geht das einwandfrei... würde ich meinen code nach tastendruck (mit entprellung) die led an/ausschalten lassen geht das auch 1a nur alles zusammen funktioniert nicht :/ was mache ich falsch? MfG Marcel
Dein Compiler kann nicht erkennen, dass die Änderung an der Variablen status in der ISR zum tragen kommt. Für ihn sieht es so aus, als ob die ISR Funktion nie aufgerufen würde (der Compiler weiß nicht, dass die ISR automatisch aufgerufen wird) Daher macht es für ihn auch keinen Sinn eine Variable zu beschreiben, die nirgendwo abgefragt wird. Wenn der Optimizer den ganzen Zugriff nicht überhaupt rauswirft, so versucht der Compiler zumindest die Zeit dafür einzusparen, indem er die Variable status in main() in einem Register hält. -> Die Änderung landet nie wirklich im Speicher. volatile int status; behebt dieses.
Danke für deine Antwort, ich habe oben die variable status global folgendermaßen deklariert: volatile int status; aber es tut sich immernoch nichts :/ MfG
Naja, für die Variable count gilt natürlich sinngemäß das gleiche.
ok hab beide als volatile int gemacht, bringt aber nix (status war ja vorher der interrupt routine bekannt, das war also nicht das problem) led bleibt immernoch, liegt der fehler vllt. woanders? MfG
Ich hol das Programm mal hierher. Das ist doch Unsinn, da immer auf eine externe Website gehen zu müssen, wenn man ein Programm studieren soll
1 | #define F_CPU 1000000
|
2 | |
3 | #include <avr/io.h> |
4 | #include <avr/interrupt.h> |
5 | #include <util/delay.h> |
6 | |
7 | int status = 0; |
8 | float count; |
9 | |
10 | inline uint8_t debounce(volatile uint8_t *port, uint8_t pin) { |
11 | if (! (*port & (1 << pin))) { |
12 | /* Pin wurde auf Masse gezogen, 100ms warten */
|
13 | _delay_ms(100); |
14 | if ( ! (*port & (1 << pin)) ) { |
15 | /* Anwender Zeit zum Loslassen des Tasters geben */
|
16 | _delay_ms(100); |
17 | return 1; |
18 | }
|
19 | }
|
20 | return 0; |
21 | }
|
22 | |
23 | int main(void) { |
24 | // Prescaler = FCPU/1024
|
25 | TCCR0|=(1<<CS02)|(1<<CS00); |
26 | |
27 | //Enable Overflow Interrupt Enable
|
28 | TIMSK|=(1<<TOIE0); |
29 | |
30 | //Initialize Counter
|
31 | TCNT0=0; |
32 | |
33 | count=0; |
34 | |
35 | DDRD = 0xff; |
36 | DDRA = 0x00; |
37 | PORTA = 0xff; |
38 | |
39 | sei(); |
40 | |
41 | while(1) { |
42 | if(debounce(&PINA, PA0)) |
43 | status ^= 1; |
44 | }
|
45 | }
|
46 | |
47 | ISR(TIMER0_OVF_vect) { |
48 | //This is the interrupt service routine for TIMER0 OVERFLOW Interrupt.
|
49 | //CPU automatically call this when TIMER0 overflows.
|
50 | |
51 | count++; |
52 | if((count == 4) && status) { |
53 | PORTD ^= (1 << PD6); |
54 | count=0; |
55 | }
|
56 | }
|
Also: count muss nicht volatile sein. Es finden keine gmeinsamen Zugriffe aus main() und der ISR statt. Damit istr volatile kein Problem. Aber float ist ein unglücklicher Datentyp für einen Zähler. Laut Theorie kann zwar ein float bis zu einer bestimmten Zahl alle ganzen Zahlen exakt abbilden, ob das aber auch gilt, wenn gerechnet wird weiß ich nicht. Meine Hand drauf verwetten würde ich nicht. Das mindeste was ich tun würde ist if((count >= 4) && status) { Wenn bei der ganzen Inkrementiererei count zu 4.0000001 wird, dann funktioniert diese Variante immer noch, während der Vergleich auf exakt 4 fehl schlägt. status sollte auch ein 8-Bit Typ sein, also zb ein unsigned char status damit atomarer Zugriff garantiert ist. Abgesehen davon ist mir nichts mehr aufgefallen
Danke nun klappt es, der Code sieht folgendermaßen aus: #define F_CPU 1000000 #include <avr/io.h> #include <avr/interrupt.h> #include <util/delay.h> volatile int count; volatile int status; inline uint8_t debounce(volatile uint8_t *port, uint8_t pin) { if (! (*port & (1 << pin))) { /* Pin wurde auf Masse gezogen, 100ms warten */ _delay_ms(100); if ( ! (*port & (1 << pin)) ) { /* Anwender Zeit zum Loslassen des Tasters geben */ _delay_ms(100); return 1; } } return 0; } int main(void) { // Prescaler = FCPU/1024 TCCR0 = (1<<CS02) + (1<<CS00); //Enable Overflow Interrupt Enable TIMSK|=(1<<TOIE0); //Initialize Counter TCNT0=0; count=0; status=0; DDRD = 0xff; DDRA = 0x00; PORTA = 0xff; sei(); while(1) { if(debounce(&PINA, PA0)) status ^= 1; } } ISR(TIMER0_OVF_vect) { //This is the interrupt service routine for TIMER0 OVERFLOW Interrupt. //CPU automatically call this when TIMER0 overflows. count++; if((count >= 4) && status) { PORTD ^= (1 << PD6); count=0; } } ich habe jetzt integer zum zaehlen genommen, ist ja sowieso sinnvoller... jedenfalls bei count >= 4 funktioniert es, bei count == 4 funktioniert es nicht. Warum zum Teufel?! Es ist ein Integer, der kann doch genau 4 sein... verstehe ich nicht. Danke bisher MfG Marcel
Marcel schrieb:
> Warum zum Teufel?! Es ist ein Integer, der kann doch genau 4 sein...
Können schon. Aber er muss nicht.
Wenn die ISR count hochzählt und status nicht gesetzt ist, dann wird
count auch nie auf 0 zurückgesetzt sondern zählt hoch und zählt hoch
....
1 | ISR(TIMER0_OVF_vect) |
2 | {
|
3 | count++; |
4 | |
5 | if( count == 4 ) { |
6 | count = 0; |
7 | |
8 | if( status ) { |
9 | PORTD ^= (1 << PD6); |
10 | }
|
11 | }
|
12 | }
|
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.