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

I am trying to open port COM1 at 115200 baud using the following code:
unless ($Port = new Win32::SerialPort($PortName) and $Port->baudrate($Baudrate) and $Port->parity('none') and $Port->databits(8) and $Port->stopbits(2) and $Port->handshake('rts') and $Port->buffers(4096,4096) and $Port->binary(1) and $Port->xon_limit(3000) and $Port->xoff_limit(300) and $Port->rts_active(1) and $Port->write_settings) { $mw->messageBox( -message => "Can't open $PortName at $Baudrate baud.", -type => 'OK' ); exit }
After first powering up my computer, it fails. Further investigation has shown that it's because COM1 doesn't, at this point, show 115200 baud as one of its capabilities (using WIN32API::CommPort's can_baud method). However, if I first open COM1 at 115200 baud using HyperTerminal, then close it, the above code will allow me to do so, too -- until rebooting. And, indeed, can_baud then lists 115200 as a capability for COM1. So what is HyperTerminal doing to force this capability that I can't also do in perl? Thank you!

Replies are listed 'Best First'.
(jcwren) Re: Windows serial I/O
by jcwren (Prior) on Oct 08, 2000 at 01:09 UTC
    I've used the Windows serial port drivers fairly extensively, and haven't run into this problem. Does this problem occur at other baud rates? And have you checked that you're running the latest version of Win32::SerialPort? I'm running under NT, which (IMHO) has better support than Win95/98.

    I ran your code, and had no problems, trying a number of baud rates and reboot combinations (which takes a dang long time with 256MB of memory, and 4 SCSI devices on the chain...).

    --Chris

    e-mail jcwren
      Thanks for the reply and all your trouble to test my code! The problem only occurs at 115200 baud. Other baud rates, up to 38400 at least, show up in can_baud and are functional immediately after powerup. I do have the latest version of Win32::SerialPort, as well as Win32API::CommPort. I'm running under Win98. -Phil
Re: Windows serial I/O
by Anonymous Monk on Oct 08, 2000 at 06:24 UTC
    Hey - I don't know enough about perl to help you on that end of things, but have you checked the properties of the com port in device manager? There should be a settings tab where you can change the 'maximum baud rate'.

    Not sure at all if that has anything to do with it, but I guess it's worth a check...maybe... *shrug*

    -RN

Re: Windows serial I/O
by Anonymous Monk on Oct 23, 2000 at 22:15 UTC

    I e-mailed this question to Bill Birthisel, the author of Win32::SerialPort and Win32API::CommPort. My original query and his answer (with his permission) follow:

    ______________________

    I'm trying to open COM1 at 115200 baud on a Win98 machine using Win32::SerialPort. After first rebooting, I cannot. In fact, can_baud(115200) returns false, and are_baudrate omits 115200. Other baudrates, up to 38400, work fine. If I then go to HyperTerminal, I can open the same port at 115200, no problem. What's more, if I close the port, then exit H-T and return to my Perl program, it too will open COM1 at 115200 baud -- at least until I change baud rates. Then I need to go back to H-T to set up the port again. I'm using the latest versions of both Win32API::CommPort and Win32::SerialPort.

    <GIGGLE>
    True, Win9x does not consider 115200 and 57600 legal rates. It DOES accept 56000. This is a long-standing bug in the Windows API which Microsoft has decided not to fix. In the original concept, only TAPI could request the highest rates because "standard serial ports" (8250s/16450s) couldn't keep up. Of course, that doesn't explain 56000 (NT/2000 uses the correct 57600 and also allows 115200).
    </GIGGLE>

    So I'm wondering: What's happening here? What's HyperTerminal doing to gain access at 115200 baud that Perl can't do on its own?

    It is ignoring the baud-rate validation feature in the API.

    Can I get around this by altering the DCB using Win32API::CommPort?

    Yes.

    Should I? Is there a better way? So many questions!

    You can try what I suggested to someone else (who didn't confirm it worked, so consider it an experiment):

    In CommPort.pm, change the are_baudrate routine to the following:

    sub are_baudrate { my $self = shift; return unless $self->{"_C_BAUD"}; if (@_) { my $newbaud = shift; $self->{"_L_BAUD"}{$newbaud} = $newbaud; } return keys(%{$self->{"_L_BAUD"}}); }

    Then '@allowed = $PortObj->are_baudrate(115200);' should add it to the "allowed" list. A real implementation should have a bit more validation and error handling. Let me know if it works.

    -bill

    ______________________

    I pasted it in directly from his e-mail, and it worked great!

    My code now reads:

    unless ($Port = new Win32::SerialPort($PortName) and $Port->are_baudrate(115200) and $Port->baudrate($Baudrate) and $Port->parity('none') and $Port->databits(8) and $Port->stopbits(2) and $Port->handshake('rts') and $Port->buffers(4096,4096) and $Port->binary(1) and $Port->xon_limit(3000) and $Port->xoff_limit(300) and $Port->rts_active(1) and $Port->write_settings) { $mw->messageBox( -message => "Can't open $PortName at $Baudrate baud.", -type => 'OK' ); exit }

    Many thanks to Bill and the Monks for their time and effort on this one!

    -Phil

Re: Windows serial I/O
by acid06 (Friar) on Oct 08, 2000 at 06:33 UTC
    Looks like a win9x problem.
    IMHO if you really need to use Windows, do yourself a favor: install win2k. It's way better than win9x.
      Agreed, even if it does eat /more/ memory ;)

      I also tried out your code and had no problems. I think it may be something personal... sorry :(