www.mikrocontroller.net

Forum: Compiler & IDEs Uart HEX 00 Senden


Autor: Rukula (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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….

Autor: Stefan B. (CDLinux) (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht 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:
static volatile int txBuf[255];           // RS232 Transmit Buffer
static volatile int index_txBuf_R = 0;    // Index wo TXBuffer zuletzt gelesen wurde
static volatile int index_txBuf_W = 0;    // Index wo TXBuffer zuletzt geschrieben wurde
/***************************************************************/

void txBuf_Write(unsigned char parameter){  // TX-Buffer mit Werte füllen
  if(index_txBuf_W == Buf_max){           // Damit Ringbuffer nicht überläuft
    index_txBuf_W = 0;
  }
  else{
    index_txBuf_W ++;
  }
  txBuf[index_txBuf_W] = parameter;
}
void UART_Transmit(int Num_of_bytes, unsigned char *param){ // Anzahl Parameter und Parameters übergeben
  int q = 0;
  static int StartIndex = 0;              // Index wo Transmit-Frame gestartet werden soll
  
  txBuf_Write(Num_of_bytes);
  StartIndex = index_txBuf_W;             // Aufgepasst ein neuer Frame beginnt!
  for(q = 0; q < Num_of_bytes; q++){
    txBuf_Write(param[q]);
  }
  txBuf_Write(crc8_messagecalc(param, Num_of_bytes));  // CRC8 berechnen und abspeichern
  if(index_txBuf_R == Buf_max){           // Buffer am überlaufen hindern  
    index_txBuf_R = 0;
  }
  else{
    index_txBuf_R ++;
  }
  UCSRA |= (1<<TXC);                      // TXC Flag zurücksetzen, dass bei Aktivierung nicht in ISR springt
  UCSRB |= (1<<TXCIE);                    // Für Frame TX Complete Interrupt aktivieren
  RXTX_Reg = txBuf[StartIndex];           // Frame ist aufgebaut/Com starten mit Number of Bytes senden
}

/***************************************************************/
ISR(USART_TXC_vect){                       // Transmit Complete Interrupt
  if(index_txBuf_R == Buf_max){            // Damit Buffer nicht überläuft
    index_txBuf_R = 0;
  }
  else{
    index_txBuf_R ++;                      // Index erhöhen
  }  
  if(index_txBuf_R == index_txBuf_W){      // Damit Read Write nicht überholt
    UCSRB &= (~(1<<TXCIE));                // Frame beendet, TX Complete Interrupt deaktivieren
  }
  RXTX_Reg = txBuf[index_txBuf_R];         // Daten senden
}
/***************************************************************/
int main(void){
  unsigned char array[]={"Hallo welt"};    // Gibt als Parameter "Hallo welt" aus, abgeschlossen mit 00
  SysInit();
  while(1){
    int Num_bytes = ((sizeof(array)/sizeof(array[0])) - 1);  // Arrayplätze berechnen, letzter Platz ignorieren
    UART_Transmit(Num_bytes, array);       // Werte übergeben und senden
  }
}
hab hier nicht den ganzen Sourcecode gepostet, musst ihn aber auf deine 
Bedürfnisse anpassen...

hoffe es hilft dir trotzdem weiter...
MFG
Patrick

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@  Patrick B.
Man lernt nie aus:
static volatile int txBuf[255];           // RS232 Transmit Buffer
static volatile int index_txBuf_R = 0;    // Index wo TXBuffer zuletzt gelesen wurde
static volatile int index_txBuf_W = 0;    // Index wo TXBuffer zuletzt geschrieben wurde
/***************************************************************/

void txBuf_Write(unsigned char parameter){  // TX-Buffer mit Werte füllen
  if(index_txBuf_W == Buf_max){           // Damit Ringbuffer nicht überläuft
    index_txBuf_W = 0;
  }
  else{
    index_txBuf_W ++;
  }
  txBuf[index_txBuf_W] = parameter;
}
:

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:
volatile unsigned char txBuf[256];           // RS232 Transmit Buffer
volatile unsigned char index_txBuf_R = 0;    
volatile unsigned char index_txBuf_W = 0;    
/***************************************************************/

void txBuf_Write(unsigned char parameter){  // TX-Buffer mit Werte füllen
  index_txBuf_W++;     // hier Preincrement, aber besser sollte der Index erst nach dem Beschreiben des Speicherplatzes erhöht werden...
  txBuf[index_txBuf_W] = parameter;
}
:
Damit fallen die ganzen Abfragen nach Buf_max aus dem Code heraus, 
weil der Index (als char) niemals größer als 255 werden kann.

Autor: Patrick B. (p51d)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Da I (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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:
volatile unsigned char txBuf[16];           // RS232 Transmit Buffer
volatile unsigned char index_txBuf_R = 0;    
volatile unsigned char index_txBuf_W = 0;    
/***************************************************************/

void txBuf_Write(unsigned char parameter){ // TX-Buffer mit Werte füllen
  txBuf[index_txBuf_W&0xf] = parameter;    // nur 16 Speicherplätze, deshalb Maske über die unteren 4 Bits
  index_txBuf_W++;                         // der Index darf ruhig weiterlaufen, es werden ja nur die unteren 4 Bits verwendet
}
  // Abfrage, ob ein Element im Puffer
  if (index_txBuf_W!=index_txBuf_R) {
      wert = txBuf[index_txBuf_R&0xf];
      index_txBuf_R++;
  }
:
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.

Autor: Patrick B. (p51d)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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:
volatile unsigned char txBuf[256];           // RS232 Transmit Buffer
volatile unsigned char index_txBuf_R = 0;    
volatile unsigned char index_txBuf_W = 0;    
/***************************************************************/

void txBuf_Write(unsigned char parameter){   // TX-Buffer mit Werte füllen
  txBuf[index_txBuf_W & 0xFF] = parameter;  // nur 16 Speicherplätze, deshalb Maske über die unteren 4 Bits
  index_txBuf_W ++;                         // der Index darf ruhig weiterlaufen, es werden ja nur die unteren 4 Bits verwendet
}
  // Abfrage, ob ein Element im Puffer
  if (index_txBuf_W!=index_txBuf_R) {
      wert = txBuf[index_txBuf_R & 0xf];
      index_txBuf_R ++;
  }
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

Autor: klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: doc (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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..

Autor: Lothar Miller (lkmiller) (Moderator) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht 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).

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.