Forum: Mikrocontroller und Digitale Elektronik Sendefunktion


von UART Sendefunktionje (Gast)


Lesenswert?

Ich versuche gerade eine Funktion zu schreiben, mit der ich über die 
UART Schnittstelle Daten über ein RS232 to USB Kabel (COM4) an ein 
Terminal auf dem PC schicke, um mir die Daten ansehen zu können. Ich 
möchte die UART kennen lernen.

Ich schicke direkt eine 0, wenn value = 0 ist.
Wenn die Zahl > 0 ist, arbeite ich mit einem Modulo Operator und teile 
die Zahl immer durch 10, damit ich einzelne Ziffern ins Array setzen 
kann.

Die Zahlen werden immer beginnend mit dem letzten Index in das Array 
gespeichert.
Wenn die Zahl negativ sein sollte, wird alles mit Nullen gefüllt.

Ich habe nun 2 Fragen.
Da das Array eine Länge von 10 hat sieht die Anordnung von der Zahl 7800 
beispielsweise so aus:
xxxxxx7800
Wenn ich diesen Wert über die UART schicke sehe ich am Terminal (HTERM) 
einen Zeilenumbruch nach jedem 10. Wert einstelle, sehe ich nicht diese 
Anordnung, sondern mir wandern die Zahlen ständig hin und her.
Wenn ich Glück habe sieht es wie folgt aus: (Die nicht gefüllten Felder 
werden im HTERM stets mit "*" dargestellt)
******7800
die nächste Zahl zB
*******68

Aber manchmal kann es auch folgendermassen aussehen:
**7800****  (1. Zahl)
7800******  (2. Zahl)
und die nächste Zahl 68 dann
7800*****6  (3. Zahl 68)
8*********

oder auch mal die 100 mit einer folgenden 0
****1000**

Ich verstehe das nicht.

Was mache ich nur falsch? Liegt es daran, dass ich die Felder (value > 
0) nicht weiter fülle? Was könnte das Problem sein?

Weiters möchte ich das Programm irgendwie auf Einfachstem Wege dazu 
bringen auch negative Zahlen darstellen zu können.
Dazu müsste ich den Typ des Parameters wohl zuerst einmal auf int32_t 
umstellen, aber dann habe ich das Problem mit der else.
Gibt es irgendwie eine einfache Lösung oder muss ich die komplette 
Funktion umschreiben?

1
void UART_transmit_Int(uint32_t value)
2
{
3
   uint8_t string[10];  // die maximale Zahl kann 10 Stellen haben, deshalb array[10]
4
   uint8_t zero = '0';
5
   
6
   // sende direkt 0, wenn value = 0 und beende die Funktion
7
   if (value == 0){
8
      HAL_UART_Transmit(&UART1_HANDLER, &zero, sizeof(zero), 1000);              
9
      return;
10
   }
11
   
12
  for (uint8_t i = 0; i<10; i++)
13
   {
14
      if(value > 0)
15
      {
16
         string[9-i] = 48 + (value % 10);                                       /* Das letzte Zeichen im Array string ist 48 => 0 in ASCI-Tabelle + 
17
                                                                                   Rest von number und schreibe Zeichen in string*/
18
         value /= 10;                                                           // teile value dann durch 10
19
      }
20
      else
21
      {
22
        string[9-i] = 0x00;  //0                                                 // wenn number < 0 fülle Rest mit Nullen auf
23
      }
24
   }
25
       
26
   HAL_UART_Transmit(&UART1_HANDLER, string, sizeof(string), 1000);              // Drucke dann alle Zeichen im string aus

von Walter S. (avatar)


Lesenswert?

>         string[9-i] = 0x00;  //0
> // wenn number < 0 fülle Rest mit Nullen auf

meinst du vielleicht
string[9-i] = '0';

von Walter S. (avatar)


Lesenswert?

und eine Endekriterium wäre auch hilfreich

von Stefan F. (Gast)


Lesenswert?

Ich sehe spontan keinen Fehler im Quelltext. Die Antworten von Walter S. 
kann ich nicht nachvollziehen.

Könnte es sein, dass du eine zu hohe Baudrate verwendest, die der µC 
nicht genau genug erzeugen kann? Oder verwendest du einen R/C Oszillator 
für den Systemtakt?

von UART Sendefunktionje (Gast)


Lesenswert?

Stefanus F. schrieb:
> Ich sehe spontan keinen Fehler im Quelltext. Die Antworten von
> Walter S.
> kann ich nicht nachvollziehen.
>
> Könnte es sein, dass du eine zu hohe Baudrate verwendest, die der µC
> nicht genau genug erzeugen kann? Oder verwendest du einen R/C Oszillator
> für den Systemtakt?

Hallo

Ich verwende einen externen Quarz ja.
Systemtakt ist auf 48MHz eingestellt.
Baudrate 9600.

von Eric B. (beric)


Lesenswert?

Mach doch am Ende vom String ein '\n' (newline), dann brauchst du keine 
Zeichen zählen am PC-Ende. Es sieht danach aus, dass du bei der 
Übertragung zeichen verlierst...
1
void UART_transmit_Int(int32_t value)
2
{
3
  uint8_t string[11];  // max 10 digits + end-of-line char
4
5
  string[10] = '\n';   // set end-of-line
6
7
  Bool_t is_neg = (value < 0);
8
9
  if(is_neg) {
10
    value = -value;
11
  }
12
13
  index = 9;
14
  if (value == 0) {
15
    string[index] = '0';
16
    index--;
17
  } else {
18
    while ((value > 0) && (index > 0)) {
19
      string[index] = (value % 10) + '0';
20
      value /= 10;
21
      index --;
22
    }
23
  }
24
  
25
  if(is_neg) {
26
    string[index] = '-';
27
  } else {
28
    index++;
29
  }
30
31
  HAL_UART_Transmit(&UART1_HANDLER, string + index, sizeof(11 - index), 1000);
32
}

von Stefan F. (Gast)


Lesenswert?

Eric B. schrieb:
> Es sieht danach aus, dass du bei der Übertragung zeichen verlierst

Ja, das denke ich auch. Deswegen hatte ich die Baudrate versus 
Takrfrequenz hinterfragt. Wenn die Baudrate zu ungenau ist, kann das 
passieren.

Aber 48MHz aus einem Quarz und 9600 Baud sollten immer gehen.

von chris (Gast)


Lesenswert?

Stefanus F. schrieb:
> Könnte es sein, dass du eine zu hohe Baudrate verwendest, die der µC
> nicht genau genug erzeugen kann?

Alle Jahre wieder....
Der Baudratenfehler hat nichts mit der Höhe der Baudrate zu tun!
Ein prozentualer Fehler ist und bleibt prozentual.

von Stefan F. (Gast)


Lesenswert?

chris schrieb:
> Der Baudratenfehler hat nichts mit der Höhe der Baudrate zu tun!
> Ein prozentualer Fehler ist und bleibt prozentual.

Doch hat er schon, wenn (wie in diesem Fall) kein Baudratenquarz 
verwendet wurde. Einige Baudraten kann er mit den 48MHz sehr genau 
erzeugen (z.B. 1000000 Baud), aber weniger genau. Die Chance, eine 
ungeeigenete Kombination zu treffen ist bei den niedrigen Baudraten 
geringer.

Falls du mir nicht glaubst: Schau mal im Datenblatt vom ATmega328, 
welche Baudraten der bei 16MHz (Arduino Nano) wie genau erzeugen kann. 
Dann wirst du sehen, dass man bis auf einzelne Ausnahmen mit den 
Baudraten unter 57kbps besser bedient ist.

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.