How to read the serial port, and display in hexadecimal


Here is the code, I'm using to read and display the data stream coming via the serial interface. I'm displaying the content in 0x?? notation to ease readability. The TCL script works fine and should help debugging. I use it for debugging purposes, ie my microcontroller has few memory, therefore I can make hex-dumps in this way.

### Constants
set baudrate   38400
set parity     n
set databits   8
set stopbits   1

### G U I
text .t1 -width 85 -font {courier 8 } -tabs {3c 6c 9c 13c left}\
    -cursor gobbler
pack .t1 -side top -anchor nw
button .b1 -text Exit -command exit
pack .b1 -side bottom -anchor nw -fill x -expand true
wm title . "Com1 Reader - HexCharacters "

### M A I N
.t1 tag configure underline -underline true
.t1 tag configure bold -font {courier 10 bold}
.t1 tag configure finsih -font {courier 6}
.t1 insert end "\tRead COM1: $baudrate, Parity=$parity,\
    Databits=$databits, Stopbits=$stopbits\n\n" {underline bold}

### Procedures

proc rd_chid {chid} {
    set msg [read $chid 3]
    set listOfLetters [split $msg {} ]
    set serialIPinHex ""
    foreach iChar $listOfLetters {
        scan $iChar "%c" decimalValue
        set hexValue [format "%02X" $decimalValue ]
        set hexValue "0x$hexValue"
        set serialIPinHex "$serialIPinHex $hexValue"
    .t1 insert @0,0 "hallo:\"$serialIPinHex\"\n"   

proc open_com {} {
    global com
    global baudrate
    global parity
    global databits
    global stopbits
    set com [open com1: r+]
    fconfigure $com -mode $baudrate,$parity,$databits,$stopbits \
        -blocking 0 -translation auto -buffering none -buffersize 12
    fileevent $com readable [list rd_chid $com]


# the channel shouldn't be closed before exiting

#close $com


Very special, reading data in bunches of 3 ... nevertheless, if you want it that way you can have it. And you can have it better!

You cared about setting tabs, a funny cursor and underlined information, but you didn't care about an important thing: Scrolling! Seeing new info arriving at the top and old info disappering into an unknown bottom is awkward. Let me improve the GUI, adding 2 lines, rearranging 4 lines to fit the new style. Yes, you're allowed to introduce your cursor again, if this is what you really want your program to show.

### G U I
button .b1 -text Exit -command exit
pack .b1 -side bottom -fill x -expand true
text .t1 -width 85 -font {courier 8} -yscrollcommand ".s1 set"
scrollbar .s1 -command ".t1 yview"
pack .s1 -side right -fill y -expand true
pack .t1 -side left
wm title . "Com1 Reader - HexCharacters "

Now, add smart autoscolling, it works this way: If the text area is scrolled to the bottom, scroll it to the (new) bottom after inserting a string, keep the position otherwise. Sounds simple, is simple. (This is Tcl.)

proc output str {
    lassign [.t1 yview] y0 y1
    .t1 insert end $str
    if {$y1 == 1} {
        .t1 see end

Rewrite the event callback to make use of all this (and a little bit more). Needs Tcl8.5 or a backport of the binary command since it uses the unsigned "u".

proc rd_chid {chid} {
    set msg [read $chid 3]
    binary scan $msg cu* valueList
    set str "hallo:"
    foreach value $valueList {
        append str [format " 0x%02X" $value]
    output "$str\n"

I hope I gave enough hints to further improve your serial line debugging.