Hallo, ich möchte mich nun doch mal in die Programierung mit C einarbeiten. Leider scheitere ich schon bei den ersten Zeilen... :-(. Bei folgenden Code sollte ich im Simulator ( AVRStudio6) doch ein gesetztes I-Flag im SREG erwarten; oder? Werner // ATMega 644P @ 20MHz #include <avr/interrupt.h> int Timer1Irq() { // return (0); } ISR(TIMER1_COMPA_vect) { Timer1Irq(); } int main() { sei(); while(1) { // } }
Werner S. schrieb: > Bei folgenden Code sollte ich im Simulator ( AVRStudio6) doch ein > gesetztes I-Flag im SREG erwarten; oder? Ja. Allerdings meine ich erst kürzlich auf AVFfreaks einen Thread gesehen zu haben, wo jemand ebenfalls das Problem hatte, dass der Simulator das I-Flag nicht korrekt angezeigt hatte. Also versteife dich nicht zu sehr darauf, das gesetzte Flag auch tatsächlich im Simulator zu sehen.
Stefan Ernst:
> ....Also versteife dich nicht zu sehr darauf, das gesetzte Flag auch >
tatsächlich im Simulator zu sehen.
Hallo,
habe dann einfach mal weitergemacht und den folgenden Code geschrieben,
leider lande ich nicht auf dem Breakpoint??
@Stefan Ernst:
Vielen Dank für den Hinweis auf AVRfreaks!
Manfred
// ATMega 644P @ 20MHz
#include <avr/interrupt.h>
int Timer1Irq()
{
//
return (0);
}
ISR(TIMER1_COMPA_vect)
{
Timer1Irq(); <------ BREAKPOINT
}
int main()
{
OCR1A = 1000; // compare value timer1 = 50µs
TCCR1A = 0; // switch to CTC-Mode..
TCCR1B = ((1<<WGM12)|(1<<CS10)); // ..top=CR1A; set prescaler to 1
TIMSK1 = 1 << OCIE1A; // interrupt by timer compareA match
sei();
while(1)
{
//
}
}
Werner S. schrieb: > int Timer1Irq() > { > // > return (0); > } > > ISR(TIMER1_COMPA_vect) > { > Timer1Irq(); <------ BREAKPOINT > } Das wird mit ziemlicher Sicherheit komplett wegoptimiert worden sein, weil der Code (aus Sicht des Compilers) kein Ergebnis hat, das den Aufruf der ISR überdauert ("toter Code"). Was du machen könntest wäre z.B.:
1 | #include <stdint.h> |
2 | #include <avr/io.h> |
3 | |
4 | volatile uint8_t t1count; |
5 | |
6 | ISR(TIMER1_COMPA_vect) |
7 | {
|
8 | t1count++; // da sollte ein Breakpoint möglich sein |
9 | }
|
10 | |
11 | void main(void) |
12 | {
|
13 | uint8_t ctmp; |
14 | |
15 | OCR1A = 1000; // compare value timer1 = 50µs |
16 | TCCR1A = 0; // switch to CTC-Mode.. |
17 | TCCR1B = ((1<<WGM12)|(1<<CS10)); // ..top=CR1A; set prescaler to 1 |
18 | TIMSK1 = 1 << OCIE1A; // interrupt by timer compareA match |
19 | |
20 | sei(); |
21 | |
22 | while(1) |
23 | {
|
24 | cli(); |
25 | ctmp = t1count; |
26 | sei(); |
27 | if(ctmp == 0) |
28 | {
|
29 | // hier irgendwas machen, z.B. ein Portbit toggeln...
|
30 | }
|
31 | }
|
Grüße Stefan
Hallo,
beim Ausprobieren von Stefans Code ist mir aufgefallen, daß
nach Benutzung von "Step Into" der Breakpoint nicht mehr angesprungen
wurde.
Die Lösung war: Tools -> Options -> Debugger -> Mask interrupts while
stepping = FALSE einzustellen.
Nun funktioniert auch mein ursprünglicher Code (incl. I_Flag).
Der Optimization Level ist übrigens egal, sofern man den Debug Level
> 2 stellt.
Nun mache ich erst mal weiter....
@Stefan
Danke für Deine Mühe
Werner
Hallo, habe auch das Problem und nutze daher diesen Thread. Wenn ich den Quellcode emulieren will, dann wird das I_Flag nicht gesetzt und der Vorgang wiederholt sich wieder bei cli();. Auf den uC kann ich das zwar überspielen, aber der macht nicht das, was ich haben will. Hat jmd noch einen Tipp?
bestimmt hast du eine ISR vergessen und der simualtor "bootet" neu. Gehe mal im ASM schrittweise durch.
Peter II schrieb: > bestimmt hast du eine ISR vergessen und der simualtor "bootet" neu. Gehe > mal im ASM schrittweise durch. Hey, danke für dir schnelle Antwort. Ich kann das Problem etwas eingrenzen, dazu folgender Quellcode-Ausschnitt: void Timer1Init(void) { TCCR1A =0x00; TIMSK1 |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B); EIMSK |= (1<<INT1); EICRA |= (1<<ISC00) | (1<<ISC01); OCR1A = 20000; OCR1B = 20000; ICR1 = 0x4e20; TCCR1B |= (1<<CS11); } wenn ich die Register TIMSK1, EIMSK, EICRA und TCCR1B als hex-Zahlen ausschreibe, dann funktioniert das Programm einwandfrei, nur nicht, wenn ich die Register direkt zuweise. Hast du dafür eine Idee?
welche Hexzahlen schreibst du dann hin? brauchst doch nur in das LSS file zu schauen, dort steht immer der ausgerechnete wert drin - ist der identich mit deinem Hex Wert?
Hi Peter II; hier zum Vergleich void Timer1Init(void) { TCCR1A =0x00; TIMSK1 |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B); EIMSK |= (1<<INT1); EICRA |= (1<<ISC00) | (1<<ISC01); OCR1A = 20000; OCR1B = 20000; ICR1 = 0x4e20; TCCR1B |= (1<<CS11); } void Timer1Init(void) { TCCR1A = 0x00; TIMSK1 = 0x07; EIMSK |= 0x01; EICRA |= 0x03; OCR1A= 20000; OCR1B= 20000; ICR1 = 0x4e20; TCCR1B = 0x02; } Wenn ich den oberen durch den unteren tausche, läuft es. Das mit der LSS file hab ich nicht verstanden, sry. Was meinst damit genau?
Das: > TIMSK1 |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B); und das: > TIMSK1 = 0x07; sind aber 2 verschiende dinge? einmal überschreibst du TIMSK1 und einmal fügst du nur bits hinzu. Was steht voher in TIMSK1 drin? Die werte habe nicht geprüft.
Hi, entschuldige das missverständnis, entweder verwende ich den oberen oder den unteren Quellcode; es wird nichts überschrieben. Dieser Tipp von dir war der entscheidende "bestimmt hast du eine ISR vergessen und der simualtor "bootet" neu. Gehe mal im ASM schrittweise durch." -->EIMSK |= (1<<INT1); es muss heißten -->EIMSK |= (1<<INT0); Ich hab das durcheinander gebracht, jetzt laufen beide! Danke für deine Mühe, hat mir Zeit erspart :-)
Bernd schrieb: > Hi Peter II; > hier zum Vergleich > void Timer1Init(void) > { > TCCR1A =0x00; > TIMSK1 |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B); > EIMSK |= (1<<INT1); > EICRA |= (1<<ISC00) | (1<<ISC01); > OCR1A = 20000; > OCR1B = 20000; > ICR1 = 0x4e20; > TCCR1B |= (1<<CS11); > } > void Timer1Init(void) > { > TCCR1A = 0x00; > TIMSK1 = 0x07; > > EIMSK |= 0x01; > EICRA |= 0x03; > > OCR1A= 20000; > OCR1B= 20000; > ICR1 = 0x4e20; > > TCCR1B = 0x02; > } > Wenn ich den oberen durch den unteren tausche, läuft es. Dann hast du höchst wahrscheinlich im Projekt den falschen Prozessor eingestellt. Denn der Compiler macht ja auch nichts anderes, als aus den Bitnamen die Hex-Werte ausrechnen. Dazu benutzt er vordefinierte Konstanten, die auf den jeweiligen Prozessortyp abgestimmt sind und in aus den Include-Files kommen. Im Include File steht zb #define TOIE1 0 #define OCIE1A 1 #defien OCIE1B 2 Um zb > TIMSK1 |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B); zu übersetzen, rechnet der Compiler den Ausdruck rechts aus und kommt zum Ergebnis, dass da 0x07 rauskommt. Endgültig compiliert wird daher dann TIMSK1 |= 0x07; Also, bis auf die Verorderung, dasselbe was du auch mit TIMSK1 = 0x07; hinschreibst. Aber: Bei einem anderen Prozessor mag zb OCIE1B nicht mehr das Bit 2 sondern das Bit 4 sein. Als C Programmierer brauchst du dann bei TIMSK1 |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B); überhaupt nichts machen. Durch das andere #define im Include-File #define OCIE1B 4 rechnet der COmpiler die geänderte Konstante aus und compiliert TIMSK1 |= 0x13; Schreibst du selbst aber im Original TIMSK1 = 0x07; dann darfst du nicht vergessen, bei einem anderne µC diese Konstante anzupassen. Und daher ist die Variante mit den Bitnamen zu bevorzugen - wenn dir der COmpiler Arbeit abnehmen kann, dann lass ihn das machen. Die Kehrseite der Medaille: Wenn das Include File für einen falschen Prozessor benutzt wird, dann sind die #define für die Bitnamen falsch. Stimmen also die Ergebnisse für Bitnamen nicht mit dem überein, was du selbst als Hex-Zahlen ermittelt hast, dann gibt es 3 Möglichkeiten * entweder sind die Include Files falsch (ist unwahrscheinlich, das wäre schon vor dir jemandem aufgefallen) * Du hast dich bei der Ermittlung der Bits vertan * oder du hast den falschen µC (und damit die falschen Include Files) eingestellt. Letzterer Fall ist der Häufigere.
Bernd schrieb: > Hi, > entschuldige das missverständnis, entweder verwende ich den oberen oder > den unteren Quellcode; es wird nichts überschrieben. doch wird es das sind 2 verschinde dinge die du machst: > TIMSK1 |= (1<<TOIE1) | (1<<OCIE1A) | (1<<OCIE1B); > TIMSK1 = 0x07; einmal ist es eine zuweisung einmal eine "voroderung".
Ok, vielen Dank an Karl Heinz und Peter II, werd es für nächste Male berücksichtigen.
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.