Wenn ich bei beendetem Empfang über den UART per Interrupt die Leseroutine starten möchte, dann ist das doch der ISR_VECTOR(UART_RX_vect) oder? Zusätzlich muss sei() gesetzt sein. Muß ich sonst noch was beachten? Wenn wenn ich im AVR-Studio Simuliere und den RXCIE anklicke passiert erstmal nichts. Wenn ich aber dann noch RXC aktiviere, dann springt das Program nicht auf die Interrupt-Routine, sondern zum Beginn der Main-Schleife...Hab ich was vergessen?
Phillip Hommel wrote:
> auf die Interrupt-Routine, sondern zum Beginn der Main-Schleife...
Ist ein deutliches Indiz für einen Software Fehler. Und zwar
hat der Compiler nicht erkannt, dass du eine ISR schreiben
willst, bzw. du hast dich im Namen der ISR irgendwo vertan.
ISR( USART_RXC_vect )
{
...
}
Wenn du dir nicht sicher bist, wie der Interrupt wirklich
heissen muss, dann mach das zu deinem Prozessor gehörende
include file auf (bei einem Mega32 ist das zb. iom32.h)
und sieh da drinnen nach.
Opps:
Wir reden doch vom gcc auf einem Atmel µC, oder nicht?
(Dachte die Anfrage wäre im gcc-Forum gekommen und nicht
im M+C)
Aus der io8535.h demensprechend auch mein nC. Ich benutze AVR-Studio mit gcc. /* UART, RX Complete */ #define UART_RX_vect _VECTOR(11) #define SIG_UART_RECV _VECTOR(11) Habe es aber sicherheitshalber auch schon mit UART_RXC_vect versucht. Gleiches Ergebnis, springt immer wieder zum anfang und ingnoriert den Handler total!
Dass es "ISR" und nicht "ISR_VECTOR" (wo auch immer Du das her hast) heißen muss, ist aber jetzt klar, oder?
Ach mist, das war noch nicht korrigiert. Hab ich inzwischen entdeckt...Allerdings tuts immer noch nicht. Nochmal zum Verständnis: Der Hardware UART lädt das was kommt in den Puffer, wenn er fertig ist kommt das empfangene ins UDR. Wenn das passiert wird das RXCIE gesetzt und damit das Interrupt ausgelöst, gleichzeitig geht die RXC-Falg auf 1. Ist das soweit richtig? Wenn ich in der Simulation nur RXC oder nur RXCIE auf 1 setze, passiert gar nichts, sind beide gesetzt springt das Prog. auf Anfang.
1 | |
2 | ISR(UART_RX_vect) |
3 | {
|
4 | Number_of_bytes_RXD = Usart_Rx(); //erstes Paket als Number of Bytes |
5 | |
6 | Type_of_bytes_RXD = Usart_Rx(); //2.Paket als Type of RX, |
7 | //0x00=PC fordert Daten an
|
8 | //0x01=PC fordert nach Empfang Daten an
|
9 | //0x02=PC sendet nur daten
|
10 | //0xff=board resetten
|
11 | switch(Type_of_bytes_RXD) //Fallunterscheidung anhand Typ |
12 | {
|
13 | case 0x00 : Send_To_PC(Data_to_send);break; |
14 | case 0x01 : Data_Receive(Data_received_LED);Send_To_PC(Data_to_send);break; |
15 | case 0x02 : Data_Receive(Data_received_LED);break; |
16 | case 0xff : reset();break; |
17 | }
|
18 | }
|
Ich weiß, die Routine ist zu lang, aber das ist erstmal ein anderes Problem oder?
Wieso rufst Du innerhalb der ISR zwei mal irgendeine Funktion "Usart_Rx" auf? Und was macht diese Funktion? Ich vermute, Du hast da was gründlich falsch verstanden. Wenn ein Byte empfangen wurde, wird das Flag gesetzt und (wenn der Rx-Interrupt aktiviert ist) in die ISR gesprungen (Du versuchst aber anscheinend, mehr als ein Byte zu lesen). Das Flag wird erst dann gelöscht, wenn das Datenregister UDR gelesen wird (und wenn im Buffer kein weiteres Zeichen wartet).
Phillip Hommel wrote: > Ach mist, das war noch nicht korrigiert. Hab ich inzwischen > entdeckt...Allerdings tuts immer noch nicht. > Nochmal zum Verständnis: > Der Hardware UART lädt das was kommt in den Puffer, wenn er fertig ist > kommt das empfangene ins UDR. > Wenn das passiert wird das RXCIE gesetzt und damit das Interrupt > ausgelöst, gleichzeitig geht die RXC-Falg auf 1. > Ist das soweit richtig? So ungefähr. Die Reihenfolge ist anders rum. RXC wird beim Empfang auf jeden Fall gesetzt. RXCIE wird ebenfalls gesetzt und nur wenn der Interrupt auch freigegeben ist, findet dann auch der AUfruf statt. > Ich weiß, die Routine ist zu lang, aber das ist erstmal ein anderes > Problem oder? Für dein konkretes Problem: ja Auf lange Sicht: nein Es gibt noch eine Möglichkeit für deine Beobachtung: Du hast irgendeinen anderen Interrupt freigegeben. Wie sieht die UART Initialisierung aus.
Das ist richtig, habs noch nicht ganz verstanden ;) Ich möchte im Endeffekt 16 Datenbytes + das "Type of Data"-Byte empfangen. Das Hauptprogramm soll aber wenn nichts kommt andere Aufgaben erledigen, unter anderem auch daten verschicken. Wenn jetzt das erste Byte ankommt, sagt mir das erstmal, wieviele Bytes noch kommen (für die empfangsschleife). Das zweite sagt mir dann was ich machen soll (nur empfangen, nur daten nochmals senden, beides, reset). Danach kommen dann die Datenbytes und sollen zu einem Array zusammengebastelt werden. Meine Idee war jetzt, das wenn ein Byte empfangen wird, ein Intterupt ausgelöst wird und sich der Controller jetzt nur noch mit dem Empfang der Daten beschäftigt, bis dieser abgeschlossen ist (darum steht eben auch alles im Interrupt-Handler drin). Danach läuft das Programm normal weiter Die Initialisierung des UART habe ich aus einem Headerfile und wird im main() einmal getätigt:
1 | void USART_Init( unsigned int ubrr) |
2 | {
|
3 | /* Baudrate setzen */
|
4 | UBRRH = (unsigned char)(ubrr>>8); |
5 | UBRRL = (unsigned char)ubrr; |
6 | |
7 | /* RX/TX einschalten */
|
8 | UCSRB = (1<<RXEN)|(1<<TXEN); |
9 | |
10 | /* Datenformat setzen: 8data, 2stop bit */
|
11 | UCSRC = (1<<URSEL)|(1<<USBS)|(3<<UCSZ0); |
12 | }
|
Ebenfalls setze ich die Interrupts natürlich zu Programmbeginn per sei(), Register wird in der Simulation auch gesetzt. Wenn ich dann die RXC und RXCIE setze, geht das SREG(7) Byte auch auf 0, es wird einfach mein ISR-Handler ignoriert.
Ok, mit ISR(VECTOR(11)) gehts, was komisch ist, denn ich habe die io.h ja geladen...hmm Naja, ich erkene auch so langsam daß das was ich da tue etwas, ähm, ungünstig ist. Werde mal weiter probieren und bestimmt mit der einen oder anderen Frage glecih wieder zur Stelle sein... lg Phil edit: AUTSCH, ich hatte in der io8535.h gescuht, die is aber für den at90s8535...für meinen gilt die iom8535, dort heisst das ding dann nicht UART_RX_vect, sondern USART_RX_vect
Soo, läuft alles soweit, bis auf ein kleines Problem: Wenn der Interrupt ausgelöst wird, wird im selben Takt, in dem das Program auf den Interrupt Handler Springt, auch das UDR gelöscht. Wie kann ich den Wert dann noch Speichern?
@ Phillip Hommel (Firma hs-bremen) (philharmony) >Wenn der Interrupt ausgelöst wird, wird im selben Takt, in dem das >Program auf den Interrupt Handler Springt, auch das UDR gelöscht. Kaum. >Wie kann ich den Wert dann noch Speichern? my_data = UDR; MFG Falk
dann macht das nur der Simulator? ich habe das so gemacht, daß ich das prog. hab laufen lassen (paar mal F11 für next step bis ich im main loop war). dann nen Wert ins UDR reingeklickt und RXCIE und RXC auf 1. Beim nächsten Step springt er wie gewollt in die ISR-Routine, aber der UDR ist leer. Muß ich am ende des Handlers eigentlich manuell wieder irgendwas setzen (sei(), RXCIE,...)?
@ Phillip Hommel (Firma hs-bremen) (philharmony) >dann macht das nur der Simulator? Nö. >ich habe das so gemacht, daß ich das >prog. hab laufen lassen (paar mal F11 für next step bis ich im main loop >war). >dann nen Wert ins UDR reingeklickt und RXCIE und RXC auf 1. >Beim nächsten Step springt er wie gewollt in die ISR-Routine, aber der >UDR ist leer. Du verarscht ja auch den Simulator nach Strich und Faden. Kein Wunder wenn der sich wehrt ;-) >Muß ich am ende des Handlers eigentlich manuell wieder irgendwas setzen >(sei(), RXCIE,...)? NEIN! Lies nochmal zum Thema Interrupts und Uart in den Datenblätern und im GCC Tutorial. MFG Falk
>dann macht das nur der Simulator? Habe ich auch so festgestellt. Der Debugger im AVR-Studio 4.13 hat da so seine Schwächen. UDR wird jedesmal nach dem Beschreiben (beim nächsten Schritt) auf null gesetzt. Auf der Hardware läuft's aber einwandfrei! ;)
Hmm, dann muss ich jetzt nur noch warten bis die Schieberegister per Post ins Haus flattern und dann verscuh ich mal obs klappt. >Du verarscht ja auch den Simulator nach Strich und Faden. Kein Wunder >wenn der sich wehrt ;-) Wieso verarsche ich den sim? Gibt es eine andere Möglichkeit, UART-Empfang zu Simulieren? lg
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.