免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 12553 | 回复: 11
打印 上一主题 下一主题

php串口通信编程问题 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2011-04-19 17:21 |只看该作者 |倒序浏览
本帖最后由 erleng 于 2011-04-20 11:01 编辑

最近做个小项目,要远程控制一个水泵,编程只会一点儿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扩展。开发环境配置完毕。
测试了一下,没问题。
程序开始,惨了,家里机器上没有代码啊。

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

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

  23. "55 01 01 02 00 00 00 59"; //  吸合第1路继电器
  24. "55 01 01 00 02 00 00 59"; //  吸合第2路继电器
  25. "55 01 01 00 00 02 00 59"; // 吸合第3路继电器
  26. "55 01 01 00 00 00 02 59"; // 吸合第4路继电器

  27. "55 01 01 01 00 00 00 58"; // 断开第1路继电器
  28. "55 01 01 00 01 00 00 58"; // 断开第2路继电器
  29. "55 01 01 00 00 01 00 58"; // 断开第3路继电器
  30. "55 01 01 00 00 00 01 58"; // 断开第4路继电器

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

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

  42. $k1off="\x55\x01\x01\x01\x00\x00\x00\x58";
  43. $k2off="\x55\x01\x01\x00\x01\x00\x00\x58";
  44. $k3off="\x55\x01\x01\x00\x00\x01\x00\x58";
  45. $k4off="\x55\x01\x01\x00\x00\x00\x01\x58";

  46. $kon="\x55\x01\x01\x02\x02\x02\x02\x5f";
  47. $koff="\x55\x01\x01\x01\x01\x01\x01\x5b";
  48. $kstatus="\x55\x01\x00\x00\x00\x00\x00\x56";
  49. //定义接受的get 命令
  50. $ops = array("k1on", "k2on", "k3on", "k4on",
  51.                         "k1off","k2off","k3off","k4off","kon","koff","kstatus");
  52. //串口操作开始                       
  53. if ( isset($_GET['op']) and in_array($_GET['op'],$ops ) )
  54. {       
  55.         $data=${$_GET['op']};               
  56.         set_time_limit(3);
  57.         //echo 'windows下设置窜口参数<br>';
  58.         exec("mode ".$com."BAUD=9600 PARITY=n DATA=8 STOP=1 odsr=off");
  59.        
  60.         //echo "打开端口$com<br>";
  61.         $f =  dio_open ($com, O_RDWR | O_NOCTTY | O_NONBLOCK);
  62.         if(!$f)
  63.         {
  64.                 die("Error when open $com");
  65.         }
  66.         //echo "向串口发送数据<br>".$data.'<br>';
  67.         dio_write ($f, $data);
  68.         //echo "接收数据<br>";
  69.         $str="";
  70.         for ($i = 0; $i <= 7; $i++)
  71.         {
  72.                 $str.=bin2hex(dio_read( $f,1));
  73.         }       
  74.         //echo $str;
  75.         $k1=$str[7];
  76.         $k2=$str[9];
  77.         $k3=$str[11];
  78.         $k4=$str[13];
  79.        
  80.         //echo "关闭端口<br>";       
  81.         dio_close($f);
  82.         //串口操作结束
  83.        
  84. //输出开始       

  85. //简单控制界面       
  86. $output='串口继电器控制演示程序 2011年4月<br><br>
  87.         <a href="'.$_SERVER[’PHP_SELF’].'?op=k1on">k1开</a>
  88.         <a href="'. $_SERVER[’PHP_SELF’].'?op=k1off">k1关</a>
  89.         <a href="'.$_SERVER[’PHP_SELF’].'?op=k2on">k2开</a>
  90.         <a href="'. $_SERVER[’PHP_SELF’].'?op=k2off">k2关</a>
  91.         <a href="'.$_SERVER[’PHP_SELF’].'?op=k3on">k3开</a>
  92.         <a href="'. $_SERVER[’PHP_SELF’] .'?op=k3off">k3关</a>
  93.         <a href="'.$_SERVER[’PHP_SELF’].'?op=k4on">k4开</a>
  94.         <a href="'. $_SERVER[’PHP_SELF’] .'?op=k4off">k4关</a>       
  95.         <a href="'. $_SERVER[’PHP_SELF’] .'?op=kon">全开</a>
  96.         <a href="'. $_SERVER[’PHP_SELF’] .'?op=koff">全关</a>       
  97.         <a href="'. $_SERVER[’PHP_SELF’] .'?op=kstatus">查询</a>
  98.         <a href="'. $_SERVER[’PHP_SELF’] .'?op=kstatus&out=xml">XML格式查询</a>
  99.         <br><br>
  100.         开关状态 1关 2开<br><br>
  101.         <br>k1:'.$k1.'<br>
  102.         <br>k2:'.$k2.'<br>
  103.         <br>k2:'.$k3.'<br>
  104.         <br>k2:'.$k4.'<br>';               
  105.        
  106. echo $output;               
  107. }
  108. ?>
复制代码
我的问题在哪里呢?
必须要用串口控制程序初始化一下窜口,我的php程序才能正常工作。不明白,google了N次,也google不出来。
自己分析是用win自己的mode命令设置的参数还不完整,可是要怎么设置呢?自己cmd下用mode测试,结果居然蓝屏死机了。
哪位大侠能给个解决方法?

论坛徽章:
0
2 [报告]
发表于 2011-04-19 19:15 |只看该作者
不错,支持一下

论坛徽章:
0
3 [报告]
发表于 2011-04-19 21:29 |只看该作者
本帖最后由 a.a 于 2011-04-19 22:25 编辑

回复 1# erleng


    建议楼主全程论坛更新,php 还可以实现这种功能,很想见证一下。

论坛徽章:
0
4 [报告]
发表于 2011-04-19 22:20 |只看该作者
对端口读写,只要有硬件支持就行 ,不难

论坛徽章:
0
5 [报告]
发表于 2011-04-19 22:24 |只看该作者
回复 4# ashchen


    不需底层的驱动吗?

论坛徽章:
0
6 [报告]
发表于 2011-04-20 09:47 |只看该作者
php还能做这类功能,关注

论坛徽章:
0
7 [报告]
发表于 2011-04-20 10:56 |只看该作者
本帖最后由 erleng 于 2011-04-20 11:13 编辑

再研究,google,发现不用php 的dio 也成。别人的代码如下
  1. <?php
  2. // HOW TO USE PHP TO WRITE TO YOUR SERIAL PORT: TWO METHODS
  3. $serproxy=true;
  4. if ($serproxy) {
  5.     // Use this code in conjunction with SERPROXY.EXE
  6.     // (http://www.lspace.nildram.co.uk/freeware.html)
  7.     // which converts a Serial stream to a TCP/IP stream
  8.     $fp = fsockopen ("localhost", 5331, $errno, $errstr, 30);
  9.     if (!$fp) {
  10.         echo "$errstr ($errno)";
  11.     } else {
  12.         $e = chr(27);
  13.         $string  = $e . "A" . $e . "H300";
  14.         $string .= $e . "V100" . $e . "XL1SATO";
  15.         $string .= $e . "Q1" . $e . "Z";
  16.         echo $string;
  17.         fputs ($fp, $string );
  18.         fclose ($fp);
  19.     }
  20. } elseif ($com1) {
  21.     // Use this code to write directly to the COM1 serial port
  22.     // First, you want to set the mode of the port. You need to set
  23.     // it only once; it will remain the same until you reboot.
  24.     // Note: the backticks on the following line will execute the
  25.     // DOS 'mode' command from within PHP
  26.     `mode com1: BAUD=9600 PARITY=N data=8 stop=1 xon=off`;
  27.     $fp = fopen ("COM1:", "w+");
  28.     if (!$fp) {
  29.         echo "Uh-oh. Port not opened.";
  30.     } else {
  31.         $e = chr(27);
  32.         $string  = $e . "A" . $e . "H300";
  33.         $string .= $e . "V100" . $e . "XL1SATO";
  34.         $string .= $e . "Q1" . $e . "Z";
  35.         echo $string;
  36.         fputs ($fp, $string );
  37.         fclose ($fp);
  38.     }
  39. }
  40. ?>
复制代码
这样也成?不用dio的话,配置服务器就方便多了。改吧!
  1. <?php
  2. /**************************************************************
  3. *rs232new.php            控制4路串口继电器程序                          *
  4. *  作者 tiger92665@gmail.com        2011.04                  *
  5. **************************************************************/

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

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

  28. "55 01 01 01 00 00 00 58"; // 断开第1路继电器
  29. "55 01 01 00 01 00 00 58"; // 断开第2路继电器
  30. "55 01 01 00 00 01 00 58"; // 断开第3路继电器
  31. "55 01 01 00 00 00 01 58"; // 断开第4路继电器

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

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

  42. $k1off="\x55\x01\x01\x01\x00\x00\x00\x58";
  43. $k2off="\x55\x01\x01\x00\x01\x00\x00\x58";
  44. $k3off="\x55\x01\x01\x00\x00\x01\x00\x58";
  45. $k4off="\x55\x01\x01\x00\x00\x00\x01\x58";

  46. $kon="\x55\x01\x01\x02\x02\x02\x02\x5f";
  47. $koff="\x55\x01\x01\x01\x01\x01\x01\x5b";
  48. $kstatus="\x55\x01\x00\x00\x00\x00\x00\x56";
  49. //定义接受的get 命令
  50. $op = array("k1on", "k2on", "k3on", "k4on",
  51.                         "k1off","k2off","k3off","k4off","kon","koff","kstatus");
  52. //串口操作开始                       
  53. if ( isset($_GET['op']) and in_array($_GET['op'],$op ) )
  54. {       
  55.         $data=${$_GET['op']};               
  56.         set_time_limit(3);
  57.         //echo 'windows下设置窜口参数<br>';
  58.         exec("mode ".$com."BAUD=9600 PARITY=n DATA=8 STOP=1 odsr=off");
  59.        
  60.         //echo "打开端口$com<br>";
  61.         $f =  fopen ($com, 'w+');
  62.         if(!$f)
  63.         {
  64.                 die("Error when open $com");
  65.         }
  66.         //echo "向串口发送数据<br>".$data.'<br>';
  67.         fwrite ($f, $data);
  68.         //echo "接收数据<br>";
  69.         $str="";
  70.         for ($i = 0; $i <= 7; $i++)
  71.         {
  72.                 $str.=bin2hex(fread( $f,1));
  73.         }       
  74.         //echo $str;
  75.         $k1=$str[7];
  76.         $k2=$str[9];
  77.         $k3=$str[11];
  78.         $k4=$str[13];
  79.        
  80.         //echo "关闭端口<br>";       
  81.         fclose($f);
  82.         //串口操作结束
  83.        
  84.         //输出开始       
  85.         if ( isset($_GET['out']) and ($_GET['out']=="xml" ) )
  86.         {
  87.         //xml输出
  88.                 $output        =
  89.                 '<?xml version="1.0" ?>
  90.                 <k1>'.$k1.'</k1>
  91.                 <k2>'.$k2.'</k2>
  92.                 <k3>'.$k3.'</k3>
  93.                 <k4>'.$k4.'</k4>';
  94.         }
  95.         else
  96.         {
  97.         //简单控制界面       
  98.                 $output='串口继电器控制演示程序 2011年4月<br><br>
  99.                                 <a href="'.$_SERVER[’PHP_SELF’].'?op=k1on">k1开</a>
  100.                                 <a href="'. $_SERVER[’PHP_SELF’].'?op=k1off">k1关</a>
  101.                                 <a href="'.$_SERVER[’PHP_SELF’].'?op=k2on">k2开</a>
  102.                                 <a href="'. $_SERVER[’PHP_SELF’].'?op=k2off">k2关</a>
  103.                                 <a href="'.$_SERVER[’PHP_SELF’].'?op=k3on">k3开</a>
  104.                                 <a href="'. $_SERVER[’PHP_SELF’] .'?op=k3off">k3关</a>
  105.                                 <a href="'.$_SERVER[’PHP_SELF’].'?op=k4on">k4开</a>
  106.                                 <a href="'. $_SERVER[’PHP_SELF’] .'?op=k4off">k4关</a>       
  107.                                 <a href="'. $_SERVER[’PHP_SELF’] .'?op=kon">全开</a>
  108.                                 <a href="'. $_SERVER[’PHP_SELF’] .'?op=koff">全关</a>       
  109.                                 <a href="'. $_SERVER[’PHP_SELF’] .'?op=kstatus">查询</a>
  110.                                 <a href="'. $_SERVER[’PHP_SELF’] .'?op=kstatus&out=xml">XML格式查询</a>
  111.                                 <br><br>
  112.                                 开关状态 1关 2开<br><br>
  113.                                 <br>k1:'.$k1.'<br>
  114.                                 <br>k2:'.$k2.'<br>
  115.                                 <br>k2:'.$k3.'<br>
  116.                                 <br>k2:'.$k4.'<br>';               
  117.         }
  118.         echo $output;               
  119. }
  120. ?>
复制代码
测试也成功了,可以控制继电器动作!不过还是那个问题,要用串口程序初始化串口!

论坛徽章:
0
8 [报告]
发表于 2011-04-20 11:02 |只看该作者
本帖最后由 erleng 于 2011-04-20 11:38 编辑
回复  ashchen


    不需底层的驱动吗?
a.a 发表于 2011-04-19 22:24

php_dio.dll应该算是php到串口的驱动
看改过的程序,看来是不需要啦。

论坛徽章:
0
9 [报告]
发表于 2011-04-20 11:09 |只看该作者
你买的买的串口4路继电器板有DEMO程序给你吗?

如果有建议将DEMO改成PHP可调用交互的exe文件,通过exec 执行这类DELPHI或VB等写的程序和串口通信,相对PHP直接通讯要稳定的多。

我原先的一些PHP读写串口的应用都是通过购买的相应硬件厂方提供的DEMO改写的程序作通讯中介的。

论坛徽章:
0
10 [报告]
发表于 2011-04-20 11:17 |只看该作者
本帖最后由 erleng 于 2011-04-20 11:25 编辑
你买的买的串口4路继电器板有DEMO程序给你吗?

如果有建议将DEMO改成PHP可调用交互的exe文件,通过exec  ...
abaowu 发表于 2011-04-20 11:09

有的,是vb做的,是调用 一个mscomm32.ocx控件实现的,不过好像与win7不兼容,它的程序跑不起来。
程序最终要到linux下运行,所以就不能用你的方法啦。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP