PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Perl: Zugriff auf Com-Port verweigert



Molaf
18-08-2009, 09:05
Hallo allerseits.

Ich möchte mit einem Perl-Skript regelmäßig den Com-Port auslesen, zwecks Kommunikation mit einem externen Gerät.

Eine propitäre Anwendung vom Hersteller des Gerätes aus der Gegenseite verbindet sich problemlos mit COM1 und kann Kommandos senden und Daten empfangen.

Ich habe erstmal auf CPAN nachgesehen, und es gibt tatsächlich ein passendes Modul: Win32::SerialPort.
Das Windows ist ein Win2000.

Mein Code ist folgender:

use strict;
use bytes;

use Win32::SerialPort qw( :STAT 0.19 );

my $PortName = 'COM1';

my $cfgfile = 'C:/Serial-Conf-file.cfg';

my $quiet=1;
my $PortObj = new Win32::SerialPort ($PortName, $quiet)
|| die "Can't open $PortName: $^E\n"; # $quiet is optional

$PortObj->user_msg('ON');
$PortObj->databits(8);
$PortObj->baudrate(9600);
$PortObj->parity("none");
$PortObj->stopbits(1);
$PortObj->handshake("rts");
$PortObj->buffers(4096, 4096);
$PortObj->write_settings || undef $PortObj;

# or switch to a different configuration on the same port
$PortObj->restart($cfgfile)
|| warn "Can't reread '$cfgfile': $^E\n";

my $tie_ob = tie(*COM,'Win32::SerialPort', $cfgfile)
or die "Can't start '$cfgfile'\n";

while (1)
{
my ($BlockingFlags, $InBytes, $OutBytes, $LatchErrorFlags) = $PortObj->status
|| warn "could not get port status\n";
if ($BlockingFlags) { print "warn:Port $PortName is blocked\n"; }
else {my $in = getc COM; print $in."\n";}

print COM "\x84\x0D";
sleep 1;
}
(entspricht weitestgehend den Spezifikationen aus der POD zum Modul, ich habe lediglich use bytes und use strict eingefügt.

Die Anwendung des Herstellers verbindet sich (erfolgreich) mit 57600 Baut, in der Systemsteuerung sind aber nur 9600 voreingestellt. Nach dem ersten Fehlschlag habe ich sicherheitshalber auch 57600 bei meinem Skript eingetragen.

Die Fehlermeldung lautet beim Start: Zugriff verweigert auf COM1
die betroffene Zeile ist die mit dem tie, also der eigentliche Verbindungsstart lauf Modul-Beschreibung.

Ich habe übrigens auch die Adminstratorrechte auf dem Rechner, es greift kein anderes Programm auf den Port zu.

Was kann es wohl sein, was mir den Zugriff verweigert?

mfg Molaf

reneeb
19-08-2009, 11:09
Das "tie"-Interface ist eine *Alternative* zu dem oberen Code (wenn ich es richtig verstanden habe). Lass das "tie" mal weg.

Du kannst Dir ja auch die Beispiele aus dem eg/-Ordner ansehen (siehe http://search.cpan.org/~bbirth/Win32-SerialPort-0.19/MANIFEST )

Molaf
19-08-2009, 11:19
Stimmt genau, inzwischen funktioniert es auch mit dem Kommunizieren.

Der Vollständigkeit halber poste ich den laufenden Code mal, vielleicht hilft das ja mal jemandem.

use strict;
use bytes;

use Win32::SerialPort qw( :STAT 0.19 );

my $PortName = 'COM1';

my $cfgfile = 'C:/Serial-Conf-file.cfg';

my $quiet=1;
my $PortObj = new Win32::SerialPort ($PortName, $quiet)
|| die "Can't open $PortName: $^E\n"; # $quiet is optional

$PortObj->user_msg('ON');
$PortObj->databits(8);
$PortObj->baudrate(57600); # 56000
$PortObj->parity("none"); # none mark space even odd
$PortObj->stopbits(1);
$PortObj->handshake("none"); # none rts dtr xoff
$PortObj->buffers(4096, 4096);
$PortObj->write_settings || undef $PortObj;

while (1)
{
my $in = $PortObj->input;
print $in."\n";
# ....

$PortObj->write("\x84\x0D");
sleep 1;
}

Komisch, gestern habe ich verbissen an allen Einstellungen herumprobiert und trotzdem nichts mehr zustande gekriegt. Heute ist mir relativ schnell der Fehler bewußt geworden, Auskommentieren einzelner Zeilen hat dann schnell den Grund zutage gefördert.

Das Modul ist aber wirklich dämlich dokumentiert, wenn ich das noch schreiben darf. :)

Gruß,
Molaf