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.
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
voidxwait_10ms()
2
{
3
inti=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.
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.
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!
@ 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...
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
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
~
~
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!