Hi,
Habe ein Infineon-C515c. Kann mir einer sagen:
1. Wieso nach der Konfiguration der seriellen Schnittstelle, TI=1
gesetzt werden muss? TI wird doch automatisch gesetzt durch die CPU?
2. Wenn ich TI=1 setze, ist doch ein "serial Interrupt" ausgelöst. Wieso
wird dann nicht zur "Interrupt Service Routine" gesprungen?
Den Code habe ich angehangen. Hoffe auf Hilfe
Lens schrieb:> 1. Wieso nach der Konfiguration der seriellen Schnittstelle, TI=1> gesetzt werden muss? TI wird doch automatisch gesetzt durch die CPU?> 2. Wenn ich TI=1 setze, ist doch ein "serial Interrupt" ausgelöst. Wieso> wird dann nicht zur "Interrupt Service Routine" gesprungen?
Hast du mal ins Datenblatt zu dem Thema geguckt?
Ich bin mit dem 515C nicht mehr ganz so vertraut, aber manche andere
Controller (AVR) setzen gewisse Flags zurück, wenn man sie mit einer 1
beschreibt. Das wäre in diesem Zusammenhang meine Vermutung.
Mir ist klar, dass ich noch den "serial interrupt" im "IEN0"-Register
aktivieren muss, doch ich versteh trotzdem nicht, wieso das "TI"-Flag am
Anfang gesetzt werden muss.
Jetzt könnt ihr mir vielleicht helfen. Im Bild steht "TI" direkt neben
"/SEND". Doch es steht nirgends explizit, dass TI dem "/SEND"-Pin
entspricht. Was meint ihr?
Es heißt außerdem "TI = 1; /* TI: set TI to send first char of UART */
Was soll das denn heißen? Wie kann ich denn das erste Zeichen senden,
obwohl ich noch garkeinen Sendebefehl abgesetzt hab?
Es geht wohl um interruptgesteuertes Senden.
Die Interruptroutine, die aufgerufen wird, wenn die UART mit dem Senden
des vorhergehenden Zeichens fertig ist, holt sich ein Zeichen aus dem
(Software-)Sendepuffer und übergibt das der UART-Hardware. Die sendet
das Zeichen, und löst wiederum einen Interrupt für das nächste Zeichen
aus.
Ist der Sendepuffer leer, wird kein weiteres Zeichen gesendet und also
kein weiterer Interrupt ausgelöst.
Um den ganzen Kram zu starten, genügt es nicht, Daten in den
Softwaresendepuffer zu schreiben, sondern es muss die
Sendeinterruptroutine gewissermaßen einmal angestupst werden -- und das
geschieht durch manuelles Setzen des TI-Bits.
Das war mir schon klar :). Nur wie du in meinem Code vielleicht siehst,
ist nirgendwo was von seriellem Interrupt, geschweigedenn von Interrupt
Service Routinen was zu sehen. Das ganze basiert auf "polling", da ja
printf() als "polling" programmiert ist. printf() überprüft ob TI=1 ist,
wenn ja, dann schreibt es das Zeichen in "SBUF". Das versteh ich ehrlich
gesagt nicht. Wieso muss es abprüfen, ob TI=1 ist? Ich mein wenn er
"TI=0" abprüfen würde, dann fände ich das logischer?
Lens schrieb:> printf() überprüft ob TI=1 ist,> wenn ja, dann schreibt es das Zeichen in "SBUF". Das versteh ich ehrlich> gesagt nicht. Wieso muss es abprüfen, ob TI=1 ist? Ich mein wenn er> "TI=0" abprüfen würde, dann fände ich das logischer?
Wie ist denn das Bit im Datenblatt beschrieben? Ich nutze den von Dir
verwendeten µC nicht, deswegen kenne ich natürlich seine UART auch
nicht.
Lens schrieb:> Das versteh ich ehrlich> gesagt nicht. Wieso muss es abprüfen, ob TI=1 ist? Ich mein wenn er> "TI=0" abprüfen würde, dann fände ich das logischer?
TI=1 sagt doch, dass das Senderegister leer ist und ein neues Zeichen
geschrieben werden darf. Wenn es =0 ist, wird noch gesendet und man darf
nicht schreiben.
TI könnte einen Interrupt auslösen, wenn das Bit "ES" im Register
"IEN0" gesetzt ist. Aber man kann TI auch pollen.
(Hinweis: Ich habe das jetzt mal schnell im Datenblatt nachgeschaut, es
ist also nur meine Theorie ohne praktische Erfahrung und Garantie!)
Gruß Dietrich
Dietrich L. schrieb:> TI=1 sagt doch, dass das Senderegister leer ist und ein neues Zeichen> geschrieben werden darf. Wenn es =0 ist, wird noch gesendet und man darf> nicht schreiben.> TI könnte einen Interrupt auslösen, wenn das Bit "ES" im Register> "IEN0" gesetzt ist. Aber man kann TI auch pollen.
Genau so ist es. Auch bei polled-Betrieb, muss am Anfang explizit das
Senderegister als "leer" deklariert werden.
Senderoutine (polling):
1.) warte, bis das Senderegister leer ist
2.) lege das nächste Zeichen in das Senderegister
3.) fertig.
Bei Interrupt Betrieb wird es etwas komplexer. Hier wird das neue
Zeichen in den Sende-Ringbuffer gelegt - sofern gerade eine Übertragung
läuft. Ansonsten wird es direkt in das Senderegister gepackt. Der
Interrupt prüft dann, ob weitere Zeichen im Ringbuffer sind und lädt
ggfs das nächste Zeichen in das Senderegister. Ist nichts mehr zu
senden, wird "fertig" markiert, damit der nicht-Interrupt-Teil weiß,
dass er die Übertragung neu anwerfen muss.
Georg G. schrieb:> 1.) warte, bis das Senderegister leer ist> 2.) lege das nächste Zeichen in das Senderegister> 3.) fertig.
So wie ich das bei der Beschreibung von TI gelesen hab, muss TI noch
gelöscht werden: TI=1 löst Interrupt aus, die ISR löscht TI wieder. Auch
wenn das nur im Zusammenhang mit Interrupt genannt wurde, vermute ich
doch, dass das auch ohne ISR gilt.
Gruß Dietrich