Forum: Compiler & IDEs Uart HEX 00 Senden


von Rukula (Gast)


Lesenswert?

Hallo, ich möchte ein Gerät über die UART mit der Funktion printf 
Steuern.
Hierzu werden 12 Hex Zeichen übermittelt.
Beispiel 80 01 05 07 00 DD
Code:
printf(“\x80\x01\x05\x07\x00\xDD“);

Nur leider werden die beiden 00 nicht übertragen, bzw. wird die 
Übertragung sogar danach beendet.
Wie kann ich die den Befehl Senden? Welche möglichkeiten gibt es sonst 
noch?
Danke für eure Hilfe….

von Stefan B. (CDLinux) (Gast)


Lesenswert?

Geht nicht. printf versendet Strings und die \x00 ist das Zeichen für 
Stringende in C.
Versende die 6 Zeichen einzeln mit 6 putc()-Aufrufen hintereinander.

von Patrick B. (p51d)


Lesenswert?

Rukula schrieb:
> Nur leider werden die beiden 00 nicht übertragen, bzw. wird die
> Übertragung sogar danach beendet.
Wie schon geschrieben sind die Strings mit 00 abgeschlossen:
string "hallo welt" sieht in der char-Array so aus:
'h','a','l','o','','w','e','l','t',0


> Wie kann ich die den Befehl Senden? Welche möglichkeiten gibt es sonst
> noch?
Schreibe die Werte doch direkt in das UDR Register...

Diesen Code habe ich in der Schule schreiben müssen:
1
static volatile int txBuf[255];           // RS232 Transmit Buffer
2
static volatile int index_txBuf_R = 0;    // Index wo TXBuffer zuletzt gelesen wurde
3
static volatile int index_txBuf_W = 0;    // Index wo TXBuffer zuletzt geschrieben wurde
4
/***************************************************************/
5
6
void txBuf_Write(unsigned char parameter){  // TX-Buffer mit Werte füllen
7
  if(index_txBuf_W == Buf_max){           // Damit Ringbuffer nicht überläuft
8
    index_txBuf_W = 0;
9
  }
10
  else{
11
    index_txBuf_W ++;
12
  }
13
  txBuf[index_txBuf_W] = parameter;
14
}
15
void UART_Transmit(int Num_of_bytes, unsigned char *param){ // Anzahl Parameter und Parameters übergeben
16
  int q = 0;
17
  static int StartIndex = 0;              // Index wo Transmit-Frame gestartet werden soll
18
  
19
  txBuf_Write(Num_of_bytes);
20
  StartIndex = index_txBuf_W;             // Aufgepasst ein neuer Frame beginnt!
21
  for(q = 0; q < Num_of_bytes; q++){
22
    txBuf_Write(param[q]);
23
  }
24
  txBuf_Write(crc8_messagecalc(param, Num_of_bytes));  // CRC8 berechnen und abspeichern
25
  if(index_txBuf_R == Buf_max){           // Buffer am überlaufen hindern  
26
    index_txBuf_R = 0;
27
  }
28
  else{
29
    index_txBuf_R ++;
30
  }
31
  UCSRA |= (1<<TXC);                      // TXC Flag zurücksetzen, dass bei Aktivierung nicht in ISR springt
32
  UCSRB |= (1<<TXCIE);                    // Für Frame TX Complete Interrupt aktivieren
33
  RXTX_Reg = txBuf[StartIndex];           // Frame ist aufgebaut/Com starten mit Number of Bytes senden
34
}
35
36
/***************************************************************/
37
ISR(USART_TXC_vect){                       // Transmit Complete Interrupt
38
  if(index_txBuf_R == Buf_max){            // Damit Buffer nicht überläuft
39
    index_txBuf_R = 0;
40
  }
41
  else{
42
    index_txBuf_R ++;                      // Index erhöhen
43
  }  
44
  if(index_txBuf_R == index_txBuf_W){      // Damit Read Write nicht überholt
45
    UCSRB &= (~(1<<TXCIE));                // Frame beendet, TX Complete Interrupt deaktivieren
46
  }
47
  RXTX_Reg = txBuf[index_txBuf_R];         // Daten senden
48
}
49
/***************************************************************/
50
int main(void){
51
  unsigned char array[]={"Hallo welt"};    // Gibt als Parameter "Hallo welt" aus, abgeschlossen mit 00
52
  SysInit();
53
  while(1){
54
    int Num_bytes = ((sizeof(array)/sizeof(array[0])) - 1);  // Arrayplätze berechnen, letzter Platz ignorieren
55
    UART_Transmit(Num_bytes, array);       // Werte übergeben und senden
56
  }
57
}
hab hier nicht den ganzen Sourcecode gepostet, musst ihn aber auf deine 
Bedürfnisse anpassen...

hoffe es hilft dir trotzdem weiter...
MFG
Patrick

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

@  Patrick B.
Man lernt nie aus:
1
static volatile int txBuf[255];           // RS232 Transmit Buffer
2
static volatile int index_txBuf_R = 0;    // Index wo TXBuffer zuletzt gelesen wurde
3
static volatile int index_txBuf_W = 0;    // Index wo TXBuffer zuletzt geschrieben wurde
4
/***************************************************************/
5
6
void txBuf_Write(unsigned char parameter){  // TX-Buffer mit Werte füllen
7
  if(index_txBuf_W == Buf_max){           // Damit Ringbuffer nicht überläuft
8
    index_txBuf_W = 0;
9
  }
10
  else{
11
    index_txBuf_W ++;
12
  }
13
  txBuf[index_txBuf_W] = parameter;
14
}
15
:

Das könnte bei geeigneter Wahl Puffergröße (256 Bytes statt 255 
Integers) und der Indices (unsigned char hat den Wertebereich 0...255) 
wesentlich kompakter und effizienter geschrieben werden:
1
volatile unsigned char txBuf[256];           // RS232 Transmit Buffer
2
volatile unsigned char index_txBuf_R = 0;    
3
volatile unsigned char index_txBuf_W = 0;    
4
/***************************************************************/
5
6
void txBuf_Write(unsigned char parameter){  // TX-Buffer mit Werte füllen
7
  index_txBuf_W++;     // hier Preincrement, aber besser sollte der Index erst nach dem Beschreiben des Speicherplatzes erhöht werden...
8
  txBuf[index_txBuf_W] = parameter;
9
}
10
:
Damit fallen die ganzen Abfragen nach Buf_max aus dem Code heraus, 
weil der Index (als char) niemals größer als 255 werden kann.

von Patrick B. (p51d)


Lesenswert?

Lothar Miller schrieb:
> Damit fallen die ganzen Abfragen nach Buf_max aus dem Code heraus,
> weil der Index (als char) niemals größer als 255 werden kann.

wenn der Index 255 erreicht hat und dann wieder inkrementiert wird, wird 
der Index dann automatisch 0 oder bleibt der 255??
denn Ansonsten bringts nichts, denn die Abfragen auf Buf_max bleiben

Danke für den Verbesserungsvorschlag

von Da I (Gast)


Lesenswert?

Der Index würde 256 werden.
Da aber nur die untersten 8 Bit "verwendet" werden:

1 0000 0000 => 0000 0000 => 0x00.

Also 255 + 1 ist bei nem Byte immer 0.

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> Da I
Das wars, was ich sagen wollte, Du da  ;-)

Dieses Prinzip funktioniert an allen Zweierpotenzgrenzen, nur muß man 
sich dann selber um die Maskierung kümmern. Hier z.B. mit 16 Elementen:
1
volatile unsigned char txBuf[16];           // RS232 Transmit Buffer
2
volatile unsigned char index_txBuf_R = 0;    
3
volatile unsigned char index_txBuf_W = 0;    
4
/***************************************************************/
5
6
void txBuf_Write(unsigned char parameter){ // TX-Buffer mit Werte füllen
7
  txBuf[index_txBuf_W&0xf] = parameter;    // nur 16 Speicherplätze, deshalb Maske über die unteren 4 Bits
8
  index_txBuf_W++;                         // der Index darf ruhig weiterlaufen, es werden ja nur die unteren 4 Bits verwendet
9
}
10
  // Abfrage, ob ein Element im Puffer
11
  if (index_txBuf_W!=index_txBuf_R) {
12
      wert = txBuf[index_txBuf_R&0xf];
13
      index_txBuf_R++;
14
  }
15
:
Der Index sollte erst nach dem Eintragen oder Auslesen eines Wertes in 
den Fifo erhöht werden. Denn sonst könnte ja zwischen Indexincrement und 
Beschreiben des Puffers eine lesende ISR kommen, den bereits erhöhten 
Schreibindex sehen, und auf das noch nicht geschriebene Element 
zugreifen. Diesen Fehler zu finden dauert Wochen...  :-/

Bei solchen Fifo-Geschichten sollte jede Codezeile darauf abgeklopft 
werden, was wäre, wenn ein Interrupt käme.

von Patrick B. (p51d)


Angehängte Dateien:

Lesenswert?

Lothar Miller schrieb:
>> Da I
> Das wars, was ich sagen wollte, Du da  ;-)
>
> Dieses Prinzip funktioniert an allen Zweierpotenzgrenzen, nur muß man
> sich dann selber um die Maskierung kümmern. Hier z.B. mit 16 Elementen:
sprich für 256 Elemente siehts so aus:
1
volatile unsigned char txBuf[256];           // RS232 Transmit Buffer
2
volatile unsigned char index_txBuf_R = 0;    
3
volatile unsigned char index_txBuf_W = 0;    
4
/***************************************************************/
5
6
void txBuf_Write(unsigned char parameter){   // TX-Buffer mit Werte füllen
7
  txBuf[index_txBuf_W & 0xFF] = parameter;  // nur 16 Speicherplätze, deshalb Maske über die unteren 4 Bits
8
  index_txBuf_W ++;                         // der Index darf ruhig weiterlaufen, es werden ja nur die unteren 4 Bits verwendet
9
}
10
  // Abfrage, ob ein Element im Puffer
11
  if (index_txBuf_W!=index_txBuf_R) {
12
      wert = txBuf[index_txBuf_R & 0xf];
13
      index_txBuf_R ++;
14
  }
Aber kriegt man dann nicht einmal Speicherprobleme auf einem 8-Bit MCU?? 
da ja index trotzdem noch inkrementiert wird?


> Der Index sollte erst nach dem Eintragen oder Auslesen eines Wertes in
> den Fifo erhöht werden. Denn sonst könnte ja zwischen Indexincrement und
> Beschreiben des Puffers eine lesende ISR kommen, den bereits erhöhten
> Schreibindex sehen, und auf das noch nicht geschriebene Element
> zugreifen. Diesen Fehler zu finden dauert Wochen...  :-/
hhmmmm...
bei mir läuft es momentan nach folgendem Muster:
index_txBuf_W =>   txBuf[0]  <= index_txBuf_R
neuer Wert kommt...
index_txBuf_W++
index_txBuf_W =>  txBuf[1]
Code erkennt dass W und R nicht mehr gleich sind...
index_txBuf_R++
index_txBuf_W =>  txBuf[1]  <= index_txBuf_R
und so weiter...


wenn wir schon dabei sind, ich hab euch gleich den Quellcode im Anhang, 
damit ihr mal darüber schauen könnt und eure Meinung und 
Verbesserungsvorschläge sagen könnt.
p.s. sorry, wegen dem schlechten Styl, aber in der Schule lerne ich 
leider nicht "richtiges und sauberes" Programmieren

von klaus (Gast)


Lesenswert?

> Das könnte bei geeigneter Wahl Puffergröße (256 Bytes statt 255
> Integers) und der Indices (unsigned char hat den Wertebereich 0...255)
> wesentlich kompakter und effizienter geschrieben werden:

Normalerweise Rischtisch, aber bedenke, mit einem UART könnte man auch 9 
bits senden/empfangen (wollen)... ein "unsigned char" Puffer reicht dann 
nicht mehr

von doc (Gast)


Lesenswert?

Es ist schon ein Kreutz mit der 0 am Ende von C-Strings.

Für solche Fälle habe ich für mich mal eine Pascal-like-String-Library 
geschrieben.

Der Unterschied zu C-Strings: Die Stringlänge wird nicht durch eine 
Abschliessende 0 gekennzeichnet, sondern durch ein Längenbyte am Anfang 
des Strings.

Dadurch ist von einem String immer die Länge bekannt, suchen der 0 
entfällt, und alle Zeichen (incl. 0-Byte) sind gültig.
Dafür gibts dann andere Nachteile :-)

Vorteil: Wenn man Binär-Daten z.b. über Uart übertragen will, 
funktioniert es besser, und man muss sich nicht um Nullen kümmern. Auch 
einige Fkt sind schneller, z.b. strlen..

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

> hhmmmm...
> bei mir läuft es momentan nach folgendem Muster:
> index_txBuf_W =>   txBuf[0]  <= index_txBuf_R
> neuer Wert kommt...
> index_txBuf_W++
Und hier passiert es: der Interrupt (z.B. TX-Int der SIO) kommt und der 
Schreibpointer ist schon um eins hochgesetzt. Deshalb erkennt der 
Interruptcode, dass W und R nicht mehr gleich sind...
Und liest schon mal das Zeichen, das erst nach Beenden der 
Interruptroutine geschrieben wird:
> index_txBuf_W =>  txBuf[1]

Das ist das klassische Semaphorenproblem   :-o

> Pascal-like-String-Library
> Dafür gibts dann andere Nachteile :-)
Es passen z.B. nur 255 Zeichen in den String.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

klaus schrieb:
>> Das könnte bei geeigneter Wahl Puffergröße (256 Bytes statt 255
>> Integers) und der Indices (unsigned char hat den Wertebereich 0...255)
>> wesentlich kompakter und effizienter geschrieben werden:
>
> Normalerweise Rischtisch, aber bedenke, mit einem UART könnte man auch 9
> bits senden/empfangen (wollen)... ein "unsigned char" Puffer reicht dann
> nicht mehr
hä? Die Größe eine einzelnen Array Elementes hat doch nix mit der 
Größe/Anzahl speicherbarer Elemente zu tun. Das ganze würde genauso 
funktionieren mit einem Puffer der 32bit Werte enthält (sodenn man sie 
in eins an die UART weitergeben kann).

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.