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.
Vielleicht wäre es gut, wenn Du auch mal schreibst, was Du an
Messmitteln hast, die Schaltung, Deine Vorkenntnisse (formal und/oder
autodidaktisch angeeignete).
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
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.
#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");
}
>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.
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