Hallo zusammen, habe folgendes Problem: Ich habe an PORTA sowie PORTD jeweils 8 LEDs angeschlossen und habe bisher mit einem manuel Programmierten Timer diese zum leuchten gebracht. Nun will ich die Timer/Counter möglichkeiten die der ATmega16 mitbringt nutzen und habe dafuer folgendes Programm geschrieben welches lediglich den ersten PIN des PORTAs im Sekundentakt blinken lassen soll. Es blinkt jedoch nichts.. sondern die LED blinkt konstant weil die Variable "stop" anscheinend in "ISR nicht auf 0 gesetzt wird. Ich kann in ISR auch keinen Port schalten von daher habe ich das Gefühl das er garnicht erst ISR ausführt.. Hat jemand ne Idee woran es liegen könnte?.. danke im Voraus, Tobias. #include <avr/io.h> #include <avr/interrupt.h> #include <avr/wdt.h> volatile uint8_t z; volatile char stop = 1; void timer1_init() { z=0; //Schaltet zunächst alle Kontroll Register in TCCR1x aus TCCR1A=0; TCCR1B=0; //Schaltet das Zaehlregister zunaechst auf null, wobei es spaeter in abhaengigkeit von der internen Taktzahl, dem Prescaler und OCR1A // neu gesetzt wird. (Taktzahl/Prescaler_Takt/OCR1x = 11059000Hz/1024/250 //Ist letztendlich die Anzahl der Aufrufe des Interupts pro Sekunde, also: 43. Deshalb wird die Lampe alle 43 Aufrufe an und aus geschaltet. TCNT1=0; //Manipuliert den letztendlichen Takt OCR1A=250; //OCR1B=250; //Der Prescaler wird auf 1024 gesetzt und der Timer wird in den CTC-Mode gesetzt(WGM12) TCCR1B=(1<<CS10)|(1<<CS12)|(1<<WGM12); // aktiviere IRQ cnt1 TIMSK=(1<<OCIE1B)|(1<<OCIE1A); sei(); }; // ////////////////////////////////////////////////////////////////////// // Wartet etwa t*10 ms. // timer_10ms wird alle 10ms in der Timer1-ISR erniedrigt. // Weil es bis zum nächsten IRQ nicht länger als 10ms dauert, // wartet diese Funktion zwischen (t-1)*10 ms und t*10 ms. void xwait_10ms () { int i=0; for(i=0;i<2000;i++); } // ////////////////////////////////////////////////////////////////////// // Die Interrupt Service Routine (ISR). // In interrupt_num_10ms werden die IRQs gezählt. ISR(TIMER1_COMPA_vect) { #if 1 //PORTA ^= (1<<5); z++; if(z>=43) { stop ^= 1; z=0; } #endif } // ////////////////////////////////////////////////////////////////////// // Das Hauptprogramm: Startpunkt int main() { wdt_disable(); DDRA = 255; DDRD = 255; PORTA = 255; PORTD = 254; // Timer1 initialisieren timer1_init(); #if 1 while(1) { if ( stop == 1 ) { PORTA &= ~(1<<0); } else { PORTA |= (1<<0); } } #endif PORTD = 0; }
Dein Programm stürzt laufend ab, weil in TIMSK = (1<<OCIE1B)|(1<<OCIE1A); der Interrupt OCIE1B ohne die passende ISR(TIMER1_COMPB_vect) angeschaltet wird.
Zwei Dinge fallen zunächst auf:
1 | TIMSK=(1<<OCIE1B)|(1<<OCIE1A); |
Wenn Du beide Interrupts freigibst, müssen auch beide Interruptroutinen vorhanden sein, sonst hast Du einen garantierten Aufhänger gebaut. Es existiert in Deinem Code aber nur eine.
1 | void xwait_10ms () |
2 | {
|
3 | int i=0; |
4 | for(i=0;i<2000;i++); |
5 | }
|
Die Schleife wird wegoptimiert, da i nicht volatile ist. Es ergibt sich keine Verzögerung von 10 ms, sondern von 0. Nimm die Delay-Routinen der avr-libc. Weiter habe ich nicht geschaut.
ja aber die funktion xwait wird nicht benutzt und ist daher nicht zu beachten..
Ok ich hab den Teil nun geaendert: TIMSK=(1<<OCIE1A); Habe nicht gewusst das ich ihm damit sage Welche ISR Routine er starten soll.. aber es funktioniert leider trozdem noch nicht.. danke aber trozdem für die Info!
Die LED an PA0 soll also alle 1 s blinken. Das wäre wenn der Atmega16 mit 11059000Hz läuft. Wenn der AVR allerdings nur mit 1 MHz läuft (Werkseinstellung) ist die Blinkzeit ca. 11 s. Hast du mal nach der Codekorrektur so lange die laufende Schaltung beobachtet? Funktioniert die Ansteuerung der LED im statischen Fall (um Fehler im Aufbau auszuschliessen)?
ja also ich habe einen 11,059 Mhz Quarz laufen der den Takt angibt.. also ich habe die Schaltung konstant an und die LED geht wirklich nie an und aus sie leuchtet zu 100% konstant.
Tobias Neumann schrieb: > ja also ich habe einen 11,059 Mhz Quarz laufen der den Takt angibt.. Quarz allein in die Schaltung bauen reicht nicht. Schau dir den Artikel AVR Fuses an. > also ich habe die Schaltung konstant an und die LED geht wirklich nie an > und aus sie leuchtet zu 100% konstant. Wie lange beobachtet? LED von Anfang an vermeintlich dauerleuchtend passt zu einer /active high/ angeschlossenen LED und obigem Code inkl. Taktratenproblem. Ist deine LED active high angeschlossen?
Also ich hab den Quartz an XTAL1 und XTAL2 angeschlossen und der Quartz hat einen Takt von 11,059 Mhz, heißt das nicht das der Atmega16 dann mit dieser Taktung läuft? Entschuldige.. beschäftige mich erst seit einer Woche mit Microcontrollern :) Also ich habe es mind. 2 Min Beobachtet und an ist es seit Stunden.
Tobias Neumann schrieb: > Also ich hab den Quartz an XTAL1 und XTAL2 angeschlossen und der Quartz > hat einen Takt von 11,059 Mhz, heißt das nicht das der Atmega16 dann mit > dieser Taktung läuft? Entschuldige.. beschäftige mich erst seit einer > Woche mit Microcontrollern :) Reicht nicht siehe oben. > Also ich habe es mind. 2 Min Beobachtet und an ist es seit Stunden. Der Hinweis auf die notwendige Codeänderung kam doch erst vor ein paar Minuten. Hast du den Atmega16 noch nicht neu programmiert? Dann stürzt er weiterhin laufend ab.
Dann überprüf als erstes, ob die ISR überhaupt aufgerufen wird. Leg die Lampenmanipulation im Hauptprogramm still und schalte in der ISR einfach nur eine Lampe ein (oder als Gegentest aus). Lass dein Programm laufen und sieh nach, ob das tatsächlich passiert. Dann weißt du schon mal, ob die ISR überhaupt aufgerufen wird oder nicht.
Zum Thema Quarz Dieses Testprogramm
1 | #define F_CPU 11059000
|
2 | |
3 | #include <avr/io.h> |
4 | #include <utils/delay.h> |
5 | |
6 | int main() |
7 | {
|
8 | DDRA = 0xFF; |
9 | |
10 | while( 1 ) { |
11 | PORTA = 0xFF; |
12 | _delay_ms( 1000 ); |
13 | PORTA = 0x00; |
14 | _delay_ms( 1000 ); |
15 | }
|
16 | }
|
lässt deine Lampe blinken. Die Frage ist nur wie schnell? Ist die LED 1 Sekunde an / 1 Sekunde aus, dann läuft dein µC mit 11Mhz und der Quarz ist aktiv. Ist die LED 11 Sekunden an / 11 Sekunden aus, dann läuft dein µC mit 1Mhz und der QUarz ist nicht aktiv.
@ Stefan Die einzige Codeaenderung die ich bisher gemacht habe ist das ich TIMSK=(1<<OCIE1B)|(1<<OCIE1A); in TIMSK=(1<<OCIE1A); umgeschrieben habe. Danach habe ich das Program neu auf den MC gebrannt, ohne irgendwelche auswirkungen. Die LED an Port PA0 leuchtet weiterhin konstant. @Karl Heinz Ich habe versucht in der ISR Ports zu schalten. Ohne Erfolg, mir scheint es als ob die ISR garnicht aufgerufen wird!
@ Karl Heinz Habe das Test Programm aufgespielt und die LEDs gehen etwa alle 11 sekunden aus bzw an! Was soll ich nun tun? :)
Tobias Neumann schrieb: > @ Karl Heinz > > Habe das Test Programm aufgespielt und die LEDs gehen etwa alle 11 > sekunden aus bzw an! Was soll ich nun tun? :) Deinen µC so umstellen, dass er den Quarz auch benutzt http://www.mikrocontroller.net/articles/AVR_Fuses#Taktquellen_Fuse_Einstellung
@ Jo das ich meinen Quartz nicht benutze ist eine sehr hilfreiche Erkentniss, danke! Aber letztendlich löst es nicht mein Problem das die ISR nicht aufgerufen wird.. woran könnte das liegen?.. ich vermute schwer das es was mit dem übergebenen Argument von ISR zu tun hat!
Tobias Neumann schrieb: > @ Jo das ich meinen Quartz nicht benutze ist eine sehr hilfreiche > Erkentniss, danke! Aber letztendlich löst es nicht mein Problem das die > ISR nicht aufgerufen wird.. woran könnte das liegen?.. ich vermute > schwer das es was mit dem übergebenen Argument von ISR zu tun hat! ? Ich denke, die LED blinkt jetzt..dann muss doch die ISR aufgerufen werden...
Ja die LEDs haben nur in dem "Takt-Testprogramm" geblinkt.. aber dort wurde die ISR ja nicht benutzt. In meinem Programm besteht das Problem weiter!
Tobias Neumann schrieb: > @ Jo das ich meinen Quartz nicht benutze ist eine sehr hilfreiche > Erkentniss, danke! Aber letztendlich löst es nicht mein Problem das die > ISR nicht aufgerufen wird.. woran könnte das liegen?.. ich vermute > schwer das es was mit dem übergebenen Argument von ISR zu tun hat! Deine Vermutung ist falsch. An eine ISR werden keine Argumente übergeben. Aber speck doch dein Programm mal etwas ab. In diesem langen Programmwust findet man doch nichts mehr
1 | #include <avr/io.h> |
2 | #include <avr/interrupt.h> |
3 | #include <avr/wdt.h> |
4 | |
5 | |
6 | volatile uint8_t z; |
7 | volatile uint8_t stop = 1; |
8 | |
9 | ISR(TIMER1_COMPA_vect) |
10 | {
|
11 | z++; |
12 | if( z >= 40 ) |
13 | {
|
14 | stop ^= 1; |
15 | z = 0; |
16 | }
|
17 | }
|
18 | |
19 | int main() |
20 | {
|
21 | DDRA = 0xFF; |
22 | |
23 | TIMSK = (1<<OCIE1A); |
24 | OCR1A = 2500; |
25 | TCCR1B = (1<<CS10)/*|(1<<CS12)*/|(1<<WGM12); |
26 | |
27 | sei(); |
28 | |
29 | while(1) { |
30 | if ( stop == 1 ) |
31 | {
|
32 | PORTA = 0x00; |
33 | }
|
34 | else
|
35 | {
|
36 | PORTA = 0xFF; |
37 | }
|
38 | }
|
39 | }
|
Damit müsstest du schon ein Blinken sehen können
Hm wenn ich dies versuche auf meinen MC zu brennen habe ich einen sehr koischen Effekt beim AVR-dude: tobias@linux-zpyf:~/AVRprogramme/hello-atmega16> make brennen f=led avr-gcc -Wall -g -mmcu=atmega16 -DF_CPU=11059200 -c -o led.o led.c led.c:6:1: warning: "F_CPU" redefined <command line>:1:1: warning: this is the location of the previous definition In file included from led.c:9: /opt/cross/lib64/gcc/avr/4.1.2/../../../../avr/include/util/delay.h:90:3 : warning: #warning "Compiler optimizations disabled; functions from <util/delay.h> won't work as designed" avr-gcc led.o -o led avr-objcopy -j .text -j .data -O ihex led led.hex avrdude -u -e -c avrisp2 -P usb -p m16 -U flash:w:led.hex avrdude: AVR device initialized and ready to accept instructions Reading | ################################################## | 100% 0.01s avrdude: Device signature = 0x1e9403 avrdude: erasing chip avrdude: reading input file "led.hex" avrdude: input file led.hex auto detected as Intel Hex avrdude: writing flash (374 bytes): und danach passiert NICHTS mehr.. sehr komisch oder?
Tobias Neumann schrieb: > Hm wenn ich dies versuche auf meinen MC zu brennen Wenn du was auf deinen MC brennst. Das zuletzt gepostete Programm kann es nicht sein, denn > led.c:6:1: warning: "F_CPU" redefined > <command line>:1:1: warning: this is the location of the previous > definition weder habe ich eine F_CPU Definition im Programmtext, noch .... > warning: #warning "Compiler optimizations disabled; functions from > <util/delay.h> won't work as designed" wird <util/delay.h> includiert
Also ich habe nun folgendes Program versucht: #include <avr/io.h> #include <avr/interrupt.h> volatile uint8_t z; ISR(TIMER1_COMPA_vect) { z++; if(z>=40) { PORTA ^= 0xFF; z=0; } } int main() { z = 0; DDRA = 0xFF; TIMSK = (1<<OCIE1A); OCR1A = 2500; TCCR1B = (1<<CS10)|(1<<CS12)|(1<<WGM12); PORTA = 0x00; sei(); while(1); } Nachdem ich dies auf den MC gebrannt habe leuchtet der PORTA konstant. Habe quasi dein Programm noch ein bisschen abgespeckt und CS12 in TCCR1B gesetzt, jedoch ohne irgendwelche auswirkungen. danke schonmal ~ ~
PS: Dies sind meine Compileranweisungen avr-gcc -Wall -mmcu=atmega16 -c -o led2.o led2.c avr-gcc led2.o -o led2 avr-objcopy -j .text -j .data -O ihex led2 led2.hex avrdude -u -e -c avrisp2 -P usb -p m16 -U flash:w:led2.hex
Für mich ist nicht offensichtlich, was da schief läuft. Häng vielleicht das led2.hex an deine nächste Frage an, damit man es Disassemblieren (Linksammlung: Disassembler) oder Simulieren kann. Hast du selbst die Möglichkeit per (AVR-Simulation) das Programm im Einzelschritt zu debuggen?
Tobias Neumann schrieb: > tobias@linux-zpyf So einen Fall gab es hier letztens doch schonmal. Die mit den Linux-Distributionen mitgelieferten avr-gcc's sind wohl nicht alle up to date, und nicht alle funktionsfähig. Da wird dann einfach kein ISR-Vector eingetragen. Welche Version hat denn dein Compiler? Sinnvoll ist es auch, zunächst mal mit MFile ein makefile zu erstellen, und das zum comöilieren zu benutzen. Oliver
Hier Dein Quellcode und die im Simulator des AVR Studio funktionierende HEX-Datei für Atmega16 @ 11.0592 MHz. Bei 1 MHz sind die Blinkzeiten natürlich nicht 1 s sondern 11.0592 s.
Hallo, ich habe nun herausgefunden woran es damals gelegen hat. Es lag am Linker.. ich hab im Makefile nicht angegeben mit welchem Controller es der linker zu tun hat. Nachdem ich dann "LDFLAGS=-mmcu=atmega16" ins Makefile gepackt habe hat es dann funktioniert. Danke nochmal für alle Hilfe!
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.