Mit der Bash Binärzahlen auf Com Port ausgeben

Gast #3866111
Hallo,

ich stehe vor folgedem Problem einem Controler am USB ein Programm zu 
übermitteln und dabei das Ende der daten zu signalisieren. Protokoll ist 
so billig wie nur möglich:

s     = Startzeichen
nnnn  = 2 Bytes für Datenlängae
nnnn x 1 Byte Datentransfer
Ende

Bisher bin ich nur soweit:

echo "s" > dev/ttyUSB0
stat -c %s binaer.bin > /dev/tty
cat daten.bin > /dev/ttyUSB0

Wertebereich Datenlänge = 1 .... ca 40000.

der stat Ausdruck überträgt halt nur die Dateilänge als String mit 
variabler Länge, den ich wieder umständlich in eine Binärzahl umbauen 
müsste, zudem ich nur Zeichen und keine Strings variabler Länge 
empfangen kann. der Asm Code soll so knapp wie möglich auf der 
Empfängerseite sein, 2  chars, zusammenbauen zu einem int und fertig.

Wie müsste man es formulieren, dass der stat Ausdruck das binäre 
Aquivalent zu der Dateilänge ausgibt?

gruss,
Christian
Gast
Für solche Aufgaben ist die bash oder auch jede andere shell das falsche 
Schwert. Was z.B. passiert, wenn dir zwischen "echo ..." und "stat ..." 
ein anderer Prozess den Port klaut?

MfG Klaus
Gast
Hallo Christian,

Christian J. schrieb:
>
> s     = Startzeichen
> nnnn  = 2 Bytes für Datenlängae
> nnnn x 1 Byte Datentransfer
> Ende
>
> Bisher bin ich nur soweit:
>
> echo "s" > dev/ttyUSB0
> stat -c %s binaer.bin > /dev/tty
> cat daten.bin > /dev/ttyUSB0

und zum schluss noch:

echo "nnnn" Ende

must du natürlich im Kontoler definieren...

Oder habe ich da was falsch verstanden??
Gast
Christian J. schrieb:
> neumodisches Python
Naja, so "neumodisch" ist das nun auch nicht, gibts immerhin (laut 
wikipedia) schon seit 1991. :P
1
#!/usr/bin/env python3
2

3
# Bevor das Modul serial genutz werden kann, muss PySerial installiert sein
4
# Entweder Python-Pip installieren und dann mit: pip install pyserial
5
# installieren, oder über deine Paketverwaltung, unter Arch z.B.
6
# yaourt -S Python-Pyserial
7

8
import serial
9

10
ser = serial.Serial('/dev/ttyUSB0', <Baudrate>) # Port oeffnen
11
ser.write(<hier deine Daten>)  # Daten auf port schreiben
12
ser.close()                    # Port schliessen

Die .write()-Funktion unterscheidet sich zwischen den Pythonversionen 
2.x und 3.x einbisschen, inbezug darauf, was man für daten reinschiebt. 
Es muss eventuell gecastet werden.
Gast
Hi,

ich werde das Python Script mal ausprobieren, michda soweit einlesen, 
dass ich wenigstens 10 Zeilen hinkriege. Die andere Sache die ich grad 
überdenke ist einen einfach Intel Hex Interpreter zu schreiben, der das 
eh auf 7 Bit umcodiert und eine Endesequenz hat, die der Slave erkennen 
kann. Das ist sicherlich eine saubere Lösung, die zudem standardisiert 
ist.

PS: Die %4 printf Variante erzeugt zb bei einem 1177 Byte großen File, 
in eine test.dat geschrieben und mit

>$hexdump test.dat angeschaut

000000 30 34 39 39   = 0x0499
000004

allerdings eben auch als String. Der wiederum mit Bordmitteln wie BCD 
Umwandlung und Subtraktion in 04 99 umcodiert werden müsste.

Klar, printf ist ascii textbasiert, damit kann man keine Binärdaten 
ausgeben, versteht ja ein Bildschirm nicht.


Gruss,
Christian
1
perl -e ´open F, $ARGV[0] or die; $s = -s $ARGV[0]; $h = $s >> 8; $l = $s & 0xff; printf ¨%c%c¨, $h, $l; sysread( F, $b, $s ) == $s or die; close F; print $b´ binaer.bin > /dev/ttyUSB0

Die Dateilänge ist hier in Big-Endian, kannst du auch umdrehen. Die 
einfachen und doppelten Anführungszeichen könnten falsch sein, die 
kommen von ´nem Tablett, keine Ahnung wie die kodiert sind, einfach die 
ASCII-Versionen davon verwenden.
Moderator
Little Endian:
1
len=$(stat -c %s binaer.bin)
2
printf "$(printf '\\x%x' $((len & 0xff)))$(printf '\\x%x' $((len >> 8)))" > /dev/ttyUSB0

oder besser: integriert in dieses Konstrukt:

Daniel A. schrieb:
> {
>   echo ...
>   stat ...
> } > /dev/tty

Big Endian: anders herum

BTW: Printf ist ein Bash-Builtin, erzeugt also keinen Overhead für das
Laden des Kommandos.
Gast
Konrad S. schrieb:
> perl -e ´open F, $ARGV[0] or die; $s = -s $ARGV[0]; $h = $s >> 8; $l =
> $s & 0xff; printf ¨%c%c¨, $h, $l; sysread( F, $b, $s ) == $s or die;
> close F; print $b´ binaer.bin > /dev/ttyUSB0

Mal eine Frage: Hast Du das jetzt so aus dem kragen gezogen? 
Wahnsinn....
Gast
Konrad S. schrieb:
> perl -e ´open F, $ARGV[0] or die; $s = -s $ARGV[0]; $h = $s >> 8;
> $l = $s & 0xff; printf ¨%c%c¨, $h, $l; sysread( F, $b, $s ) == $s or
> die; close F; print $b´ binaer.bin > /dev/ttyUSB0
> Die Dateilänge ist hier in Big-Endian, kannst du auch umdrehen. Die
> einfachen und doppelten Anführungszeichen könnten falsch sein, die
> kommen von ´nem Tablett, keine Ahnung wie die kodiert sind, einfach die
> ASCII-Versionen davon verwenden.
Wenn man beliebige Binaerformate hinbiegen muss (verschiedene 
Endianness, Double, Single,...)
http://perldoc.perl.org/functions/pack.html

Antwort schreiben

Eine eigene Frage? Dieser Thread ist über 12 Jahre alt. Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.

Neuen Thread starten

Eine Lösung, Ergänzung oder Rückmeldung zu diesem Thread? Dann antworte hier.

Formatierung
  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] – Link zu einem Artikel
  • Verweis auf einen anderen Beitrag: Rechtsklick auf dessen Beitrags-ID (#8078628), „Adresse kopieren“, in den Text einfügen

Mehr zur Formatierung

Längeren Sourcecode als Anhang, nicht in den Text. JPG nur für Fotos und Scans; Zeichnungen und Screenshots als PNG oder GIF. Siehe Bildformate.

Schon registriert? Anmelden

Wird nicht angezeigt. Wir schicken dir einen Link; sobald du damit bestätigst, erscheint dein Beitrag.

Mit dem Abschicken legst du einen kostenlosen Account an und erkennst die Nutzungsbedingungen und die Datenschutzerklärung an.