欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  php教程

php串口通信编程问题

程序员文章站 2022-06-01 09:01:34
...

最近做个小项目,要远程控制一个水泵, 编程 只会一点儿php,正好方便远程控制。 开发环境 win7 ,一个usb转 串口 的转换器,淘宝上买的 串口 4路继电器板。 想最终整个atom的小板子加个u盘做系统,定制一个小linuxapachephp系统来做,硬件体积小,功耗低,应

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

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

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

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

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

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

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

  45. $kon="\x55\x01\x01\x02\x02\x02\x02\x5f";
  46. $koff="\x55\x01\x01\x01\x01\x01\x01\x5b";
  47. $kstatus="\x55\x01\x00\x00\x00\x00\x00\x56";
  48. //定义接受的get 命令
  49. $ops = array("k1on", "k2on", "k3on", "k4on",
  50. "k1off","k2off","k3off","k4off","kon","koff","kstatus");
  51. //串口操作开始
  52. if ( isset($_GET['op']) and in_array($_GET['op'],$ops ) )
  53. {
  54. $data=${$_GET['op']};
  55. set_time_limit(3);
  56. //echo 'windows下设置窜口参数
    ';
  57. exec("mode ".$com."BAUD=9600 PARITY=n DATA=8 STOP=1 odsr=off");

  58. //echo "打开端口$com
    ";
  59. $f = dio_open ($com, O_RDWR | O_NOCTTY | O_NONBLOCK);
  60. if(!$f)
  61. {
  62. die("Error when open $com");
  63. }
  64. //echo "向串口发送数据
    ".$data.'
    ';
  65. dio_write ($f, $data);
  66. //echo "接收数据
    ";
  67. $str="";
  68. for ($i = 0; $i
  69. {
  70. $str.=bin2hex(dio_read( $f,1));
  71. }
  72. //echo $str;
  73. $k1=$str[7];
  74. $k2=$str[9];
  75. $k3=$str[11];
  76. $k4=$str[13];

  77. //echo "关闭端口
    ";
  78. dio_close($f);
  79. //串口操作结束

  80. //输出开始

  81. //简单控制界面
  82. $output='串口继电器控制演示程序 2011年4月


  83. k1开
  84. k1关
  85. k2开
  86. k2关
  87. k3开
  88. k3关
  89. k4开
  90. k4关
  91. 全开
  92. 全关
  93. 查询
  94. XML格式查询



  95. 开关状态 1关 2开



  96. k1:'.$k1.'


  97. k2:'.$k2.'


  98. k2:'.$k3.'


  99. k2:'.$k4.'
    ';

  100. echo $output;
  101. }
  102. ?>
复制代码

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

================================================================================================================================

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

  1. // HOW TO USE PHP TO WRITE TO YOUR SERIAL PORT: TWO METHODS
  2. $serproxy=true;
  3. if ($serproxy) {
  4. // Use this code in conjunction with SERPROXY.EXE
  5. // (http://www.lspace.nildram.co.uk/freeware.html)
  6. // which converts a Serial stream to a TCP/IP stream
  7. $fp = fsockopen ("localhost", 5331, $errno, $errstr, 30);
  8. if (!$fp) {
  9. echo "$errstr ($errno)";
  10. } else {
  11. $e = chr(27);
  12. $string = $e . "A" . $e . "H300";
  13. $string .= $e . "V100" . $e . "XL1SATO";
  14. $string .= $e . "Q1" . $e . "Z";
  15. echo $string;
  16. fputs ($fp, $string );
  17. fclose ($fp);
  18. }
  19. } elseif ($com1) {
  20. // Use this code to write directly to the COM1 serial port
  21. // First, you want to set the mode of the port. You need to set
  22. // it only once; it will remain the same until you reboot.
  23. // Note: the backticks on the following line will execute the
  24. // DOS 'mode' command from within PHP
  25. `mode com1: BAUD=9600 PARITY=N data=8 stop=1 xon=off`;
  26. $fp = fopen ("COM1:", "w+");
  27. if (!$fp) {
  28. echo "Uh-oh. Port not opened.";
  29. } else {
  30. $e = chr(27);
  31. $string = $e . "A" . $e . "H300";
  32. $string .= $e . "V100" . $e . "XL1SATO";
  33. $string .= $e . "Q1" . $e . "Z";
  34. echo $string;
  35. fputs ($fp, $string );
  36. fclose ($fp);
  37. }
  38. }
  39. ?>
复制代码

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

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

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

  14. 继电器板到计算机的数据帧说明:
  15. 数据头: 0x22 (作为标识)
  16. 地址:0x01(单个继电器默认为1)
  17. 操作类型: 与计算机发来的操作类型一致
  18. 数据(四个字节) 每个字节代表一个继电器,共四个;
  19. 数据值1:继电器断开,数据值2:继电器吸合。
  20. 校验 一字节和校验(用来防止数据出错)
  21. 计算机发送指令表(部分):
  22. // k1 k2 k3 k4 校验位
  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. $k1on="\x55\x01\x01\x02\x00\x00\x00\x59";
  38. $k2on="\x55\x01\x01\x00\x02\x00\x00\x59";
  39. $k3on="\x55\x01\x01\x00\x00\x02\x00\x59";
  40. $k4on="\x55\x01\x01\x00\x00\x00\x02\x59";

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

  45. $kon="\x55\x01\x01\x02\x02\x02\x02\x5f";
  46. $koff="\x55\x01\x01\x01\x01\x01\x01\x5b";
  47. $kstatus="\x55\x01\x00\x00\x00\x00\x00\x56";
  48. //定义接受的get 命令
  49. $op = array("k1on", "k2on", "k3on", "k4on",
  50. "k1off","k2off","k3off","k4off","kon","koff","kstatus");
  51. //串口操作开始
  52. if ( isset($_GET['op']) and in_array($_GET['op'],$op ) )
  53. {
  54. $data=${$_GET['op']};
  55. set_time_limit(3);
  56. //echo 'windows下设置窜口参数
    ';
  57. exec("mode ".$com."BAUD=9600 PARITY=n DATA=8 STOP=1 odsr=off");

  58. //echo "打开端口$com
    ";
  59. $f = fopen ($com, 'w+');
  60. if(!$f)
  61. {
  62. die("Error when open $com");
  63. }
  64. //echo "向串口发送数据
    ".$data.'
    ';
  65. fwrite ($f, $data);
  66. //echo "接收数据
    ";
  67. $str="";
  68. for ($i = 0; $i
  69. {
  70. $str.=bin2hex(fread( $f,1));
  71. }
  72. //echo $str;
  73. $k1=$str[7];
  74. $k2=$str[9];
  75. $k3=$str[11];
  76. $k4=$str[13];

  77. //echo "关闭端口
    ";
  78. fclose($f);
  79. //串口操作结束

  80. //输出开始
  81. if ( isset($_GET['out']) and ($_GET['out']=="xml" ) )
  82. {
  83. //xml输出
  84. $output =
  85. '
  86. '.$k1.'
  87. '.$k2.'
  88. '.$k3.'
  89. '.$k4.'';
  90. }
  91. else
  92. {
  93. //简单控制界面
  94. $output='串口继电器控制演示程序 2011年4月


  95. k1开
  96. k1关
  97. k2开
  98. k2关
  99. k3开
  100. k3关
  101. k4开
  102. k4关
  103. 全开
  104. 全关
  105. 查询
  106. XML格式查询



  107. 开关状态 1关 2开



  108. k1:'.$k1.'


  109. k2:'.$k2.'


  110. k2:'.$k3.'


  111. k2:'.$k4.'
    ';
  112. }
  113. echo $output;
  114. }
  115. ?>
复制代码

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

=======================================================================================================

你买的买的串口4路继电器板有DEMO程序给你吗?

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

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

-------------------------

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

-----------------------------

NB啊,也有过类似的经历,找了一些PHP的串口资料,后面也没有搞到,倒是用了网络转COM口代替了.NPORT类产品.