Einfaches Terminalprogramm für serielle Kommunilation unter Linux/MacOSX in C
Simple terminal serial port program for Linux/MacOSX in C
For debugging micro controllers in "release mode" a simple "old school" serial
communication, or a similar USB implementation, is still an often used method.
A common way of accessing the port is to use stty
in combination with cat
or
screen
, e.g. for 9600 baud, 8 data bits, 1 stop bit and no parity check:
$ stty -F /dev/ttyX raw ispeed 9600 ospeed 9600 cs8 -cstopb ignpar && cat /dev/ttyX
or
$ stty -F /dev/ttyX raw ispeed 9600 ospeed 9600 cs8 -cstopb ignpar && screen /dev/ttyX
... where ttyX
is the name of the port file (and screen
has options as well
to configure the communication).
However, the settings of the port are (depending on the platform) permanently changed,
cat
does not allow interactive input, and to exit screen
you need to type CTRL-A ->k ->y
.
That can be a bit annoying. This little implementation in C simply forwards the raw
bytes and restores the settings on exit. To exit a short CTRL-C
is enough. See the
source, and if you like it get it here, say make
and start
using it:
Zum Debugging von Microcontrollern wird häufig auf die "gute alte" serielle Schnittstelle (V.24/RS232) oder eine entsprechende USB-basierte Implementation zurückgegriffen. Unter Linux/BSD/MacOS wird darauf üblicherweise direkt von der Shell zugegriffen, Beispielsweise mit 9600 Baud, 8 Datenbits, 1 Stopbit und keiner Paritätsprüfung:
$ stty -F /dev/ttyX raw ispeed 1200 ospeed 1200 cs8 -cstopb ignpar && cat /dev/ttyX
oder
$ stty -F /dev/ttyX raw ispeed 1200 ospeed 1200 cs8 -cstopb ignpar && screen /dev/ttyX
... wobei ttyX
der Dateiname der Portdatei in /dev/
ist.
Die Porteinstellungen werden dabei (abhängig von der Plattform) von stty
permanent überschrieben. Mit cat
ist keine interaktive Eingabe möglich,
und screen
hat seinen eigenen Puffer und (curses) Anzeigemanagement - man muss
CTRL-A ->k ->y
drücken bis man es wieder beendet hat. Das kann alles ein
wenig ärgerlich sein.
Eine "lightweight"-Alternative ist dieses kleine C-Programm. Es leitet die Rohdaten
(stdin
vom Terminal nach seriell, seriell zu stdout
) um und stellt beim Beenden
den normalen Port-Kontext wieder her. Zum Beenden reicht CTRL-C
. Einfach einen
Blick auf den Quelltext und die folgende Bedienungsanmerkung werfen - und wenn's
gefällt hier herunterladen und make
sagen ...
#
# First, the --help :-)
#
Usage: serialport [options] <portfile> [BAUD=115200[PARITY=n[DATABITS=8[STOPBITS=1]]]]
Simple serial port TTY redirection program for (raw) microcontroller
communication. Exit with CTRL-C.
Options:
-h, --help Print this help
-v, --verbose Make the program more chatty (on stderr)
-T, --timeout=N Exit after nothing happened for N seconds
-l, --lines=N Exit after receiving N lines
-d, --disconnect=S Disconnect when receiving this (\n etc allowed)
-t, --timestamp Add timestamp before each line
-e, --local-echo Print the sent characters locally
-w, --char-wait=N Wait N seconds before sending the next byte
-W, --start-wait=N Wait N seconds after opening port before doing anything
-c, --color Print with colors
-n, --control-chars Print non-printable control characters
-D, --debug Print debug messages and dumps (stderr)
Examples:
serialport /dev/ttyS Connect with default values
serialport /dev/ttyS 115200 Set baud rate, rest default
serialport /dev/ttyS 9600N81 Set baud rate, parity, data bits, stop bits
serialport /dev/ttyS -T 0.5 Exit after 0.5s inactivity
serialport /dev/ttyS -d 'Bye\\r' Exit when receiving 'Bye<CR>'
serialport /dev/ttyS -vect Interactive mode with colors, local
echo and timestamps for received lines
echo 'hello!' | serialport -W1.0 /dev/ttyS
Wait 1s before sending the line 'hello!'
cat cmds | serialport -t -l 10 -T 0.5 /dev/ttyS | grep 'data'
Send a file, fetch max 10 lines, quit after
idle port for 0.5s and pipe to grep to fetch
lines containing the text 'data'
Exit codes (for shell programming):
0 = OK, no error
1 = Wrong argument, you mistyped something or the program can't handle it.
2 = Signal caught, e.g. CTRL-C, broken pipe, kill, etc.
3 = Fatal error. Something went wrong internally (memory, bugs(?) etc).
4 = I/O error, e.g. Disk full, USB-serial-converted disconnected ...
(serialport v1.0, stfwi)
# Interactive mode with verbose (print the reason why the program did quit,
# the exit code, and statistics).
# Colors: RED:error, CYAN:sent, BLUE:received, GREEN:Finished without error, GRAY:Debug
$ serialport -vec /dev/tty.usb
HHeelllloo!!
112233
445566
778899
[Exit due to signal: CTRL-C][E0]
[TX:19, RX:20, RX:4 lines]
# Data to sent are piped in.
$ echo -e '1234567890\nABC\n' | serialport -ce /dev/tty.usb
1234567890
ABC
1234567890
ABC
# The same as above, only that a character send delay is added (and quit after 0.5 seconds inactivity).
# Character delays do not change the send baudrate, but it leaves small controllers time to process the data.
# The program still receives at full speed.
$ echo -e '1234567890\nABC\n' | serialport -ce -w0.2 -T0.5 /dev/tty.usb
11223344556677889900
AABBCC
# Interactive, colors, quit on receiving "!<NEW LINE>". New line can be either CR or LF or both.
$ serialport -vc -d '!\n' /dev/tty.usb
Hello!!?
Hello!!
[Exit due to disconnect command][E0]
[TX:17, RX:18, RX:2 lines]
# Pipe in, send and receive until there is inactivity for 0.5 seconds. Then quit.
$ echo -e '1234567890\nABC\n' | serialport -vct -T0.5 /dev/tty.usb
1380545190.24 1234567890
1380545190.24 ABC
[Timed out after 0.5s][E0]
[TX:16, RX:17, RX:3 lines]
# Pipe in a file, quit after having received 10 lines (separated by CR, LF or both)
$ cat test.txt | serialport -vct -l 10 /dev/tty.usb
1380545314.35 1 ABCDEFGHIJKL
1380545314.35 2 ABCDEFGHIJKL
1380545314.35 3 ABCDEFGHIJKL
1380545314.35 4 ABCDEFGHIJKL
1380545314.35 5 ABCDEFGHIJKL
1380545314.36 6 ABCDEFGHIJKL
1380545314.36 7 ABCDEFGHIJKL
1380545314.36 8 ABCDEFGHIJKL
1380545314.36 9 ABCDEFGHIJKL
1380545314.36 0 ABCDEFGHIJKL
[Specified number of lines received][E0]
[TX:195, RX:168, RX:10 lines]
# If something goes wrong, errors are RED
# Wrong TTY
$ serialport -vc /dev/YYT
[Failed to open port: /dev/YYT][E4]
[TX:0, RX:0, RX:0 lines]
# Pulled the USB plug ...
$ serialport -vc /dev/tty.usb
[I/O port error: Inappropriate ioctl for device][E4]
[TX:0, RX:2, RX:0 lines]
# Very high verbosity (DEBUG mode). Prints settings of locals and port, etc:
$ echo -e '1234\n5678\n90\n' | serialport -D -vcet -W0.5 -T0.5 -d '8' /dev/tty.usb > test.txt 2>&1
parse_args() start_wait=0
parse_args() timeout=0.500000
parse_args() disconnect=8
parse_args() portfile=/dev/tty.usb
main() Init serial port
serial_port = {
file = /dev/tty.usb
baudrate = 115200
parity = n
databits = 8
stopbits = 1
local = 1
flush = 1
set_dtr = -1
set_rts = -1
timeout_us = 1000
_state = {
error_code = 0
error_string =
handle = 3
mdlns = 00000026h
mdlns_orig = 00000026h
attr = {
c_iflag = 00000004h
c_oflag = 00000000h
c_cflag = 00038b00h
c_lflag = 00000000h
c_cc = (string)
c_ispeed = 115200
c_ospeed = 115200
}
attr_orig = {
c_iflag = 00000000h
c_oflag = 00000000h
c_cflag = 00034b00h
c_lflag = 00000000h
c_cc = (string)
c_ispeed = 9600
c_ospeed = 9600
}
}
};
main() Local input is STDIN
main() Local input is STDOUT
main() Local input is NO TTY
main() Local output is NO TTY
main() Prepare run
main() Initial timeout: 0.500000
main() Run ...
[RX 1]
1380547573.27