UltraDMA has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

I am trying to use an RS232 port (via FTDI on USB) and have unexpected trouble: Perl complains that the port is blocked since it has to wait for RLSD(DCD). I spent hours in the Internet to find and try solutions ... but no luck. I even soldered a bridge between DTR and DCD, set DTR to active, and could confirm the physical level change ... still a blocked port.

Here's what I do:

#!/usr/bin/perl require 5.003; use English; use strict; use Win32::SerialPort qw(:PARAM :STAT ); use Win32API::CommPort qw( :RAW :PARAM :STAT 0.20 ); $OUTPUT_AUTOFLUSH=1; my $BlockingFlags; my $buffer; my $Configuration_File_Name='c:\\temp\\tty-conf.txt'; my $count_in; my $count_out; my $flowcontrol; my $InBytes; my $LatchErrorFlags; my $OutBytes; my $quiet=1; my $PortObj; my $string_in; $PortObj = new Win32::SerialPort ('COM3', $quiet)|| die "Can't open CO +M Port: $^E\n"; # $quiet is optional $buffer = $PortObj->can_rlsd_config; print("RLSD_CONF: >$buffer<\n"); $PortObj->baudrate(9600); $PortObj->parity("none"); $PortObj->databits(8); $PortObj->stopbits(1); $PortObj->handshake("none"); # set parameter $PortObj->dtr_active(1); $PortObj->buffers(4096, 4096); # read, write $PortObj->read_interval(100); # max time between read char (millise +conds) $PortObj->read_char_time(5); # avg time between read char $PortObj->read_const_time(100); # total = (avg * bytes) + const $PortObj->write_char_time(5); $PortObj->write_const_time(100); $PortObj->debug(1); $PortObj->stty("-icanon"); # disable eof, erase and kill char, Unix +-style $PortObj->write_settings||undef($PortObj); $PortObj->save($Configuration_File_Name); $flowcontrol = $PortObj->handshake; # current value (scalar) print("HS: >$flowcontrol<\n"); ($BlockingFlags, $InBytes, $OutBytes, $LatchErrorFlags) = $PortObj->st +atus|| warn "could not get port status\n"; print("BF: >$BlockingFlags<\n"); warn "Port is blocked" if ($BlockingFlags!=0); if ($BlockingFlags & BM_fXoffHold) { warn "Waiting for Xoff"; } if ($BlockingFlags & BM_fDsrHold) { warn "Waiting for DSR"; } if ($BlockingFlags & BM_fRlsdHold) { warn "Waiting for Rlsd"; } if ($BlockingFlags & BM_fCtsHold) { warn "Waiting for CTS"; } if ($LatchErrorFlags & CE_FRAME) { warn "Framing Error"; } $buffer=ClearCommError($PortObj, 65535, 0); $count_out = $PortObj->write('TEST'); warn "write failed\n" unless ($count_out); warn "write incomplete\n" if ( $count_out != 4 ); # Bridging TXD and RXD should put 'TEST' into the reveive buffer ($count_in, $string_in) = $PortObj->read($count_out); warn "read unsuccessful\n" unless ($count_in == $count_out); print("RX: >$string_in<\n"); undef $PortObj; exit;
The result is:
RLSD_CONF: >64< HS: >none< Blocking Bits= 0 Input Queue= 0 Output Queue= 0 Latched Errors= 0 ok= 1 BlockingFlags= 0 Error_BitMask= 0 BF: >4< RX: >< Destroying \\.\COM3 Port is blocked at P:/tools/perl/test-serial-monk.pl line 50. Waiting for Rlsd at P:/tools/perl/test-serial-monk.pl line 53. write failed write incomplete Use of uninitialized value $wanted in numeric gt (>) at C:/progs/Perl6 +4/site/lib/Win32/SerialPort.pm line 1212. Closing Win32::SerialPort=HASH(0x60c580) COM3 at P:/tools/perl/test-se +rial-monk.pl line 66.
Any clues? Platform: Windows 7 (can't use Linux at this application).

Replies are listed 'Best First'.
Re: Perl on Windows insists on waiting for serial port's RLSD(DCD)
by Lotus1 (Vicar) on Jan 22, 2016 at 16:43 UTC
    I am trying to use an RS232 port (via FTDI on USB) and have unexpected trouble: Perl complains that the port is blocked since it has to wait for RLSD(DCD). I spent hours in the Internet to find and try solutions ... but no luck. I even soldered a bridge between DTR and DCD, set DTR to active, and could confirm the physical level change ... still a blocked port.

    Hi. From your description it sounds like you are attempting a loopback connection on your serial adapter. For loopback without hardware flow control you only need to connect RXD and TXD, pins 2 and 3 on a DB9 serial connector. For hardware flow control you also need to connect DTR with DSR ( pins 4 and 6 ) and RTS with CTS ( pins 7 and 8 ). National Instruments has a tutorial about serial loopback testing.

    The next step would be to verify that your hardware works. You can do that with Hyperterminal or another terminal program such as PuTTY. With echo 'on' in Hyperterminal you will see what you type but you should see it doubled as it is received back on the RXD pin. It's been a while since I've used Hyperterminal but the setup is pretty simple, something like tell it the com port, baud, etc.

    Finally you might start off with some of the example scripts in the distribution for Win32::SerialPort. Download the tar.gz file and look in the 'eg' folder for stty.plx or try some of the other demo scripts. Let us know what progress you make. I am curious what the application is or if this is just a test.

      Hi!

      Thanks for your reply!

      Well, in fact I want to do some "real" data transfer but at first wrote a simple 4 bytes out 4 bytes in test to see how it works. The application I head for, is communication with an embedded system via a console port. That system does not understand any handshaking, therefore my first test uses just that setting. Disturbingly, although I disabled handshaking entirely, Perl complains about a missing RLSD, even when I supply the physical voltage level.

      My script is stitched together from example code from the CPAN "man" page of Win32::SerialPort. Anyhow, I will try the examples, maybe they do something different.

      Cheers, UltraDMA