Forum: Mikrocontroller und Digitale Elektronik 0x00 über UART übertragen


von Florian Maier (Gast)


Lesenswert?

Hallo zusammen,

ich habe bei der suche im Forum keine entsprechenden beiträge zu meinem
problem gefunden, deshalb meine frage:

ich versuche im moment mit dem MEGA16 daten über die serielle
schnittstelle zu übertragen und via i2c weiterzusenden und umgekehrt.
soweit alles kein problem, die übertragung tut in beide richtungen.
*aber*: da es sich um binärdaten handelt, kommt es auch hin und wieder
vor, dass ein byte mit dem wert 0x00 übertragen werden muss.. das kommt
aber nicht an. es wird einfach ignoriert (bevor es an die i2c-routine
geht). meine idee ist jetzt über eine art escape-sequenz das zeichen zu
codieren. also: wenn 0x00 kommt stattdessen zwei bytes mit z.B. "0x01
0x01" zu übertragen und für den wert 0x01 entsprechend "0x01 0x02".
Oder gibt es da eine andere lösung?
Die zielanwendung ist PC-unabhängig aber im moment simuliere ich den
datentransfer mit minicom unter linux. ist das evtl nur ein pc-problem
oder ist das bei RS232/dem atmel uart nicht vorgesehen?

Gruß, Florian

von Martin (Gast)


Lesenswert?

Hallo.
Eine Frage: Wie hast du festgestellt das ein Nullzeichen nicht ankommt
(ich meine jetzt richtung Mikrocontroller->PC) ?
Ich will ausschliesen das es nur daran liegt das Minicom null-zeichen
ignoriert.

Auf meinem PC werden Null-Zeichen übertragern (allen meinen bisherigen
Beobachtungen nach)

von Florian Maier (Gast)


Lesenswert?

hallo martin,
danke für die schnelle antwort.
das problem tritt im moment in die andere richtung auf:
PC sendet, atmel antwortet mit itoa(UDR, tempstring,10), (integer to
string), des übertragenen bytes. alles andere ist im moment
auskommentiert. und da kommt bei einem 0x00-byte nicht mal der
interrupt.
ob bei der richtung atmel->pc das 0x00-problem auftritt habe ich nocht
nicht ausprobiert (müsste den datenstrom in ein file schicken und mit
dem hex-editor anschauen).

von Florian Maier (Gast)


Lesenswert?

ich hab das jetzt mal über esc-sequencen gelöst, das tut auch soweit
ganz gut. es lebe die modularisierung ;-)

von Thomas Burkhardt (Gast)


Lesenswert?

Was soll denn bei itoa mit 0x00 passieren? Das ist doch kein druckbares
Zeichen...

von Martin (Gast)


Lesenswert?

>Was soll denn bei itoa mit 0x00 passieren? Das ist doch kein
>druckbares Zeichen...

Aber "0" ist ein druckbares Zeichen. itoa konvertiert doch integer in
einen String.

von Florian Maier (Gast)


Lesenswert?

ja, itoa bildet die textrepräsentation eines integers, also nicht das
zeichen 0x00 sondern den String "0"

von Thomas Burkhardt (Gast)


Lesenswert?

ok, ok :)

von Martin (Gast)


Angehängte Dateien:

Lesenswert?

Mikrocontroller habe ich bislang nur im asm programmier, kann also
nichts dazu sagen ob es an itoa liegt.
Naja, ich kann dazu noch sagen, dass es eigentlich möglich ist 0x00 zu
senden und zu empfangen.
Dieser Asm-Code (Anhang) wartet auf 8 Zeichen und sendet sie zurück.
Es funktioniert (jedenfalls bei mir) auch wenn es nur nullen sind.

von Florian Maier (Gast)


Lesenswert?

okay, danke für die antworten.
das itoa verwende ich im moment nur als mittel zum zweck um
herauszufinden woran es liegt/lag. ich vermute, dass mein
terminal-programm das 0-byte nicht korrekt verwertet und nichts
aussendet. habe heute nacht nochmal ein oszi drangehängt und man sieht
rein garnichts bei 0-bytes... und der interrupt kommt ja auch nicht.
toller effekt auf jeden fall, vor allem wenn man sich wundert warum von
64kbyte nur 63.9Kbyte ankommen, obwohl der atmel zu 99% rum-idlet.

gruß, florian

von I. E. (anfaenger69)


Lesenswert?

Ich hänge mich mal an den alten Thread weil ich gerade vor dem gleichen 
Problem stehe.

Ich möchte eine Zeichenkette aus hexadezimalen Daten zu Peter Fleury's 
UART Lib übertragen:

char *zeichenkette = "\x10\x02\x68\x00\xff\x10\x03\x8c" ;
uart_puts(zeichenkette);

Hier scheitert es daran, dass die Lib das 0x00 als Stringende erkennt 
und nach dem 0x68 zum senden aufhört.

So sieht seine Lib aus:

void uart1_puts(const char *s )
{
    while (*s)
      uart1_putc(*s++);

}

Wie löse ich das am besten, dass die ganze Zeichenkette übertragen wird? 
Soll ich die Zeichen irgendwie anders deklarieren?

von Ch D. (chrisu) Benutzerseite


Lesenswert?

Schreib am anfang des strings die länge des Strings. Dann sendest du 
soviele Zeichen wie am anfang des Strings angegeben ist.

von Ch D. (chrisu) Benutzerseite


Lesenswert?

1
char *zeichenkette = "\x09\x10\x02\x68\x00\xff\x10\x03\x8c" ;
2
3
4
void uart1_puts(const char *s )
5
{
6
    int tmp = *s;
7
    int count = 0;
8
    while (count != tmp)
9
      uart1_putc(*s+count++);
10
11
}


sowas in der Art vielleicht?

von I. E. (anfaenger69)


Lesenswert?

Kann man die Länge der Zeichenkette nicht irgendwie in der Funktion 
ermitteln? Endet *s denn nie?

von Karl H. (kbuchegg)


Lesenswert?

Das Problem ist, dass die Lib auf Strings aufgebaut ist.
Ein String endet aber definitionsgemäs bei einem 0x00 Zeichen.

Was du da hast sind keine Strings. Daher ist die Funktion uart1_puts und 
alle Stringfunktionen ganz einfach die falschen Werkzeuge für das was du 
vor hast.

Um weiter zu kommen, musst du von Strings Abschied nehmen und auf Bytes 
neu aufbauen.

von Karl H. (kbuchegg)


Lesenswert?

Igor Ebner schrieb:
> Kann man die Länge der Zeichenkette

Du hast keine Zeichenkette, die den C Regeln für eine Zeichenkette 
genügt.

> nicht irgendwie in der Funktion
> ermitteln? Endet *s denn nie?

Es gibt kein Kriterium dafür.
Daher musst du allen Funktionen, die mit solchen Daten arbeiten immer 
die Länge deiner Bytefolge mitgeben.

Sieh dir den Unterschied in den Familien der str... und mem... 
Funktionen an. Die str... Funktionen sind für Strings. Die mem... 
Funktionen sind für beliebige Bytefolgen.

von I. E. (anfaenger69)


Lesenswert?

Kannst Du mal ein Beispiel zeigen wie es mit bytes aussehen würde?

von Karl H. (kbuchegg)


Lesenswert?

Wie ich schon sagte: Du musst die Anzahl der Bytes mitgeben
1
#define ARRAY_SIZE(x)  ( sizeof(x) / sizeof(*x) )
2
3
unsigned char zeichen[] = { 0x10, 0x02, 0x68, 0x00, 0xff, 0x10, 0x03, 0x8c };
4
5
void uart1_put_data( const unsigned char * data, size_t len )
6
{
7
  size_t i;
8
9
  for( i = 0; i < len; ++i )
10
    uart1_putc( *data++ );
11
}
12
13
int main()
14
{
15
  ...
16
17
  uart1_put_data( zeichen, ARRAY_SIZE( zeichen ) );
18
19
  ...
20
}

von I. E. (anfaenger69)


Lesenswert?

Ja, so klappt es auch. Danke dafür. Aber trotzdem ist es schade, dass 
die Funktion nicht selbst erkennt, wie viel Hex Daten man ihr schickt - 
ist kein bequemes schreiben, wie man es z.B. von Peter Fleury's UART Lib 
her kennt:

uart_puts("Hello World");

wäre doch viel schöner als:

uart_puts("Hello World",11);

oder

uart_puts(zeichen, ARRAY_SIZE( zeichen ));

von Christopher G. (cbg)


Lesenswert?

Schreib halt eine eigene "putx" Funktion, die bis zu einem anderen 
Terminierungszeichen als 0x00 geht. Wenn du kein Zeichen ausschließen 
kannst, dann gehts nur über die Nachrichtenlänge.

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.