Hallo Ich habe ein ATmega32 Prototype Board. und da wollte ich einen ganz einfachen Interrupt machen aber da hängt sich der Controller immer auf. MCUCR |= (1<<ISC01); MCUCR &= ~(1<<ISC00); GIMSK |= (1<<INT0); ISR (INT0_vect) { rprintf("AT+CMSS=3\r\n"); } kann mir da jemand behilflich sein? mfg Matthias Drexler
Üblicherweise ist der Aufruf von komplexen Funktionen in Interrupts zu vermeiden. Dafür gibt es im Einzelfall natürlich bestimmte Gründe. Diese gezielt darzulegen ist hier aber nicht möglich, da Details fehlen. Falls die Ausgabe mittels rprintf selbst Interrupts benutzt, bestehen vielfältige Möglichkeiten, warum das nicht funktioniert. Nicht zuletzt die Tatsache, dass, während eine Interruptroutine abgearbeitet werden, keine weiteren Interrupts behandelt werden können. (Was nichts damit zu tun hat, das jeweils ein Interrupt zumindest in dem jeweiligen Interrupt-Flag gespeichert wird). Ich empfehle Dir, in der Interrupt Routine lediglich eine Variable zu setzen, dies Flag in einer Endlos-Schleife in der Funktion main abzufragen und falls es gesetzt ist, die Ausgabe zu machen.
Hallo Klaus Wenn ich zum beispiel den PORTB auf high setze so dass dann LED´s brennen hängt er ich auch auf..... welche details würden dir denn fehlen? mfg Matthias
Abgesehen vom Programm selbst wäre es interessant zu wissen, woran Du denn genau merkst, das der uC sich "aufhängt". Gerade in diesem Bereich gibt es sehr viele Missverständnissse.
wenn ich am PD2 also am INT0 einen auf GND gehe dann bleibt die LCD anzeige und meine leds einfach stehen.
>wenn ich am PD2 also am INT0 einen auf GND gehe dann bleibt die LCD >anzeige und meine leds einfach stehen. Aha. Nun gut. Poste bitte den Code.
Vielleicht wäre es gut, wenn Du auch mal schreibst, was Du an Messmitteln hast, die Schaltung, Deine Vorkenntnisse (formal und/oder autodidaktisch angeeignete).
#include <avr/io.h> #include "global.h" // include our global settings #include "i2cmaster.h" // Auskommentieren, falls nicht benötigt... #include "lcd.h" #include <avr/interrupt.h> #include <avr/wdt.h> #include "string.h" #include "timer.h" #include <stdlib.h> #include <stdio.h> #include "usart.h" #define USE_LCD 1 // 1 Falls LCD verwendet wird void init(void) { wdt_disable(); // Watchdog ausschalten // Port B initialisieren DDRB= 0xFF; // alle 8 pins sind als Ausgang geschaltet // Port A initialisieren DDRA= 0x00; // alle 8 pins sind als Eingänge geschaltet PORTB= 0x00; // Alle unteren Pins sind low timer0Init(); /* Mit diesem Befehl wird die include-Datei timer initialisiert, die uns u.a. den Befehl timerPause() zur Verfügung stellt. */ i2c_init(); // Initialisierung des I2C-Busses sei(); // Interrupts zulassen (für timer.c wichtig) #if USE_LCD lcd_init(LCD_DISP_ON); #endif lcd_clrscr(); // LCD löschen MCUCR |= (1<<ISC01);//Interrupt löst bei fallender Flanke aus MCUCR &= ~(1<<ISC00); GIMSK |= (1<<INT0); //Interrupt_1 einschalten uartInit(); // initialize the UART (serial port) uartSetBaudRate(9600); // serielle Schnittstelle auf 19200 Baud setzen rprintfInit(uartSendByte); lcd_puts("\nStarte Programm!"); timerPause(3000); } int main (void) { init(); while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich */ { } rprintf("AT+CMSS=5\r\n"); timerPause(1000); lcd_clrscr(); // LCD löschen lcd_puts("Programm bereit!"); timerPause(3000); while(1) { .............. ................. } } ISR (INT0_vect) { rprintf("AT+CMSS=3\r\n"); }
messmittel is a Multimeter. schaltung is a bisschen schwer zu posten und was meinst du mit vorkenntnisse?
Bitte vollständigen, compilierbaren Code posten. Falls Du das aus irgendwelchen Gründen nicht willst, dann reduziere den Code, aber auf jeden Fall so, dass das Problem noch auftritt. In dem geposteten Code ist jedenfalls, bis auf die fehlerhafte Verwendung einer komplexen Funktion mit vermutlich Interrupt-Abhängigkeiten, nichts weiter erkennbar. Ausserdem werden hier nirgendwo Ports verändert, so das diese Aussage >wenn ich am PD2 also am INT0 einen auf GND gehe dann bleibt die LCD >anzeige und meine leds einfach stehen. nicht nachvollziehbar ist. Im Zweifel, was wie gepostet und beschrieben werden sollte, siehe: http://www.mikrocontroller.net/articles/Netiquette Ausserdem fehlen noch die Angaben zu: >Vielleicht wäre es gut, wenn Du auch mal schreibst, was Du an >Messmitteln hast, die Schaltung, Deine Vorkenntnisse (formal und/oder >autodidaktisch angeeignete).
MCUCR |= (1<<ISC01);//Interrupt löst bei fallender Flanke aus MCUCR &= ~(1<<ISC00); Müsste da nicht entweder zweimal ISC01 oder zweimal ISC00 hin? Wie schnell nach erscheinen von Starte Prorgramm löst du den Interrupt aus? wenn der noch in der timerpause funktion hängt, geht dass nicht? gruß Jonas
//////////////////////////////////////////////// //INTerrupt konfigurieren MCUCR |= (1<<ISC01); // Int auslösen bei fallender Flanke EIMSK |= (1<<INT0); // External Interrupt 0 Enable PIN PD2 //Globale Interrupts einschalten sei(); Gerade kopiert aus einem anderen Thread, sollte funktionieren... gruß Jonas
Das hat sich jetzt überschnitten. Bin ein langsamer Schreiber: >messmittel is a Multimeter. >schaltung is a bisschen schwer zu posten und was meinst du mit >vorkenntnisse? Was ist das Problem beim Posten der Schaltung? Vorkenntnisse: Angaben darüber welche Kenntnisse Du hast. Das kann man auf verschiedene Weise beschreiben: z.B. Formal: Studium Bachelor Informatik, Lehre Informationselektroniker, Informell: Autodidaktisch ca. 10 Jahre Erfahrung etcpp. Anders gefragt: Was von dem folgende hast Du schonmal realisiert. D.h. den Code vollständig selbst geschrieben. Nicht ob Du einzelne Teile aus Tutorials kopiert hast. 1. LED blinken lassen 2. Delay mit Timern 3. Tastenentprellung 4. Tasten- oder LED-matrix 5. LCD Ansteuerung 6. RS232 Kommunikation Es geht nur darum einen Eindruck zu bekommen, was man voraussetzen kann.
jonas biensack schrieb: >> MCUCR |= (1<<ISC01);//Interrupt löst bei fallender Flanke aus >> MCUCR &= ~(1<<ISC00); >Müsste da nicht entweder zweimal ISC01 oder zweimal ISC00 hin? Wohin müsste das zweimal. Bei Triggern auf fallender Flanke können ISC01 und ISC00 jedenfalls nicht auf den selben Wert gesetzt werden. >MCUCR |= (1<<ISC01); // Int auslösen bei fallender Flanke Dazwischen gibt es keine Unterschied, solange ISC00 im Programmlauf sonst nicht manipuliert wird. Der Default-Wert von ISC00 ist ohnehin 0. >EIMSK |= (1<<INT0); // External Interrupt 0 Enable PIN PD2 Das Register EIMSK gibt es beim ATMega32 garnicht. Genauso wie das im Code vorkommende Register GIMSK. Dagegen wird in dem Codebruchstück GICR nicht geändert. Deswegen Frage nach dem vollständigen, compilierbaren Code. Genauso wie nach den Vorkenntnissen.
Alles in allem drängt sich der Verdacht auf, das beim Compilieren die falsche CPU gesetzt ist, sonst gäbe es Fehlermeldungen.
#include <avr/io.h> #include "global.h" // include our global settings #include "i2cmaster.h" // Auskommentieren, falls nicht benötigt... #include "lcd.h" #include <avr/interrupt.h> #include <avr/wdt.h> #include "string.h" #include "timer.h" #include <stdlib.h> #include <stdio.h> #include "usart.h" #ifndef F_CPU /* In neueren Version der WinAVR/Mfile Makefile-Vorlage kann F_CPU im Makefile definiert werden, eine nochmalige Definition hier wuerde zu einer Compilerwarnung fuehren. Daher "Schutz" durch #ifndef/#endif Dieser "Schutz" kann zu Debugsessions führen, wenn AVRStudio verwendet wird und dort eine andere, nicht zur Hardware passende Taktrate eingestellt ist: Dann wird die folgende Definition nicht verwendet, sondern stattdessen der Defaultwert (8 MHz?) von AVRStudio - daher Ausgabe einer Warnung falls F_CPU noch nicht definiert: */ #warning "F_CPU war noch nicht definiert, wird nun nachgeholt mit 14756000" #define F_CPU 14756000UL // Systemtakt in Hz - Definition als unsigned long beachten // Ohne ergeben sich unten Fehler in der Berechnung #endif #define BAUD 9600UL // Baudrate // Berechnungen #define UBRR_VAL ((F_CPU+BAUD*8)/(BAUD*16)-1) // clever runden #define BAUD_REAL (F_CPU/(16*(UBRR_VAL+1))) // Reale Baudrate #define BAUD_ERROR ((BAUD_REAL*1000)/BAUD) // Fehler in Promille, 1000 = kein Fehler. #if ((BAUD_ERROR<990) || (BAUD_ERROR>1010)) #error Systematischer Fehler der Baudrate grösser 1% und damit zu hoch! #endif void init(void) { wdt_disable(); // Watchdog ausschalten DDRD &= ~(1<<PD2); // Port B initialisieren DDRB= 0xFF; // alle 8 pins sind als Ausgang geschaltet // Port A initialisieren DDRA= 0x00; // alle 8 pins sind als Eingänge geschaltet PORTB= 0x00; // Alle unteren Pins sind low (Ruhestellung) timer0Init(); /* Mit diesem Befehl wird die include-Datei timer initialisiert, die uns u.a. den Befehl timerPause() zur Verfügung stellt. */ i2c_init(); // Initialisierung des I2C-Busses sei(); // Interrupts zulassen (für timer.c wichtig) #if USE_LCD lcd_init(LCD_DISP_ON); #endif lcd_clrscr(); MCUCR |= (1<<ISC01); // Int auslösen bei fallender Flanke GICR |= (1<<INT0); // External Interrupt 0 Enable PIN PD2 // MCUCR |= (1<<ISC01);//Interrupt löst bei fallender Flanke aus // MCUCR &= ~(1<<ISC00); // GIMSK |= (1<<INT0); //Interrupt_1 einschalten uartInit(); // initialize the UART (serial port) uartSetBaudRate(9600); // serielle Schnittstelle auf 19200 Baud setzen rprintfInit(uartSendByte); lcd_puts("\nStarte Programm!"); timerPause(3000); } // Ende init int main (void) { init(); while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich { } rprintf("AT+CMSS=5\r\n"); timerPause(1000); lcd_clrscr(); lcd_puts("Programm bereit!"); timerPause(3000); while(1) { lcd_clrscr(); PORTB = (1<<PB0); timerPause(300); lcd_clrscr(); lcd_puts("\xFF\xFF\xFF\xFF\xFF"); PORTB = (1<<PB1); timerPause(300); lcd_clrscr(); lcd_puts("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"); PORTB = (1<<PB2); timerPause(300); lcd_clrscr(); lcd_puts("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF") ; PORTB = (1<<PB3); timerPause(300); lcd_clrscr(); lcd_puts("\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x FF\xFF\xFF\xFF\xFF"); } } ISR (INT0_vect) { PORTB = 0xFF; timerPause(100); PORTB = 0x00; timerPause(100); PORTB = 0xFF; timerPause(100); // rprintf("AT+CMSS=3\r\n"); }
ich bin angehender Techniker in Kommunikationstechnik. und das ist eigentlich nur mein hobby schaltungen zu programmieren und zu bauen.
>und das mit dem GICR funktioniert auch nicht
Was heisst, "es funktioniert" nicht?
Es gibt einen "richtigen" Weg und einen "falschen". Rumprobieren hilft
Dir nicht weiter. Erwarte auch nicht von jeder einzelnen Maßnahme für
sich, das sie gleich eine Verbesserung bringt.
Wenn Du klagst das Dein Auto nicht fährt und Du auf einen Rat hin Benzin
nachfüllst und es immer noch nicht fährt, dann entfernst Du ja auch
nicht das Benzin, "weil es nicht geholfen hat". Es kommt oft vor, das
mehrere Ursachen gemeinsam eine Funktion verhindern.
Abgesehen davon:
Du hättest eigentlich Fehlermeldungen erhalten müssen. Was ist mit der
Einstellung der CPU?
Delays in interruptroutinen sind genauso "falsch" wie Aufruf von
rprintf.
Bitte mach es so, wie schon beschrieben. Flag setzen und in main
abfragen.
>Es kommt oft vor, das mehrere Ursachen gemeinsam eine Funktion verhindern.
Das sollte vielmehr heissen:
Es kommt oft vor, das mehrere Ursachen jeweils für sich eine Funktion
verhindern.
Ausserdem lässt sich der Code schon wegen einfachen syntaktischen Fehlern nicht kompilieren. In der Zeile:
1 | while (!(UCSRA & (1<<UDRE))) /* warten bis Senden moeglich |
fehlt das Ende des Kommentars. Auch in den nachfolgenden Zeilen taucht das fehlende */ nicht auf. Bitte gib Dir Mühe wirklich compilierbaren Code zu posten. Am besten nimm die Datei(en) und kopiere sie in ein anderes Verzeichnis und mach ein neues Projekt im AVRStudio (vorausgesetzt das verwendest Du). Tu so als wenn Du wir wärst und nur das hättest, was hier gepostet wurde.
Füge ich den Kommentar ein, dann kommen noch mehr Fehlermeldungen: rm -rf Drexler.o Drexler.elf dep/* Drexler.hex Drexler.eep Drexler.lss Drexler.map avr-gcc -mmcu=atmega32 -Wall -gdwarf-2 -Os -std=gnu99 -funsigned-char -funsigned-bitfields -fpack-struct -fshort-enums -MD -MP -MT Drexler.o -MF dep/Drexler.o.d -c ../Drexler.c ../Drexler.c:2:55: error: global.h: No such file or directory ../Drexler.c:3:69: error: i2cmaster.h: No such file or directory ../Drexler.c:4:17: error: lcd.h: No such file or directory ../Drexler.c:8:19: error: timer.h: No such file or directory ../Drexler.c:11:19: error: usart.h: No such file or directory
Schön für Dich. Was lerne ich also hier über Dich? 1. Es lohnt sich nicht Dir Fragen zu stellen. Du antwortest nicht oder erst nach Erklärung von Begriffen des eigentlichen Grundwortschatzes. Z.B. "Vorkenntnisse". 2. Du postest keinen compilierbaren Code. 3. Du setzt Anregungen nicht um. 4. Auf Erklärungen reagierst Du nicht. 5. Wenn Du dann die Lösung findest, teilst Du sie nicht mit uns. Toll. Da macht das helfen wirklich Spass. Bis zum nächsten Mal.
1.habe ich gemacht. vielleicht nicht so schnell wie dir es gepasst hätte. und wenn mir deine fragen nicht eindeutig genug waren muss ich ja nachfragen. 2.ich habe es gepostet. 2mal. 3.wenn ich das nicht gemacht hätte würde es wahrscheinlich immer noch nicht gehen. 4.wie gesagt vielleicht nicht so schnell wie du es gerne haben würdest aber ich habe auch noch ein bisschen was anderes zu tun. 5.du bräuchtest nur zu fragen. es war die sache mit kein rprintf und timerPause im interrupt. und 6. du besitzt nicht wirklich viel menschenkenntnis
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.