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; }
> 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 | }
|
> 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 | }
|
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)
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?!
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.
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.
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 ?
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.
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.
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).
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...
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?
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.?
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.