Forum: Mikrocontroller und Digitale Elektronik ISR: wird nicht aufgerufen?!


von Cihan (Gast)


Lesenswert?

Hallo,

ich bin langsam am verzweifeln, versuche eine Uhr zu programmieren und 
die sekunden per uart im terminal auszugeben. Habe ein Atmega128 mit 2 
Quarzen. Ein RTC Uhrenquarz 32,768 KHz und ein 16 MHz Quarz.

Nun zum Problem:
Habe die Uart schon programmiert und getestet, funktioniert auch soweit.
Im Prinzip aktiviere ich in der main Funktion die globalen Interrupts 
und starte dann die Funktion Starten(). In der wird die Einstellung für 
den Timer 0 verarbeitet, meiner Meinung nach ist alles auch OK, 
zumindest mit dem Sekundentakt.

Wenn ich nun mir die Ausgabe auf dem Terminal angucke, bekomme ich jede 
Sekunde den Wert für a (Variable für die Sekundenzählung), doch sie ist 
immer 0. Ich vermute, dass die ISR nicht aufgerufen wird und somit a nie 
größer wird.

Werde daraus nicht weiter schlau, hoffe ihr könnt mir helfen.

Danke im voraus.

#include <avr/io.h>
#include <avr/interrupt.h>
#include <stdlib.h>
#include <stdio.h>
#include <math.h>

#define FOSC 16000000  //Quarzfrequenz
#define BAUD 9600  //Baudrate
#define MYUBRR FOSC/16/BAUD-1  //Werte für UBRR Register

volatile uint8_t a;
char b[10];

void USART0_Init( unsigned int ubrr ) {
  //Baudrate setzen
  UBRR0H = (unsigned char)(ubrr>>8);
  UBRR0L = (unsigned char)ubrr;

  //Sender aktivieren
  UCSR0B = (1<<TXEN0)|(1<<RXEN0);

  //Frame Format setzen: 8data, 2stop bit */
  UCSR0C = (0<<USBS0)|(1<<UCSZ01)|(1<<UCSZ00);
}

void USART0_Transmit( unsigned char data ) {
  //warten bis Sendepuffer leer
  while ( ! (UCSR0A & (1<<UDRE0)) );

  //Daten in Puffer und senden
  UDR0 = data;
}

/* puts ist unabhaengig vom Controllertyp */
void USART0_Transmit_string (char *s)
{
    while (*s)
    {   /* so lange *s != '\0' also ungleich dem 
"String-Endezeichen(Terminator)" */
        USART0_Transmit(*s);
        s++;
    }
}

ISR(TIMER0_OVF_vect) //overflow interrupt vector
{
  a++;
}

void starten(void)
  {
    TIMSK &=~((1<<TOIE0)|(1<<OCIE0));     //Disable TC0 interrupt
    ASSR |= (1<<AS0);           //set Timer/Counter0 to be asynchronous 
//from the CPU clock with a second external clock(32,768kHz)driving it.
    TCNT0 = 0x00;
    TCCR0 |= ((1<<CS02) | (1<<CS00));
    while(ASSR&0x07);           //Wait until TC0 is updated
    TIMSK |= (1<<TOIE0);
  }

int main( void )
{
  USART0_Init ( MYUBRR ); //USART initialisieren

  sei(); //Interrupts aktivieren

  starten();

  itoa( a, b, 10 );
  USART0_Transmit_string(b);

  while(1){
  }
  return 0;
}

von Karl H. (kbuchegg)


Lesenswert?

> Wenn ich nun mir die Ausgabe auf dem Terminal angucke,
> bekomme ich jede Sekunde den Wert für a


aber nicht mit dem Code. Das ist völlig unmöglich (es sei denn, dein µC 
wird ständig resettet und fängt das Programm jedes mal wieder von vorne 
an

> int main( void )
> {
>   USART0_Init ( MYUBRR ); //USART initialisieren
>
>   sei(); //Interrupts aktivieren
>
>   starten();
>
>   itoa( a, b, 10 );
>   USART0_Transmit_string(b);
>
>   while(1){
>   }
>   return 0;
> }

Du lässt dir EINMAL den Wert für a ausgeben und danach passiert in der 
Hauptschleife nix mehr. Wie willst du denn da beobachten, wie sich a 
verändert?
1
int main( void )
2
{
3
  USART0_Init ( MYUBRR ); //USART initialisieren
4
5
  sei(); //Interrupts aktivieren
6
7
  starten();
8
9
  while(1){
10
    itoa( a, b, 10 );
11
    USART0_Transmit_string(b);
12
  }
13
  return 0;
14
}

von Karl H. (kbuchegg)


Lesenswert?

> void starten(void)
>   {
>     TIMSK &=~((1<<TOIE0)|(1<<OCIE0));     //Disable TC0 interrupt
>     ASSR |= (1<<AS0);           //set Timer/Counter0 to be asynchronous
> //from the CPU clock with a second external clock(32,768kHz)driving it.
>     TCNT0 = 0x00;
>     TCCR0 |= ((1<<CS02) | (1<<CS00));
>     while(ASSR&0x07);           //Wait until TC0 is updated
>     TIMSK |= (1<<TOIE0);
>   }

Machs doch für deine ersten Gehversuche nicht komplizierter als 
notwendig
1
void starten(void)
2
{
3
  TCCR0 = ((1<<CS02) | (1<<CS00));
4
  TIMSK = (1<<TOIE0);
5
}

von Klaus T. (gauchi)


Lesenswert?

Ehrlich gesagt wundert mich, dass Du überhaupt mehr als eine Zeile 
Ausgabe bekommst, denn für meine Begriffe wird da nur einmal was 
ausgegeben (und das sollte 0 sein).

Ich vermute daher, dass dein Controller jede Sekunde resetted, 
möglicherweise ist da irgendwo der falsche Interrupt aktiviert (ich hab 
das jetzt nicht geprüft, nur ne Idee, wo man weitersuchen könnte)

von Cihan (Gast)


Lesenswert?

jede sekunde zu resetten ist ja auch gewollt, durch den Timer0 mit der 
Funktion starten(). Das macht er auch jede sekunde, nur erhöht er den 
Wert von a nicht, also kein Aufruf von ISR, oder?!

von Karl H. (kbuchegg)


Lesenswert?

Cihan schrieb:
> jede sekunde zu resetten ist ja auch gewollt

jede Sekunde resetten kann nicht gewollt sein.

Reset ist, wie wenn du den Strom abdrehst und wieder neu einschaltest.

von Stefan E. (sternst)


Lesenswert?

Cihan schrieb:
> Wenn ich nun mir die Ausgabe auf dem Terminal angucke, bekomme ich jede
> Sekunde den Wert für a (Variable für die Sekundenzählung), doch sie ist
> immer 0.

3 Möglichkeiten für dieses Verhalten (Reset jede Sekunde) bei obigen 
Source-Code:
1) M103C Fuse ist gesetzt.
2) Code wurde für falschen Controller kompiliert/gelinkt.
3) Die ELF-Datei wurde auf den Chip geladen.

von Cihan (Gast)


Lesenswert?

Dann mal anderherum beschrieben. Versuche eine einfache uhr zu 
programmieren. lese schon seit 2 - 3 Tagen mir die Threads zu 
Uhrenprogrammierung durch und habe auch schon die Tutorien durch.

Habe es so verstanden, dass ich mit den Uhrenquarz jede Sekunde einen 
interrupt werfen muss, sodass dadurch die variable a sich verändert.

Verstehe ich da etwas falsch ?

von Cihan (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Cihan schrieb:
>> Wenn ich nun mir die Ausgabe auf dem Terminal angucke, bekomme ich jede
>> Sekunde den Wert für a (Variable für die Sekundenzählung), doch sie ist
>> immer 0.
>
> 3 Möglichkeiten für dieses Verhalten (Reset jede Sekunde) bei obigen
> Source-Code:
> 1) M103C Fuse ist gesetzt.
> 2) Code wurde für falschen Controller kompiliert/gelinkt.
> 3) Die ELF-Datei wurde auf den Chip geladen.

zu 1) ist nicht gesetzt, habe einen Bootloader per ISP raufgeladen und 
habe nur Bootrst oder so gesetzt gehabt

zu 2 und 3 bräuchte ich nähere informationen was du evtl. meinst.

Danke aber für die schnellen antworten.

von Stefan E. (sternst)


Lesenswert?

Cihan schrieb:
> zu 1) ist nicht gesetzt, habe einen Bootloader per ISP raufgeladen und
> habe nur Bootrst oder so gesetzt gehabt

Dann kommt noch dazu:
4) Bootloader benutzt Interrupts, und Vectoren wurden nicht wieder in 
den App-Bereich verschoben.

Cihan schrieb:
> zu 2 und 3 bräuchte ich nähere informationen was du evtl. meinst.

Zeige einfach mal, wie du die Datei generierst, die dann auf den Chip 
geladen wird.

von Stefan E. (sternst)


Lesenswert?

Cihan schrieb:
> Verstehe ich da etwas falsch ?

Nö, aber Interrupt ist nicht das Gleiche wie Reset. Und bei deinem Code 
oben (wenn denn der Reset nicht wäre) würdest du eine Veränderung von a 
gar nicht mitbekommen, weil ... (siehe Post von Karl Heinz Buchegger).

von Cihan (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Cihan schrieb:
>> zu 1) ist nicht gesetzt, habe einen Bootloader per ISP raufgeladen und
>> habe nur Bootrst oder so gesetzt gehabt
>
> Dann kommt noch dazu:
> 4) Bootloader benutzt Interrupts, und Vectoren wurden nicht wieder in
> den App-Bereich verschoben.
>
> Cihan schrieb:
>> zu 2 und 3 bräuchte ich nähere informationen was du evtl. meinst.
>
> Zeige einfach mal, wie du die Datei generierst, die dann auf den Chip
> geladen wird.

Im Prinzip habe bei mit AVR Studio den Controller ausgewählt, in die 
Linker Options -Ttext=0x1800 eingefügt, laut Infoblatt Hersteller.

Anschließend Compeliere ich die ganze Sache und lade die hex file über 
ein externes Programm (vom Hersteller) auf den flash rauf.

Ich muss nebenbei vielleicht mal erwähnen was ich vor habe, mein 
aktuelles Projekt beinhaltet grad die Kommunikation zwischen einem 
Gsm-Modem und dem µC. Das habe ich schon fertig und funktioniert auch. 
Weiter habe ich noch einen LCD zu programmieren, bei dem auch alles 
fertig ist und funktioniert.

Der nächste schritt ist es ebend die RTC Funktion zu nutzen, ebend eine 
Uhr letztendlich daraus zu erstellen.

Hier nochmal das was ich besitze:
http://shop.chip45.com/epages/es10644620.sf/de_DE/?ObjectPath=/Shops/es10644620/Products/Crumb128-5.0/SubProducts/crumb128-5.0-14

Weiterhin nutze ich bei der Konfigruation unter AVR Studio unter Custom 
Options die avr-gcc und make vom Winavr.

Hoffe das hilft weiter...

von Stefan E. (sternst)


Lesenswert?

Cihan schrieb:
> in die
> Linker Options -Ttext=0x1800 eingefügt, laut Infoblatt Hersteller.

Wenn der Hersteller nicht ganz besondere Vorkehrungen getroffen hat, 
kann so auch kein Interrupt funktionieren. Wozu soll das gut sein?

von Cihan (Gast)


Lesenswert?

Stefan Ernst schrieb:
> Cihan schrieb:
>> in die
>> Linker Options -Ttext=0x1800 eingefügt, laut Infoblatt Hersteller.
>
> Wenn der Hersteller nicht ganz besondere Vorkehrungen getroffen hat,
> kann so auch kein Interrupt funktionieren. Wozu soll das gut sein?

das ist eine gute frage und auch berechtigt. Ich weiss nicht warum ich 
dies in die linker optionen mit rein genommen habe, finde es jetzt auf 
anhieb auch nicht mehr, aber ohne dieses funktioniert es, die sekunden 
zählen hoch.

Allerdings muss ich die Ausgabe in der ISR machen.

Nun stellt sich die Frage für mich wie mein Programm weiter ablaufen 
wird. Möchte ja dass er mir die Uhrfunktionermöglicht, also jede sekunde 
ein interrupt, möchte aber zugleich alle anderen funktionen nutzen, mit 
anderen worten bspw. kommunikation zwischen Gsm und µc und auch 
LC-Display.

Das sollte doch ohne weiteres alles möglich sein.?

von Cihan (Gast)


Lesenswert?

Hat sich geklärt, danke nochmals an alle beteiligten.

gruß Cihan

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.