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
In reply to Re: Windows serial I/O
by Anonymous Monk
in thread Windows serial I/O
by Anonymous Monk
| For: | Use: | ||
| & | & | ||
| < | < | ||
| > | > | ||
| [ | [ | ||
| ] | ] |