'''serial port''' ** See Also ** [[`[chan configure]`] ([[`[fconfigure]`]): the standard command for configuring serial port channels [channel]: nearly everything but the [[`[socket]`] information is related to serial ports [[`[close]`]: for closing a serial port channel [[`[fileevent]`]: for readable/writable callbacks [[`[open]`]: the standard command to open serial ports. port names are platform-dependent. all relevant serial-port options to fconfigure are described on th man page for [[`[open]`] [Parallel port]: [serial ports on Windows]: [http://www.lvr.com/serport.htm%|%Serial Port Central]: Jon Axelson's site about serial links and networks, including RS-232, RS-485, COM ports, and USB virtual COM ports, and his book, "Serial Port Complete" [Simple TCP/IP to serial port gateway]: ** Documentation ** [http://en.wikipedia.org/wiki/Serial_port%|%serial port] ,Wikipedia: [http://en.wikipedia.org/wiki/RS-232%|%RS-232] ,Wikipedia: ** Examples ** [apache tcl cgi script with serial port access]: [Bwise, a serial port tcl script and a Xilinx demo board]: [A simple serial terminal]: How to build a simple serial terminal in a [text] [widget] [How to read the serial port, and display in hexadezimal]: [List computations in a FPGA, driven by Tcl]: [More Serial Port Samples]: [How to read the serial port, and display in hexadezimal]: [Serial Port Logic Analyzer Screen Capture]: ** Tools ** [moni]: a serial line monitor [http://www.lostbard.com/serialplayer/index.html%|%Serial Player]: a [Microsoft Windows%|%Windows] utility for recording and playing back data from the serial communications port of the computer [http://technet.microsoft.com/en-us/sysinternals/bb896644.aspx%|%Portmon for Windows]: a proprietary but freely available program that displays all serial and parallel port activity on a system [http://sourceforge.net/projects/slsnif/%|%Serial line sniffer]: open-source license [Tcl-DP]: provides serial line features ** Description ** On [Linux], opening a special device with the proper major/minor numbers always succeeds independent of there being any hardware attached or not. The first error usually happens when doing [[`[chan configure] -mode ...]`] with `-mode` not a valid option for ... On [NetBSD], when a terminal file is opened, it normally causes the process to wait until a connection is established. For most hardware, the presence of a connection is indicated by the assertion of the hardware `CARRIER DETECT (DCD)` line. This is a problem since most hardware and/or cables in common use ignores this line. Using the `NONBLOCK` flag with [[`[open]`] is not enough to get things right, because the `DCD` is also used to detect the [[`[eof]`] condition, causing the channel to assert [[`[eof]`] after the first [[`[read]`] or [[`[gets]`]. There's patch at [http://sourceforge.net/tracker/?func=detail&atid=360894&aid=3324195&group_id=10894%|%feature request 603] which adds a new flag to [[`[chan configure]`], `-ignoredcd` (only on unix machines with conforming termios interface) which controls whether the underlying device driver ignores the `DCD` line or not. Without this patch, the (non-portable) way to use a serial port lacking the `DCD` line is: ====== set device /dev/tty00 set fd [open $device {RDWR NONBLOCK}] exec stty -f $device clocal ====== Serial lines have many characteristics known to Tcl. [fconfigure] is their usual interface. Typical options include '''`-ttycontrol`''', '''`-ttystatus`''', '''`-timeout`''', and more. ** Basic Example ** D. J. Hagberg mailto:dhagberg@millibits.com: Here is a simple example... The [send_exp] stuff is pretty generic and should work for any channel that supports non- blocking I/O. ====== # simple serial port example to send AT to modem and # wait for OK response in a fixed amount of time. At the # bottom is a simple loop to do this 20x to check serial # handler reliability... # # Works well on Tcl 8.0 and up on Unix (Solaris/NT), poorly on # the tclsh included with Tcl 8.1.1 on NT, but pretty well on # the wish included with same. # # NOTE may need to set comPort appropriately for your # platform. Must have a modem configured to respond # with "OK" to "AT" commands. # switch $tcl_platform(os) { {Linux} {set comPort /dev/modem} {SunOS} {set comPort /dev/cua/a} {Windows NT} {set comPort COM2:} default {error "Must configure comPort"} } set waitSecs 2 set nTries 20 # # A cheap version of expect. # # Set up a event-driven I/O reader on the channel, output the # string, and wait some number of seconds for the result. # # @param fh # a channel opened in non-blocking mode for I/O # with buffering turned off. # # @param outstr # a string to send to the output channel -- note: end- # of-line characters must be included in this string, # if desired. # # @param regexp # regular expression to match in the incoming data. # # @param seconds # number of seconds to wait for above match # # @throws error # if eof is detected on the channel while waiting # # @returns int # 1 if a match is found, 0 otherwise. # proc send_expect {fh outstr regexp seconds} { global send_exp # make sure global vars are initialized properly set send_exp($fh.matched) 0 if {![info exists send_exp($fh.buffer)]} { set send_exp($fh.buffer) {} } # set up our Read handler before outputting the string. if {![info exists send_exp($fh.setReader)]} { fileevent $fh readable [list private_send_exp_reader \ $fh $regexp] set send_exp($fh.setReader) 1 } # output the string to send puts -nonewline $fh $outstr flush $fh # set up a timer so that we wait a limited amt of seconds set afterId [after [expr {$seconds*1000}] \ [list set send_exp($fh.matched) 0]] vwait send_exp($fh.matched) set matched $send_exp($fh.matched) unset send_exp($fh.matched) catch [list after cancel $afterId] # If we got an eof, then throw an error if {$matched < 0} { error "Channel EOF while waiting for data" return 0 } return $matched } # # PRIVATE channel read event handler for send_expect. Should # not be called by user. # proc private_send_exp_reader {fh regexp} { global send_exp if {[eof $fh]} { close $fh set send_exp($fh.matched) -1 return } append send_exp($fh.buffer) [read $fh] if {[regexp $regexp $send_exp($fh.buffer)]} { set send_exp($fh.matched) 1 } } # # Return the current contents of the send_expect buffer # # @param fh # channel identifier that was used with send_expect # # @returns string # the current contents of the buffer for the channel # proc send_exp_getbuf {fh} { global send_exp return $send_exp($fh.buffer) } # # Reset the send_expect buffer, returning its contents # # @param fh # channel identifier that was used with send_expect # # @returns string # the current contents of the buffer for the channel # proc send_exp_resetbuf {fh} { global send_exp set buf $send_exp($fh.buffer) set send_exp($fh.buffer) {} return $buf } # # Close out a send_expect session, closing I/O event handler # # @param fh # channel identifier that was used with send_expect # # @returns # the channel identifier passed as the fh parameter # proc send_exp_end {fh} { global send_exp fileevent $fh readable {} foreach v [array names send_exp $fh.*] { catch [list unset send_exp($v)] } return $fh } ## ## MAIN ## set fh [open $comPort RDWR] fconfigure $fh -blocking 0 -buffering none \ -mode 9600,n,8,1 -translation binary -eofchar {} # Loop nTries times, sending AT to modem and expecting OK. set nMatches 0 for {set i 0} {$i < $nTries} {incr i} { if {[send_expect $fh "AT\r" "OK" $waitSecs]} { incr nMatches regsub -all "\r" [send_exp_getbuf $fh] {\r} buf regsub -all "\n" $buf {\n} buf puts "GOT MATCH: <$buf>" } else { puts "NO MATCH IN $waitSecs SECONDS" } send_exp_resetbuf $fh } send_exp_end $fh close $fh puts "Matched $nMatches/$nTries\ ([expr 100.0*$nMatches/$nTries]%)" ====== ---- [RJM]: Via the serial communication resources, one can also communicate via USB. However, this will surely work with one specific USB peripheral chip, namely from FTDI. Resource: http://www.ftdichip.com/FTDrivers.htm They provide a royalty-free USB driver. With Tcl apps the virtual com port driver can be used. Advantages over RS-232: * USB protocol handles transmission errors, so protocol free communication is possible * high speed I myself created a project with Tcl and USB: http://www.msp430web.de/msp430-usb.htm (note that downloadable software resources here may need an update). [MS] 2005-01-09: If you want to use the ftdi-chip with a [Linux] system you can also use the RS-232-emulation of the Linux driver. The USB chip can then be accessed as if it were an RS-232 chip. You can look at http://www.enertex.de/linux/ftdi for some basic code examples. ---- [Twylite]: Note that on Windows you can use the device aliases "COM1" .. "COM9" (the trailing colon is not necessary), but to access higher numbered COM ports (quite common when using USB-to-serial converters or Bluetooth dongles) you must use the Win32 device name e.g. {\\.\COM14} . <> Device Control | Channel