27
2012
08

参考资料 php串口通信编程问题





原帖地址 : http://bbs.chinaunix.net/thread-2306104-1-1.html

 

最近做个小项目,要远程控制一个水泵,编程只会一点儿php,正好方便远程控制。
开发环境 win7 ,一个usb转串口的转换器,淘宝上买的串口4路继电器板。
想最终整个atom的小板子加个u盘做系统,定制一个小linux+apache+php系统来做,硬件体积小,功耗低,应该可靠性比较高。
google了一下,看到大多都是用的php dio模块,我也用吧。
原来开发开发环境用的是 wamp server 2.1, 发现没有pecl dio模块,又google,发现 pecl4win.php.net当机了,郁闷。
又找,在http://snaps.php.net/win32/找到了php5.2-win32-200808060430.zip和pecl5.2-win32-200808060430.zip这个是配套的。
要下班了,回家继续写!
继续,继续google,找到了个coreAMP,试试看,下载安装,包含2个php版本,5.2.17,和5.3.5,都没有扩展库,下载的php版本是 5.2.7,php版本不一样,
覆盖看看行不行,解压php5.2-win32-200808060430.zip覆盖coreamp的php5.2.17目录,解压
pecl5.2-win32-200808060430.zip到php5.2.17的ext目录,修改php.ini,改extension_dir = "C:\CoreAMP\server\php-5.2.17\ext"添加php_dio.dll扩展。开发环境配置完毕。
测试了一下,没问题。
程序开始,惨了,家里机器上没有代码啊。

回单位了,上代码:

 

<?php
/**************************************************************
*rs232.php            控制4路串口继电器演示程序           *
*  作者 tiger92665@gmail.com        2011.04   *
**************************************************************
  采用232协议通信,波特率9600,8个数据位,一个停止位,无校验位。
MODE COM1 9600, n, 8, 1
计算机到继电器板的数据帧说明:
数据头: 0x55  (作为标识)
地址:0x01(一个继电器板默认为1)
操作类型: 0x00(查询当前各继电器状态)0x01(写入新值)
数据(四个字节) 每个字节代表一个继电器,共四个;
数据值1:继电器断开;数据值2:继电器吸合;数据值0:继电器无动作。
校验           一字节和校验 0x56

继电器板到计算机的数据帧说明:
数据头: 0x22  (作为标识)
地址:0x01(单个继电器默认为1)
操作类型: 与计算机发来的操作类型一致
数据(四个字节)      每个字节代表一个继电器,共四个;
数据值1:继电器断开,数据值2:继电器吸合。
校验           一字节和校验(用来防止数据出错)
计算机发送指令表(部分):

"55 01 01 02 00 00 00 59"; //  吸合第1路继电器
"55 01 01 00 02 00 00 59"; //  吸合第2路继电器
"55 01 01 00 00 02 00 59"; // 吸合第3路继电器
"55 01 01 00 00 00 02 59"; // 吸合第4路继电器

"55 01 01 01 00 00 00 58"; // 断开第1路继电器
"55 01 01 00 01 00 00 58"; // 断开第2路继电器
"55 01 01 00 00 01 00 58"; // 断开第3路继电器
"55 01 01 00 00 00 01 58"; // 断开第4路继电器

55 01 01 02 02 02 02 5F  吸合所有继电器
55 01 01 01 01 01 01 5B  断开所有继电器

"55 01 01 00 00 00 00 57";  查询当前继电器板的状态 */
//定义被操作的窜口
$com="com4";
//定义串口数据
//                                      k1  k2   k3   k4  校验位
$k1on="\x55\x01\x01\x02\x00\x00\x00\x59";
$k2on="\x55\x01\x01\x00\x02\x00\x00\x59";
$k3on="\x55\x01\x01\x00\x00\x02\x00\x59";
$k4on="\x55\x01\x01\x00\x00\x00\x02\x59";

$k1off="\x55\x01\x01\x01\x00\x00\x00\x58";
$k2off="\x55\x01\x01\x00\x01\x00\x00\x58";
$k3off="\x55\x01\x01\x00\x00\x01\x00\x58";
$k4off="\x55\x01\x01\x00\x00\x00\x01\x58";

$kon="\x55\x01\x01\x02\x02\x02\x02\x5f";
$koff="\x55\x01\x01\x01\x01\x01\x01\x5b";
$kstatus="\x55\x01\x00\x00\x00\x00\x00\x56";
//定义接受的get 命令
$ops = array("k1on", "k2on", "k3on", "k4on",
                        "k1off","k2off","k3off","k4off","kon","koff","kstatus");
//串口操作开始                       
if ( isset($_GET['op']) and in_array($_GET['op'],$ops ) )
{       
        $data=${$_GET['op']};               
        set_time_limit(3);
        //echo 'windows下设置窜口参数<br>';
        exec("mode ".$com."BAUD=9600 PARITY=n DATA=8 STOP=1 odsr=off");
       
        //echo "打开端口$com<br>";
        $f =  dio_open ($com, O_RDWR | O_NOCTTY | O_NONBLOCK);
        if(!$f)
        {
                die("Error when open $com");
        }
        //echo "向串口发送数据<br>".$data.'<br>';
        dio_write ($f, $data);
        //echo "接收数据<br>";
        $str="";
        for ($i = 0; $i <= 7; $i++)
        {
                $str.=bin2hex(dio_read( $f,1));
        }       
        //echo $str;
        $k1=$str[7];
        $k2=$str[9];
        $k3=$str[11];
        $k4=$str[13];
       
        //echo "关闭端口<br>";       
        dio_close($f);
        //串口操作结束
       
//输出开始       

//简单控制界面       
$output='串口继电器控制演示程序 2011年4月<br><br>
        <a href="'.$_SERVER[’PHP_SELF’].'?op=k1on">k1开</a>
        <a href="'. $_SERVER[’PHP_SELF’].'?op=k1off">k1关</a>
        <a href="'.$_SERVER[’PHP_SELF’].'?op=k2on">k2开</a>
        <a href="'. $_SERVER[’PHP_SELF’].'?op=k2off">k2关</a>
        <a href="'.$_SERVER[’PHP_SELF’].'?op=k3on">k3开</a>
        <a href="'. $_SERVER[’PHP_SELF’] .'?op=k3off">k3关</a>
        <a href="'.$_SERVER[’PHP_SELF’].'?op=k4on">k4开</a>
        <a href="'. $_SERVER[’PHP_SELF’] .'?op=k4off">k4关</a>       
        <a href="'. $_SERVER[’PHP_SELF’] .'?op=kon">全开</a>
        <a href="'. $_SERVER[’PHP_SELF’] .'?op=koff">全关</a>       
        <a href="'. $_SERVER[’PHP_SELF’] .'?op=kstatus">查询</a>
        <a href="'. $_SERVER[’PHP_SELF’] .'?op=kstatus&out=xml">XML格式查询</a>
        <br><br>
        开关状态 1关 2开<br><br>
        <br>k1:'.$k1.'<br>
        <br>k2:'.$k2.'<br>
        <br>k2:'.$k3.'<br>
        <br>k2:'.$k4.'<br>';               
       
echo $output;               
}
?>

 

我的问题在哪里呢?
必须要用串口控制程序初始化一下窜口,我的php程序才能正常工作。不明白,google了N次,也google不出来。
自己分析是用win自己的mode命令设置的参数还不完整,可是要怎么设置呢?自己cmd下用mode测试,结果居然蓝屏死机了。
哪位大侠能给个解决方法?

再研究,google,发现不用php 的dio 也成。别人的代码如下

 

<?php
// HOW TO USE PHP TO WRITE TO YOUR SERIAL PORT: TWO METHODS
$serproxy=true;
if ($serproxy) {
    // Use this code in conjunction with SERPROXY.EXE
    // (http://www.lspace.nildram.co.uk/freeware.html)
    // which converts a Serial stream to a TCP/IP stream
    $fp = fsockopen ("localhost", 5331, $errno, $errstr, 30);
    if (!$fp) {
        echo "$errstr ($errno)";
    } else {
        $e = chr(27);
        $string  = $e . "A" . $e . "H300";
        $string .= $e . "V100" . $e . "XL1SATO";
        $string .= $e . "Q1" . $e . "Z";
        echo $string;
        fputs ($fp, $string );
        fclose ($fp);
    }
} elseif ($com1) {
    // Use this code to write directly to the COM1 serial port
    // First, you want to set the mode of the port. You need to set
    // it only once; it will remain the same until you reboot.
    // Note: the backticks on the following line will execute the
    // DOS 'mode' command from within PHP
    `mode com1: BAUD=9600 PARITY=N data=8 stop=1 xon=off`;
    $fp = fopen ("COM1:", "w+");
    if (!$fp) {
        echo "Uh-oh. Port not opened.";
    } else {
        $e = chr(27);
        $string  = $e . "A" . $e . "H300";
        $string .= $e . "V100" . $e . "XL1SATO";
        $string .= $e . "Q1" . $e . "Z";
        echo $string;
        fputs ($fp, $string );
        fclose ($fp);
    }
}
?>

这样也成?不用dio的话,配置服务器就方便多了。改吧!

<?php
/**************************************************************
*rs232new.php            控制4路串口继电器程序                          *
*  作者 tiger92665@gmail.com        2011.04                  *
**************************************************************/

/*  采用232协议通信,波特率9600,8个数据位,一个停止位,无校验位。
MODE COM1 9600, n, 8, 1
计算机到继电器板的数据帧说明:
数据头: 0x55  (作为标识)
地址:0x01(一个继电器板默认为1)
操作类型: 0x00(查询当前各继电器状态)0x01(写入新值)
数据(四个字节) 每个字节代表一个继电器,共四个;
数据值1:继电器断开;数据值2:继电器吸合;数据值0:继电器无动作。
校验           一字节和校验 0x56

继电器板到计算机的数据帧说明:
数据头: 0x22  (作为标识)
地址:0x01(单个继电器默认为1)
操作类型: 与计算机发来的操作类型一致
数据(四个字节)      每个字节代表一个继电器,共四个;
数据值1:继电器断开,数据值2:继电器吸合。
校验           一字节和校验(用来防止数据出错)
计算机发送指令表(部分):
//                                 k1 k2 k3 k4        校验位
"55 01 01 02 00 00 00 59"; //  吸合第1路继电器
"55 01 01 00 02 00 00 59"; //  吸合第2路继电器
"55 01 01 00 00 02 00 59"; // 吸合第3路继电器
"55 01 01 00 00 00 02 59"; // 吸合第4路继电器

"55 01 01 01 00 00 00 58"; // 断开第1路继电器
"55 01 01 00 01 00 00 58"; // 断开第2路继电器
"55 01 01 00 00 01 00 58"; // 断开第3路继电器
"55 01 01 00 00 00 01 58"; // 断开第4路继电器

55 01 01 02 02 02 02 5F  吸合所有继电器
55 01 01 01 01 01 01 5B  断开所有继电器

"55 01 01 00 00 00 00 57";  查询当前继电器板的状态 */
//定义被操作的窜口
$com="com4";
//定义串口数据
$k1on="\x55\x01\x01\x02\x00\x00\x00\x59";
$k2on="\x55\x01\x01\x00\x02\x00\x00\x59";
$k3on="\x55\x01\x01\x00\x00\x02\x00\x59";
$k4on="\x55\x01\x01\x00\x00\x00\x02\x59";

$k1off="\x55\x01\x01\x01\x00\x00\x00\x58";
$k2off="\x55\x01\x01\x00\x01\x00\x00\x58";
$k3off="\x55\x01\x01\x00\x00\x01\x00\x58";
$k4off="\x55\x01\x01\x00\x00\x00\x01\x58";

$kon="\x55\x01\x01\x02\x02\x02\x02\x5f";
$koff="\x55\x01\x01\x01\x01\x01\x01\x5b";
$kstatus="\x55\x01\x00\x00\x00\x00\x00\x56";
//定义接受的get 命令
$op = array("k1on", "k2on", "k3on", "k4on",
                        "k1off","k2off","k3off","k4off","kon","koff","kstatus");
//串口操作开始                       
if ( isset($_GET['op']) and in_array($_GET['op'],$op ) )
{       
        $data=${$_GET['op']};               
        set_time_limit(3);
        //echo 'windows下设置窜口参数<br>';
        exec("mode ".$com."BAUD=9600 PARITY=n DATA=8 STOP=1 odsr=off");
       
        //echo "打开端口$com<br>";
        $f =  fopen ($com, 'w+');
        if(!$f)
        {
                die("Error when open $com");
        }
        //echo "向串口发送数据<br>".$data.'<br>';
        fwrite ($f, $data);
        //echo "接收数据<br>";
        $str="";
        for ($i = 0; $i <= 7; $i++)
        {
                $str.=bin2hex(fread( $f,1));
        }       
        //echo $str;
        $k1=$str[7];
        $k2=$str[9];
        $k3=$str[11];
        $k4=$str[13];
       
        //echo "关闭端口<br>";       
        fclose($f);
        //串口操作结束
       
        //输出开始       
        if ( isset($_GET['out']) and ($_GET['out']=="xml" ) )
        {
        //xml输出
                $output        =
                '<?xml version="1.0" ?>
                <k1>'.$k1.'</k1>
                <k2>'.$k2.'</k2>
                <k3>'.$k3.'</k3>
                <k4>'.$k4.'</k4>';
        }
        else
        {
        //简单控制界面       
                $output='串口继电器控制演示程序 2011年4月<br><br>
                                <a href="'.$_SERVER[’PHP_SELF’].'?op=k1on">k1开</a>
                                <a href="'. $_SERVER[’PHP_SELF’].'?op=k1off">k1关</a>
                                <a href="'.$_SERVER[’PHP_SELF’].'?op=k2on">k2开</a>
                                <a href="'. $_SERVER[’PHP_SELF’].'?op=k2off">k2关</a>
                                <a href="'.$_SERVER[’PHP_SELF’].'?op=k3on">k3开</a>
                                <a href="'. $_SERVER[’PHP_SELF’] .'?op=k3off">k3关</a>
                                <a href="'.$_SERVER[’PHP_SELF’].'?op=k4on">k4开</a>
                                <a href="'. $_SERVER[’PHP_SELF’] .'?op=k4off">k4关</a>       
                                <a href="'. $_SERVER[’PHP_SELF’] .'?op=kon">全开</a>
                                <a href="'. $_SERVER[’PHP_SELF’] .'?op=koff">全关</a>       
                                <a href="'. $_SERVER[’PHP_SELF’] .'?op=kstatus">查询</a>
                                <a href="'. $_SERVER[’PHP_SELF’] .'?op=kstatus&out=xml">XML格式查询</a>
                                <br><br>
                                开关状态 1关 2开<br><br>
                                <br>k1:'.$k1.'<br>
                                <br>k2:'.$k2.'<br>
                                <br>k2:'.$k3.'<br>
                                <br>k2:'.$k4.'<br>';               
        }
        echo $output;               
}
?>

 

测试也成功了,可以控制继电器动作!不过还是那个问题,要用串口程序初始化串口!

« 上一篇 下一篇 »

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。