Forum: Mikrocontroller und Digitale Elektronik AVRStudio6; Problem mit sei()


von Werner S. (wernerdu)


Lesenswert?

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)
  {
    //
  }
}

von Stefan E. (sternst)


Lesenswert?

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.

von Werner S. (wernerdu)


Lesenswert?

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)
  {
   //
  }
}

von Stefan W. (dl6dx)


Lesenswert?

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

von Werner S. (wernerdu)


Lesenswert?

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

von Stefan W. (dl6dx)


Lesenswert?

Bitte, gern.

Grüße

Stefan

von Bernd (Gast)


Angehängte Dateien:

Lesenswert?

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?

von Peter II (Gast)


Lesenswert?

bestimmt hast du eine ISR vergessen und der simualtor "bootet" neu. Gehe 
mal im ASM schrittweise durch.

von Bernd (Gast)


Lesenswert?

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?

von Peter II (Gast)


Lesenswert?

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?

von Bernd (Gast)


Lesenswert?

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?

von Peter II (Gast)


Lesenswert?

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.

von Bernd (Gast)


Lesenswert?

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 :-)

von Karl H. (kbuchegg)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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".

von Bernd (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.