Chinaunix

标题: Perl 如何实现串行通信啊? [打印本页]

作者: Chennysky    时间: 2006-01-06 15:46
标题: Perl 如何实现串行通信啊?
有人说直接 将 com1 当成文件就可以了
有人建议用 Win32::SerialPort ( 基于 Win32API::CommPort )

各位有什么好建议?有没有相关的源代码供参考一下?谢谢

open(FH,">>COM1") or die "$!\nCant't create";
print FH `dir`;

虽然没有报错,可是我从哪儿查看结果呢?
怎么可以用串口实现 超级终端 的功能,将多个命令顺序执行呢?

谢谢各位
作者: Chennysky    时间: 2006-01-09 09:45
我下载了 Win32::SerialPort ,可是在调用该模块时就出错呢
下载的模块有错,该咱办呢?

D:\PerlDev\Exercise>perl exSerialPort.pl
Can't locate loadable object for module Win32::API in @INC (@INC contains: c:/Pe
rl/lib c:/Perl/site/lib .) at c:/Perl/site/lib/Win32API/CommPort.pm line 5
Compilation failed in require at c:/Perl/site/lib/Win32API/CommPort.pm line 5.
BEGIN failed--compilation aborted at c:/Perl/site/lib/Win32API/CommPort.pm line
5.
Compilation failed in require at c:/Perl/site/lib/SerialPort.pm line 4.
BEGIN failed--compilation aborted at c:/Perl/site/lib/SerialPort.pm line 4.
Compilation failed in require at exSerialPort.pl line 6.
BEGIN failed--compilation aborted at exSerialPort.pl line 6.
作者: Chennysky    时间: 2006-01-09 10:55
#c:/Perl/site/lib/Win32API/CommPort.pm
package Win32API::CommPort;

use Win32;
use Win32::API 0.01;

我的API.pm 究竟应放在哪儿呢?怎么总找不到Win32::API ?
作者: Chennysky    时间: 2006-01-09 15:23
ppm>install Win32-API

就可以了,直接复制到相应目录不一定成功的哟

笨了
作者: Chennysky    时间: 2006-01-11 16:46
呵呵,经过几天的调试,可以通信了,可是需要延时
我的数据不能及时传给 串口,只能逐个字符传输,然后延时
否则就会丢失数据,得不到需要的结果了

读数据时也是这样
如何才可以将所有数据无丢失的读出呢?
继续努力中!
加油哦
作者: peakgod    时间: 2006-01-13 11:08
标题: 回复 5楼 Chennysky 的帖子
看你一个人,兄弟我来陪一程!
虽然解答不了你的问题,但是可以在你的问题中学习!
作者: Chennysky    时间: 2006-01-13 13:30
标题: 谢谢!
#!C:\Perl\bin  
# driverreg.pl
# This is a Perl program for Driver Regression Test with Serial Port.
#        Run on Windows OS.

#Define title of the software.
format SYSNAME=
        ========================================
        Driver Regression Test System [Ver 1.0]
        ========================================
.

use File::Copy;
use Win32::SerialPort;
use Time::HiRes qw /usleep/;        #Sleep for some time less than 1 second.
#use strict;

# Define some values
my $drvCaseFile = "D:/PerlDev/DrvTest/drvcase.txt";
my $drvTestReport = "D:/PerlDev/DrvTest/DrvTestReport.txt";
my $portCom1;
my $Configuration_File_Name = "D:/PerlDev/DrvTest/Com1Port.cfg";

# Start test.
$| = 1;        # Update before write or read.
$~=SYSNAME;                #Display the title.
write;

if (-e $drvTestReport)        #Delete the report file if exist.
{
    print "Exist file $drvTestReport.";
    system ("rm -f $drvTestReport");
}

# SerialPort Constructor
unless ($portCom1 = Win32::SerialPort->new ('com1')) {
    printf "Could not open port COM1: $^E\n";
    exit 1;
}


# Set parameters
$portCom1->user_msg(ON);
$portCom1->baudrate(115200)    || die "bad baudrate";
$portCom1->databits(8)         || die "bad databits";
$portCom1->parity('none')      || die "bad parity";
$portCom1->stopbits(1)         || die "bad stopbits";

# After new, must check for failure
$portCom1->write_settings || undef $portCom1;
print "Can't change Device_Control_Block: $^E\n" unless ($portCom1);
print "write_settings done\n";

# Before using start, restart, or tie
$portCom1->save($Configuration_File_Name)
        || warn "Can't save $Configuration_File_Name: $^E\n";

my ($BlockingFlags, $InBytes, $OutBytes, $LatchErrorFlags) = $portCom1->status
        || warn "could not get port status\n";
print "The value of \$BlockingFlags is $BlockingFlags\n";
$portCom1->lookclear;

undef $portCom1;

$portCom1 = tie (*FH, 'Win32::SerialPort', $Configuration_File_Name)
       || die "Can't tie: $^E\n";            ## TIEHANDLE ##

open (CASEFILE, "<$drvCaseFile")||die "$!\nCannot open case file $drvCaseFile\n";
my @comLineArr = <CASEFILE>;
close (CASEFILE);
print "@comLineArr\n";

open (REPORTFILE, ">>$drvTestReport")
        ||die "$!\nCannot write to report file $drvCaseFile\n";
print (REPORTFILE "    This Is The Driver Test Report\n");
foreach my $comLineOrg (@comLineArr)
{
    my $startTime = time;
    chomp ($comLineOrg);
    print "The command line is: $comLineOrg!\n\n";
    print (REPORTFILE "\n\n========== Test case:$comLineOrg ==========\n");
    @comLine = split (//, $comLineOrg);    #Get the character one by one
#    sleep 1;
#    print "Run to here1\n";
   
INPUTCMD:
    sleep 1;
    print "The command by character is: @comLine!\n\n";
    foreach my $comChar (@comLine)
    {
        syswrite (FH, $comChar);        ## WRITE     ##
        usleep (10000);
    }
    $enterChar = "\r";
    syswrite (FH, $enterChar, length($enterChar), 0);             ## WRITE     ##
   
    my @com1OutArr;
    for (my $i = 0;;$i++)
    {   
        $lineFromCom1 = <FH>;
        if ($lineFromCom1 ne "")
        {
            print "The line from COM1 $i: $lineFromCom1";
            open (REPORTFILE, ">>$drvTestReport") ||die "$!\nCannot write to report file $drvCaseFile\n";
            print (REPORTFILE "$lineFromCom1");
            chomp ($lineFromCom1);
            chop ($lineFromCom1);
            goto INPUTCMD if($lineFromCom1 =~ "Invalid command");
            @com1OutArr = split (/>/, $lineFromCom1);
        }

        my $curTime = time;
        my $testPeriod = $curTime - $startTime;
        
        last if (($lineFromCom1 eq $comLineOrg)
                 ||($lineFromCom1 =~ "ss")
#                 ||($com1OutArr[$#com1OutArr] eq $comLineOrg)
                 ||($com1OutArr[$#com1OutArr] =~ "End of mp3.")
                 ||(300 <= $testPeriod));
    }
}
close (REPORTFILE);
close FH || warn "Close failed\n";           ## CLOSE     ##
undef $portCom1;
untie *FH;                                 ## DESTROY   ##

先有这么多了,就是不能总保证传输的正确性
自己觉得延时的确定和恰当比较关键
否则,不停的读写com1,就会传输出错。

呵呵,不过各位不用串口的,可以不看咯
继续学习!^_^

[ 本帖最后由 Chennysky 于 2006-1-13 14:21 编辑 ]
作者: 兰花仙子    时间: 2006-01-13 20:07
ft呀,这年头连脚本语言也可以读写串口呢
作者: Chennysky    时间: 2006-01-16 10:58
标题: 就是就是
不怕做不到,就怕想不到啊!呵呵

对了,目前我还只能传送字符串数据
如何传送 文件呢? 我现在急需要传送文件,各位有什么好建议?
感激!!
作者: Chennysky    时间: 2006-01-16 11:35
其实如果有一个 传送 文件的 命令行程序,我将其嵌入到我的perl程序中也可以的
作者: rimrock    时间: 2006-01-16 20:23
原来perl还有这个功能呀。
我可是用delphi编的串口部分的程序,然后再用perl来调用,从来没有出过错。

希望你可以考虑考虑
作者: Chennysky    时间: 2006-01-17 15:12
我现在也这么想了,希望编写一个c的传送文件的程序让perl调用
perl 传送 一些消息还是很方便的

你的delphi程序可以发送文件了么?
可否供参考一下?谢谢
作者: Chennysky    时间: 2006-01-19 15:59
我还是希望将 文件 逐字节读出再往串口写
可是写到一部分时就再写不进去了
同样的方法往 文件中写是可以得,还不知道是什么原因
作者: rimrock    时间: 2006-01-20 11:18
perl来组织要发送的文件,然后调用c的exe文件来发送
作者: Chennysky    时间: 2006-01-20 15:33
终于把 C 的发送串口文件的程序完成了!
这样就可以把这个程序嵌入到 我的 Perl 中去了
system ("com1sendfile.exe filename");

呵呵
成功!
谢谢楼上的支持!!
作者: rimrock    时间: 2006-01-20 20:47
祝贺
作者: sunbeat    时间: 2006-01-20 21:33
刚用perl写了一个短信服务器程序,也是用Win32::SerialPort的模块,另外加上了Gsm模块
作者: rimrock    时间: 2006-01-20 22:06
移动的短信40元/800条加上五指派50元/1000条,有没有更优惠的了?

你使用SIEMENS还是其他公司的无限模块?
作者: sunbeat    时间: 2006-01-20 23:39
我用的自己的手机(西门子6618)、还有NOKIA6100,NOKIA6670、三星的几个啥牌子的记不清了,都是可以支持的。我想西门子或者其它公司的短信猫应该也能支持。
因为GSM的标准指令集,大家都是一样的
作者: Chennysky    时间: 2006-01-21 11:03
这个好,可以免费发消息咯?!
作者: Chennysky    时间: 2006-03-02 10:46
这里也提过串口发送文件的问题!

可是我还是希望使用perl 发送或接收文件呢。用C接收文件的程序没有写好,并且我担心 我关闭Perl的串口,再打开C的串口,中间就有数据丢失了
作者: xiash_poll    时间: 2006-03-07 12:10
标题: 回复 17楼 sunbeat 的帖子
大虾,不知道能否贡献写得短信发送程序?
作者: Basin    时间: 2006-03-07 16:22
提示: 作者被禁止或删除 内容自动屏蔽
作者: Chennysky    时间: 2006-03-10 17:48
进展:
我在读取 com 传递给PC的数据流(二进制,逐字节传输)时,发现问题:
0A变成0D0A
AF变成0DAF

只好经过判断将其中的0D去掉,这样可以接收到一些10K以下的文件,测试2个文件成功
可是一旦原二进制文件中就有 0D0A ,0DAF 在一起连着的呢?我就无法处理了!

问题:com 怎么会将 0A变成0D0A(实际是换行),AF变成0DAF的呢?我该如何传送或接收才会避免这种问题?

Thanks!
作者: rimrock    时间: 2006-03-10 20:36
串口发送多大的文件一般都不会出错。
但是在数据线过长,波特率过高,有时会出错。像你的情况肯定是程序的问题
作者: Chennysky    时间: 2006-03-13 16:16
基本问题:

从串口传回PC的数据放在哪儿了呢?这个缓冲区的大小有限制么?如果1分钟内不取出,数据会一直保存在那个缓冲区的么?
作者: Chennysky    时间: 2006-03-15 17:24
不好意思,一直跟这个贴是因为问题还没有很好的解决:

0A变成0D0A
AF变成0DAF

估计是因为 读串口时,直接将串口当成了文本文件,如果将它转化为二进制文件该不会有问题吧
可是 binmode (FH);   #FH 是串口句柄

会出错Can't locate object method "BINMODE" via package "Win32::SerialPort"。

这该怎么办呢?
作者: Chennysky    时间: 2006-03-21 10:31
标题: 新发现!
发现:使用SerialPort,串口本身就是以二进制打开的
#  binmode (FH); #这样会出错
就当然会出错了

Ports are opened for binary transfers. A separate binmode is not needed.
(From CPAN)

可是 0A变成0D0A
还是会发生,我用PC上的一个同样的二进制文件进行逐字节读出写入,没有发现这样的问题,串口怎么就出错了呢?

继续努力中!这个串口搞了我好久哦
作者: rimrock    时间: 2006-03-21 21:39
为什么一定要用perl来做串口呢?
作者: Chennysky    时间: 2006-03-22 09:44
呵呵,我是用于测试用的

当然 这个串口接收数据的程序用C写也是可以的
估计我得这么做了

Thanks
作者: Chennysky    时间: 2006-03-27 10:46
标题: 呵呵,结贴!
经过反复调试、测试与跟踪,后来发现是经com发送数据到PC的那个函数有问题
它在处理时就将 “0A”变成了 “0D0A”,(可能用于其他用途吧)
后来只好重新写了一个新的函数发送数据到PC,现在OK!

打扰大家这么久,不好意思!




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2