Forum: Mikrocontroller und Digitale Elektronik UART Receive vom PC. Erstes Zeichen ist ständig 0


von Andreas E. (everest_75)


Lesenswert?

Guten Abend zusammen,

ich komm einfach nicht mehr weiter.
Die Situation: Ein PC Programm (C++) sendet seriell Daten raus.
Empfangsseite ist ein Nucleo Board mit STM32F103.
Er empfängt die Bytes alle korrekt bis auf das Erste. Das wird immer als 
Null empfangen.

Ausschnitt des  PC-Code:
1
while (sendBuffer[i] != 0)
2
 {
3
        printf("%d\n", sendBuffer[i]);  // hiermit prüfe ich dass 
4
        i++;                            // sendBuffer richtig belegt ist
5
 }
6
                  
7
8
                  
9
                      object.connect("COM4");
10
                      object.sendArray(sendBuffer, sizeof(sendBuffer));
11
                      object.disconnect();


Empfangsseite Mikrocontroller, im UART-receive-Interrupthandler:
1
if(USART_GetITStatus(USART2, USART_IT_RXNE))
2
{
3
  USART_ClearITPendingBit(USART2, USART_IT_RXNE);
4
  
5
6
  uint8_t data = (uint8_t) USART_ReceiveData(USART2);
7
8
  receivedString[counter] = data;
9
  counter++;
10
}
Jetzt lese ich im Debug Modus (CooCox CoIDE) receivedString aus. Und 
siehe: receivedString[0] ist immer Null, alle anderen Positionen ab 
receivedString[1] sind völlig korrekt empfangen.

Und ganz seltsam: Wenn ich statt aus dem PC Programm heraus über ein 
Terminalprogramm (HTerm) von Hand das Array byteweise an den 
Mikrocontroller sende, dann funktioniert alles, auch das erste Element 
hat dann seinen richtigen Wert. Also zumindest auf µC Seite dürfte das 
einen fehler im Code ausschliessen, oder?

Irgendjemand auch nur den kleinsten Anhaltspunkt?

von Sascha W. (sascha-w)


Lesenswert?

Hallo,

du solltest die Schnittstelle nicht immer am Ende der Übertragung 
schließen. Kann sein das dann beim öffnen der Schnittstelle auf der 
TX-Leitung ein Flanke auftritt die am Empfänger zu einem Nullbyte führt.
Ist das Nullbyte zusätzlich oder wird das erste Nutzbyte zu selbigem?

Sascha

von Andreas E. (everest_75)


Lesenswert?

Das erste Nutzbyte kommt als Nullbyte an, das echte Nutzbyte ist also 
nicht auswertbar.

Zum Schliessen der Verbindung:
das findet nur einmalig statt. Die PC Anwendung soll nur einmal pro 
Durchlauf einen Datensatz an den µC senden. Der komplette Datensatz ist 
in sendBuffer gespeichert. Dass die richtigen daten drin sind hab ich 
vorher nochmal mt printf nachgeprüft.
Also einmal soll der datensatz gesendet werden und fertig. nach dem 
Close des Ports ist das Programm fertig.

: Bearbeitet durch User
von dummschwaetzer (Gast)


Lesenswert?

counter volatile?

von Sascha W. (sascha-w)


Lesenswert?

Andreas E. schrieb:
> Das erste Nutzbyte kommt als Nullbyte an, das echte Nutzbyte ist also
> nicht auswertbar.
ok, mit HTerm öffnen und dann Daten senden geht schreibst du. Da du in 
HTerm ja nicht sofort nach dem öffnen des Programms sendest, würd' ich 
mal testhalber zwischen öffnen der Schnittstelle und senden der Daten 
50ms Pause machen.
Was genau passiert müsste man sich mal mit einem Oszi oder LA anschauen. 
Kannst du mal am μC dafür sorgen das ein Frameerror angezeigt wird.

Sascha

von R. M. (Gast)


Lesenswert?

Benutzt du eventuell, außer den Datenleitungen (RxD und TxD) noch die 
Modemsteuerausgänge (DTR oder RTS) für irgendwelche 
Steuerungs/Stromversorgungszwecke? Die werden ja üblicherweise erst mit 
dem Öffnen der Schnittstelle aktiv. Nicht das hier eine Verzögerung rein 
kommt.

von Andreas E. (everest_75)


Lesenswert?

Wie geht denn in C++ eine verzögerung?  ich kenns nur beim µC mit Timern 
und so.

von Andreas E. (everest_75)


Lesenswert?

Ok, leider hilfts auch nicht.
Hatte jetzt einmal Sleep(50) und einmal Sleep(200)

jeweils zwischen object.connect(); und  object.sendArray(sendBuffer, 
sizeof(sendBuffer));

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Andreas E. schrieb:
> while (sendBuffer[i] != 0)
>  {
>         printf("%d\n", sendBuffer[i]);  // hiermit prüfe ich dass
>         i++;                            // sendBuffer richtig belegt ist
>  }

Und wie sieht i aus, bevor Du diesen Codeschnipsel aufrufst?

Was ist "objekt"?

von Harry L. (mysth)


Lesenswert?

Andreas E. schrieb:
> Empfangsseite Mikrocontroller, im
> UART-receive-Interrupthandler:if(USART_GetITStatus(USART2,
> USART_IT_RXNE))
> {
>   USART_ClearITPendingBit(USART2, USART_IT_RXNE);
>
>
>   uint8_t data = (uint8_t) USART_ReceiveData(USART2);
>
>   receivedString[counter] = data;
>   counter++;
> }

Sollten nicht ZUERST die Daten abgeholt werden, und DANACH Das 
Pending-Bit gelöscht werden?

von Wolfgang (Gast)


Lesenswert?

Andreas E. schrieb:
> Irgendjemand auch nur den kleinsten Anhaltspunkt?

Hänge einen Logikanalysator auf die Schnittstelle. Dann weisst du, was 
dort wirklich läuft und wo du den Fehler suchen musst.
So ein Ding kostet weniger als die Zeit, um hier den Thread zu öffenen 
und zu verfolgen (http://www.ebay.com/itm/201541710029).

von Jim M. (turboj)


Lesenswert?

Harry L. schrieb:
> Sollten nicht ZUERST die Daten abgeholt werden, und DANACH Das
> Pending-Bit gelöscht werden?

Nein. So herum ist richtig(er). Wenn verspätet noch ein Zeichen ankommt, 
dann möchte man das sofort via Tail-Chain abholen. Anderenfalls ist so 
das Pending Bit auf jeden Fall gelöscht vor dem Interrupt return.

Beitrag #5026136 wurde von einem Moderator gelöscht.
von Joachim B. (jar)


Lesenswert?

also nach dem power on in der Init würde ich ja sagen:

counter=0;
while(USART_GetITStatus(USART2, USART_IT_RXNE))
  uint8_t data = (uint8_t) USART_ReceiveData(USART2);

um Reste zu leeren.

und dann erst in die endlos loop gehen.

: Bearbeitet durch User
von Andreas E. (Gast)


Lesenswert?

Ok, Leute .
Danke für die vielen Tipps. Aber wahrscheinlich muss ich doch meine 
hardware überprüfen, im mom. hab ich da kein Werkzeug für da. Irgendwas 
stimmt einfach nicht an der seriellen Schnittstelle.

Seit heute morgen ging es nicht mal mehr über HTerm, was gestern noch 
ging.

Deshalb machen die Vermutungen, im µC Code stimme was nicht, wie ob erst 
Interrupt Flag zurücksetzen und dann lesen oder umgekehrt, eher wenig 
Sinn.

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
Noch kein Account? Hier anmelden.