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….
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.
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
@ 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.
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
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.
> 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.
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
> 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
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..
> 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.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.