Version 22 of serial ports on Windows

Updated 2007-06-11 16:35:15 by LV

Serial Ports on Windows

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 :)


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
 }

Also note that you want:

 set serial [open "COM1:" "RDWR"]

and not

 set serial [open "COM1" "RDWR"]

without that colon (:), you get a file in the current directory called COM1. Also, note that you will 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.


Category Device Control - Category Windows