Hallo Leute,
Ich habe ein Problem mit meinem UART Sendevorgang:
Ih füge mit sprintf eine Floatzahl an einen char string an was auch
funktioniert. Allerdings bekomme ich dann keine UART Ausgabe.
Wenn ichsprintf ausklammere und den string "händisch" beschreibe, dann
funktioniert es.
Den ADC Einlesevorgang habe ich auskommentiert, weil dieser bereits
funktioniert.
Meien Vermutung ist, dass der MSP nicht in den Sende-Interrupt geht.
Aber wieso??
1
#include<msp430.h> //einbinden der MSP430 Programmbibiothek
Hi
>Meien Vermutung ist, dass der MSP nicht in den Sende-Interrupt geht.>Aber wieso??
Also bei AVRs kommt der TX-Interrupt, wenn ein Zeichen gesendet wurde.
Dazu muss man aber die Übertragung erst mal von 'Hand' anstoßen.
MfG Spess
Sebastian Vvvvvv schrieb:> Wenn ichsprintf ausklammere und den string "händisch" beschreibe.
Dann fehlt ein Satzteil.
Ein Satz, der mit 'wenn' beginnt, benötigt ein 'dann'.
Also. Was ist dann?
funktioniert es etwa dann?
> char string2[12];
mach da mal ein bischen mehr.
12 ist nicht gerade viel.
> sprintf(string2, "I = %f", I);
Für den konstanten Textanteil sind das schon mal 4 Positionen. Dann noch
die 0-Terminierung, machvt 5 Zeichen. 12-5 macht 7. d.h. für die Zahl
bleiben dir 7 Stellen übrig. Wenn dein sprintf bei Fliesskommazahlen zb
5 Nachkommastellen ausgibt, dann bist du mit 347.14500 schon aus dem
Array draussen.
Du lebst wohl gerne gefährlich? Eine Variable mit einer derart wichtigen
Bedeutung wie ein Zeichenzähler nennt man doch nicht 'i'. Die hat sich
wirklich einen besseren Namen verdient. Und dann auch noch eine Variable
namens 'I'? Das nennt man Drahtseilakt ohne Netz und doppelten Boden.
Sowas
> if (i == sizeof string2 - 1) // TX over?
willst du auch nicht benutzen.
Du willst genau dann aufhören, wenn der String zu Ende ist und nicht
wenn das Array aufhört. Ein String ist zu Ende, wenn du im String auf
die 0-Terminierung stösst.
1
if(string2[i]!='\0')
2
UCA0TXBUF=string2[i++];
3
else
4
{
5
i=0;//Zähler für Übertragung reseten
6
UC0IE&=~UCA0TXIE;// Disable USCI_A0 TX interrupt
7
}
8
}
(Schon alleine, dass du hier die Operation am 'i' komentieren musst, ist
ein Indiz, dass du die Variablen anders benennen sollst. 'string2' kann
alles sein, genauso wie 'i'. Was spricht gegen
1
if(uartOutBuffer[uartOutBufferCnt]!='\0')
2
UCA0TXBUF=uartOutBuffer[uartOutBufferCnt++]
3
else
4
{
5
uartOutBufferCnt=0;
und schon muss nichts kommentiert werden. Die Anweisung ist
selbsterklärend und spricht für sich. Die Zeit, die du in Kommentare
steckst, ist besser aufgehoben, wenn du vernünftige, sprechende
Variablennamen benutzt.
Die Übertragung funktioniert ja auch, wenn ich sprintf nicht verwende.
kann es sein, dass diese Funktion zu lange braucht?
Der MSP schafft es ja die Zahl auf den String zu schreiben (im
Debugmodus des CCS6 gesehen).
Also "will" er es nur nicht senden.
spess53 schrieb:>>Meien Vermutung ist, dass der MSP nicht in den Sende-Interrupt geht.>>Aber wieso??>> Also bei AVRs kommt der TX-Interrupt, wenn ein Zeichen gesendet wurde.> Dazu muss man aber die Übertragung erst mal von 'Hand' anstoßen.
So ist normalerweise der Send Interrupt. Er wird ausgelöst wenn ein
Zeichen gesendet wurde, damit die ISR dann das nächste Zeichen senden
kann.
@Sebastian:
Du sendet in der IRQ ohne vorher zu prüfen ob überhaupt etwas im String
steht.
Du schreibst in der Interruptroutine auf die Variable 'i', sie ist aber
nicht volatile.
Hi
>So ist normalerweise der Send Interrupt. Er wird ausgelöst wenn ein>Zeichen gesendet wurde, damit die ISR dann das nächste Zeichen senden>kann.
Aber UCA0TXBUF = string2... taucht nur im Interrupt auf. Wie soll der
aufgerufen werde?
MfG Spess
Die Interruptroutine mit dem i Counter müsste doch funktionieren, da sie
auch mit einem anderen string funktioniert.
Gibt es denn typische Probleme, die bei sprintf auftreten=
Sebastian Vvvvvv schrieb:> Gibt es denn typische Probleme, die bei sprintf auftreten=
Ja.
Wenn dein Array zu klein ist.
Und nein: Ich seh doch im Debugger, dass da das richtige drinn steht,
gilt nicht.
Ist das Array zu klein, bügelst du dir die unmittelbar im Speicher
angrenzenden Variablen nieder.
Mach die 12 größer. An dieser Stelle ist während der Entwicklung
knausrig sein der falsche Weg.
Wo wird denn der USCI Interrupt enabled? Wird i mit 0 initialisiert?
Aber was, wenn, dann ...
Im Timer Interrupt wird am Anfang auf den ADC gewartet und am Ende
sprintf aufgerufen. Wie lange dauert das und wie oft kommt der
Interrupt? Was höhere Priorität, Timer oder USCI?
mit i=0 initialisieren habe ich es auch schon versucht...
also der Interrupt wirde jede ms aufgerufen.
Wie kann ich den nachsehen, wie lange diese Aktionen dauern?
Die Priorität sollte doch von selber geregelt werden oder?
Wenn nicht wäre es ideal, wenn der Timer Interrupt erst wieder aktiviert
wird, wenn der USCI Interrupt fertig ist. Doch wie mach ich das, sodass
anschließend der Timer Interrupt wieder dort weitermacht, wo er gestoppt
wurde??
Wirf ein Blick auf die Timer Initialisierung, nicht auf den Kommentar.
In einer ISR sollte man nicht unnötig warten. Und, der ADC hat einen
eigenen Interrupt.
Was könnte ich da an der Initialiserung groß ändern?
Könnte ich anstatt des Warten dann einen Ablauf wie:
ISR starten -> ADC Einlesung + sprintf -> ISR Stopp -> UART Übertragung
-> UART Ende -> ISR starten ...
einfach realisieren?
Sebastian Vvvvvv schrieb:> Was könnte ich da an der Initialiserung groß ändern?
Der Code passt nicht zu den Kommentaren.
Zeig einmal deinen Code ohne sprintf, der funktioniert.
Sebastian Vvvvvv schrieb:> einen Ablauf wie
- Clock initialisieren
- ADC initialisieren
- USCI initialisieren
- ADC starten
- endless loop
ADC löst Interrupt aus -> in der ADC-ISR Ausgabepuffer füllen und
Ausgabe-Interrupt aktivieren -> beim letzten Zeichen in der USCI-ISR ADC
starten -> ...
Es lag daran, dass sprintf in der Timer-A ISR nicht fertig wurde und
ohne Watch-Dog dies nicht erkannt wurde und der Aufruf der UART
Übertragung nicht aufgerufen wurde.
Lösung:
-erhöhen der Prozessorfrequenz
-erhöhen von Periodendauer von Timer_A
Danke für die Hilfe