Home > Archive > Tcl > March 2006 > Having trouble with basic serial commands???
You are viewing an archived Text-only version of the thread.
To view this thread in it's original format and/or if you want to reply to
this thread please [click here]
| Author |
Having trouble with basic serial commands???
|
|
|
| Hi,
I am new to the group and have been looking around at the articles
about serial ports. I just can't seem to get it to work. I can send
OK, but I can never read back anything.
I am on WinXP with Tcl 8.4.12. I am trying to talk with a Maxim 1-wire
controller (DS2480B) over a FTDI chip. LabVIEW can talk to it with no
problems except for too much memory overhead :). I have tried Rolf's
Moni program, and it works fine.
Here is the basic serial test I am doing.
proc rd_chan {ch} {
set msg [gets $ch]
puts "Message: <$msg>"
}
set chan [open com4: r+]
fconfigure $chan -mode 9600,n,8,1 -blocking 0 -translation binary
-buffering none
fileevent $chan readable [list rd_chan $chan]
puts -nonewline $chan [binary format c 0x62]
after 500
close $chan
exit
On an O-scope, I can see the 0x62 show up on TX and a 0x63 on RX (don't
ask, that's just what the chip does), but all I get back from TCL is:
% Message: <>
All I want to do is send and receive basic hex data up to 16 bytes
long.
I'm stumped. Any help would be great.
Thanks,
Ken
| |
| Ulrich Schöbel 2006-03-24, 10:01 pm |
| Am Fri, 24 Mar 2006 12:08:29 -0800 schrieb KenT:
> Hi,
>
> I am new to the group and have been looking around at the articles
> about serial ports. I just can't seem to get it to work. I can send
> OK, but I can never read back anything.
>
> I am on WinXP with Tcl 8.4.12. I am trying to talk with a Maxim 1-wire
> controller (DS2480B) over a FTDI chip. LabVIEW can talk to it with no
> problems except for too much memory overhead :). I have tried Rolf's
> Moni program, and it works fine.
>
> Here is the basic serial test I am doing.
>
>
> proc rd_chan {ch} {
> set msg [gets $ch]
> puts "Message: <$msg>"
> }
>
> set chan [open com4: r+]
> fconfigure $chan -mode 9600,n,8,1 -blocking 0 -translation binary
> -buffering none
> fileevent $chan readable [list rd_chan $chan]
> puts -nonewline $chan [binary format c 0x62]
> after 500
> close $chan
> exit
>
>
> On an O-scope, I can see the 0x62 show up on TX and a 0x63 on RX (don't
> ask, that's just what the chip does), but all I get back from TCL is:
>
> % Message: <>
>
> All I want to do is send and receive basic hex data up to 16 bytes
> long.
>
> I'm stumped. Any help would be great.
>
> Thanks,
> Ken
Hi Ken,
use 'read' instead of 'gets'.
Kind regards
Ulrich
| |
| slebetman@yahoo.com 2006-03-25, 8:01 am |
| KenT wrote:
> Hi,
>
> I am new to the group and have been looking around at the articles
> about serial ports. I just can't seem to get it to work. I can send
> OK, but I can never read back anything.
>
> I am on WinXP with Tcl 8.4.12. I am trying to talk with a Maxim 1-wire
> controller (DS2480B) over a FTDI chip. LabVIEW can talk to it with no
> problems except for too much memory overhead :). I have tried Rolf's
> Moni program, and it works fine.
>
> Here is the basic serial test I am doing.
>
>
> proc rd_chan {ch} {
> set msg [gets $ch]
> puts "Message: <$msg>"
> }
>
> set chan [open com4: r+]
> fconfigure $chan -mode 9600,n,8,1 -blocking 0 -translation binary
> -buffering none
> fileevent $chan readable [list rd_chan $chan]
> puts -nonewline $chan [binary format c 0x62]
> after 500
> close $chan
> exit
>
>
> On an O-scope, I can see the 0x62 show up on TX and a 0x63 on RX (don't
> ask, that's just what the chip does), but all I get back from TCL is:
>
> % Message: <>
>
> All I want to do is send and receive basic hex data up to 16 bytes
> long.
>
> I'm stumped. Any help would be great.
>
Read the manual. The 'gets' command waits until there is a newline
character(s) (either "\n", "\r" or "\r\n") before returning any data.
If it doesn't find a newline character then it will buffer all the
recieved bytes so far and return an empty string until it finds a
newline character.
Given how 'gets' works there are two problems in your code. The first
problem is I assume the device you're talking to sends binary data and
does not send a newline character at the end of its data packet. This
means gets will infinitely (until you run out of RAM) buffer all
recieved bytes as long as it doesn't see a newline and keep returning
an empty string to you.
The second problem is that what Tcl recognises as a newline depends on
the -translation setting (lf, cr or crlf). Since you've set it to
binary I'm not sure what Tcl recognises as newlines (maybe defaults to
auto, haven't tested so I don't know).
What you should be using instead is the 'read' command:
proc read_channel {channel} {
set msg [read $channel]
puts "Message: <$msg>"
}
Or if you want to read byte by byte:
set msg [read $channel 1]
| |
| Melissa Schrumpf 2006-03-25, 7:03 pm |
| KenT wrote:
> proc rd_chan {ch} {
> set msg [gets $ch]
> puts "Message: <$msg>"
> }
>
> set chan [open com4: r+]
> fconfigure $chan -mode 9600,n,8,1 -blocking 0 -translation binary
> -buffering none
> fileevent $chan readable [list rd_chan $chan]
> puts -nonewline $chan [binary format c 0x62]
> after 500
> close $chan
> exit
>
>
> On an O-scope, I can see the 0x62 show up on TX and a 0x63 on RX (don't
> ask, that's just what the chip does), but all I get back from TCL is:
>
> % Message: <>
>
> All I want to do is send and receive basic hex data up to 16 bytes
> long.
>
> I'm stumped. Any help would be great.
To fix your problem, use [read] instead of [gets]. Gets won't return
anything until a 0x0d or 0x0a is read.
I don't know how your I/O is expected to work, or how much data you
expect as a result, but you might also want to account for the fact that
even so little data as two bytes might be split into two or more calls
to rd_chan.
That is:
puts $ch [format %c 0x30]
Message: <1>
Message: <2>
could happen if your device returns 0x31 and 0x32, but with a delay
between the bytes long enough for the serial driver to deliver them
separately.
Depending on the architecture of your program, I'd personally deal with
this in one of two ways: (a) declare a global to hold the data, clear it
when you transmit, and append to it when you receive, or (b) pass the
buffer as an argument to rd_chan, e.g.:
Also, you'll probably want to handle errors on the channel checking for
eof or zero-length read.
proc rd_chan {ch {databuf ""}} {
set msg [read $ch]
if {(([eof $ch]) || (![string length $msg]))} {
# do something sensible, however you might define that
return
}
set databuf "$databuf$ch"
binary scan $databuf H* v
puts "Message: <$v>"; # this is much more human-readable
fileevent $ch readable [list rd_chan $ch $databuf]
}
--
MKS
| |
|
| Thanks very much for everyones help.
It has been a while since I did Tcl scripts, and the Read vs Gets thing
just wasn't clicking.
Ken
|
|
|
|
|