Version 30 of serial ports on Windows

Updated 2011-10-14 14:16:35 by dkf

I created this page in case some people may have some questions or answers about using a serial port on Windows.

I just tried to communicate with com1 on a Windows 2000 machine. For some reason I could not receive any data using the following commands in Wish.

   % proc rd_chid {chid} {
   set msg [gets $chid]
   puts $msg
   }
   % set com [open com1: r+]
   % fconfigure $com -mode 9600,n,8,1 -blocking 0 -translation auto -buffering line
   % fileevent $com readable [list rd_chid $com]

However, I was able to receive data by putting those last 3 lines into its own procedure...

   % proc rd_chid {chid} {
   set msg [gets $chid]
   puts $msg
   }
   % proc open_com {} {
   global com
   set com [open com1: r+]
   fconfigure $com -mode 9600,n,8,1 -blocking 0 -translation auto -buffering line
   fileevent $com readable [list rd_chid $com]
   }
   % open_com
   # lots of data comes streaming :)
   % close $com

jg


Tcl 8.4 greatly improved serial port control across platforms. Refer to the updated fconfigure documentation for more info.


To retrieve details on input/output errors--which are, in general, frequent, when working with serial lines--interrogate

    set details [fconfigure $serial_handle -lasterror]

8.3.4 introduced this capability.


How can I connect to a com port higher than 9? (I am using a terminal server, and its driver creates com ports upto 16 or so.) Would appreciate answer by mail - [email protected]

Thanks

25Aug2003 PS: You need to use the 'generic' name (I think it is actually the UNC path) of the com port. Use the file name \\.\com13 to open 'com13:' Mind you, windows wants to see those all those \ chars, so use [open \\\\.\\com13 r+]. I have not tested this myself... E_NO_ACCESS_TO_BIG_SERIAL_CARD. But it does work :)

20111014 tested with 8.5.9: open //./com13 definitely works (or \\\\.\\com13), shorter variants don't. Interesting detail: if you are using a tclkit app, you can open com5 etc only if you have the current directory NOT within tclkit VFS, but outside of this (com1...4 always open regardless current dir). But using the absolute path as proposed above, VFS or normal current directory does not matter.


The following code will enumerate the serial devices on a windows XP machine - including USB devices.

 package require registry
 
 proc get_serial_ports { } {
    set serial_base "HKEY_LOCAL_MACHINE\\HARDWARE\\DEVICEMAP\\SERIALCOMM"
    set values [ registry values $serial_base ]
 
    set result {}
 
    foreach valueName $values {
       lappend result [ registry get $serial_base $valueName ]
    }
 
    return $result
 }

Yep, the above works fine on XP. Try " return lsort -dictionary $result" to get the list sorted... -regards

ZB 20111012 - yes, it works on my Win XP - but I had the problem, that id did list also the "virtual serial ports" left by Bluetooth device (not connected). Trying to open such serial port resulted in very long pause (almost a minute), before "open" gave up.


enumerate serial devices on win2k-win7(Jee Labs version [L1 ])

 # 2010-04-21 improved version, see http://talk.jeelabs.net/topic/208
 proc RawListSerialPorts {} {
   set result {}
   set ccs {HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet}
   foreach {type match} {
     Serenum {^FTDIBUS.*_6001.(\w+)}
     usbser  {^USB\B.*\B(.*)$}
   } {
     # ignore registry access errors
     catch {
       set enum "$ccs\\Services\\$type\\Enum"
       set n [registry get $enum Count]
       for {set i 0} {$i < $n} {incr i} {
         set desc [registry get $enum $i]
         if {[regexp $match $desc - serial]} {
           set p [registry get "$ccs\\Enum\\$desc\\Device Parameters" PortName]
           # Log . {usb-$serial Port: $p\
                     Friendly: [registry get "$ccs\\Enum\\$desc" FriendlyName]}
           lappend result usb-$serial $p
         }
       }
     }
   }
   return $result
 }

Note that you most frequently see code something like this:

 set serial [open "COM1:" "RDWR"]
 fconfigure $serial -mode 9600,n,8,1

where fconfigure sets the baud rate, etc. of the serial port.

ZB The above procedure didn't work at all on my Win XP.