正在加载……
Mysql日期和时间函数
Posted in LAMP on July 20, 2006 / 评论(0) »

Mysql日期和时间函数    
  posted   by   kevin   on   2004,   September   7,   8:26   PM.   技术资料      
  本文出自:http://linuxdb.yeah.net   作者:   晏子     (2001-07-05   15:00:00)    
   
   
  对于每个类型拥有的值范围以及并且指定日期何时间值的有效格式的描述见7.3.6   日期和时间类型。        
   
  这里是一个使用日期函数的例子。下面的查询选择了所有记录,其date_col的值是在最后30天以内:        
   
  mysql>   SELECT   something   FROM   table        
  WHERE   TO_DAYS(NOW())   -   TO_DAYS(date_col)   <=   30;        
   
  DAYOFWEEK(date)        
  返回日期date的星期索引(1=星期天,2=星期一,   ……7=星期六)。这些索引值对应于ODBC标准。        
  mysql>   select   DAYOFWEEK('1998-02-03');        
  ->   3        
   
  WEEKDAY(date)        
  返回date的星期索引(0=星期一,1=星期二,   ……6=   星期天)。        
  mysql>   select   WEEKDAY('1997-10-04   22:23:00');        
  ->   5        
  mysql>   select   WEEKDAY('1997-11-05');        
  ->   2        
   
  DAYOFMONTH(date)        
  返回date的月份中日期,在1到31范围内。        
  mysql>   select   DAYOFMONTH('1998-02-03');        
  ->   3        
   
  DAYOFYEAR(date)        
  返回date在一年中的日数,   在1到366范围内。        
  mysql>   select   DAYOFYEAR('1998-02-03');        
  ->   34        
   
  MONTH(date)        
  返回date的月份,范围1到12。        
  mysql>   select   MONTH('1998-02-03');        
  ->   2        
   
  DAYNAME(date)        
  返回date的星期名字。        
  mysql>   select   DAYNAME("1998-02-05");        
  ->   'Thursday'        
   
  MONTHNAME(date)        
  返回date的月份名字。        
  mysql>   select   MONTHNAME("1998-02-05");        
  ->   'February'        
   
  QUARTER(date)        
  返回date一年中的季度,范围1到4。        
  mysql>   select   QUARTER('98-04-01');        
  ->   2        
   
  WEEK(date)        
           
  WEEK(date,first)        
  对于星期天是一周的第一天的地方,有一个单个参数,返回date的周数,范围在0到52。2个参数形式WEEK()允许    
  你指定星期是否开始于星期天或星期一。如果第二个参数是0,星期从星期天开始,如果第二个参数是1,    
  从星期一开始。        
  mysql>   select   WEEK('1998-02-20');        
  ->   7        
  mysql>   select   WEEK('1998-02-20',0);        
  ->   7        
  mysql>   select   WEEK('1998-02-20',1);        
  ->   8        
   
  YEAR(date)        
  返回date的年份,范围在1000到9999。        
  mysql>   select   YEAR('98-02-03');        
  ->   1998        
   
  HOUR(time)        
  返回time的小时,范围是0到23。        
  mysql>   select   HOUR('10:05:03');        
  ->   10        
   
  MINUTE(time)        
  返回time的分钟,范围是0到59。        
  mysql>   select   MINUTE('98-02-03   10:05:03');        
  ->   5        
   
  SECOND(time)        
  回来time的秒数,范围是0到59。        
  mysql>   select   SECOND('10:05:03');        
  ->   3        
   
  PERIOD_ADD(P,N)        
  增加N个月到阶段P(以格式YYMM或YYYYMM)。以格式YYYYMM返回值。注意阶段参数P不是日期值。        
  mysql>   select   PERIOD_ADD(9801,2);        
  ->   199803        
   
  PERIOD_DIFF(P1,P2)        
  返回在时期P1和P2之间月数,P1和P2应该以格式YYMM或YYYYMM。注意,时期参数P1和P2不是日期值。        
  mysql>   select   PERIOD_DIFF(9802,199703);        
  ->   11        
   
  DATE_ADD(date,INTERVAL   expr   type)        
           
  DATE_SUB(date,INTERVAL   expr   type)        
           
  ADDDATE(date,INTERVAL   expr   type)        
           
  SUBDATE(date,INTERVAL   expr   type)        
  这些功能执行日期运算。对于MySQL   3.22,他们是新的。ADDDATE()和SUBDATE()是DATE_ADD()和DATE_SUB()的同义词。    
  在MySQL   3.23中,你可以使用+和-而不是DATE_ADD()和DATE_SUB()。(见例子)date是一个指定开始日期的    
  DATETIME或DATE值,expr是指定加到开始日期或从开始日期减去的间隔值一个表达式,expr是一个字符串;它可以以    
  一个“-”开始表示负间隔。type是一个关键词,指明表达式应该如何被解释。EXTRACT(type   FROM   date)函数从日期    
  中返回“type”间隔。下表显示了type和expr参数怎样被关联:   type值   含义   期望的expr格式        
  SECOND   秒   SECONDS        
  MINUTE   分钟   MINUTES        
  HOUR   时间   HOURS        
  DAY   天   DAYS        
  MONTH   月   MONTHS        
  YEAR   年   YEARS        
  MINUTE_SECOND   分钟和秒   "MINUTES:SECONDS"        
  HOUR_MINUTE   小时和分钟   "HOURS:MINUTES"        
  DAY_HOUR   天和小时   "DAYS   HOURS"        
  YEAR_MONTH   年和月   "YEARS-MONTHS"        
  HOUR_SECOND   小时,   分钟,   "HOURS:MINUTES:SECONDS"        
  DAY_MINUTE   天,   小时,   分钟   "DAYS   HOURS:MINUTES"        
  DAY_SECOND   天,   小时,   分钟,   秒   "DAYS   HOURS:MINUTES:SECONDS"        
   
  MySQL在expr格式中允许任何标点分隔符。表示显示的是建议的分隔符。如果date参数是一个DATE值并且你的计算仅仅    
  包含YEAR、MONTH和DAY部分(即,没有时间部分),结果是一个DATE值。否则结果是一个DATETIME值。        
   
  mysql>   SELECT   "1997-12-31   23:59:59"   +   INTERVAL   1   SECOND;        
  ->   1998-01-01   00:00:00        
  mysql>   SELECT   INTERVAL   1   DAY   +   "1997-12-31";        
  ->   1998-01-01        
  mysql>   SELECT   "1998-01-01"   -   INTERVAL   1   SECOND;        
  ->   1997-12-31   23:59:59        
  mysql>   SELECT   DATE_ADD("1997-12-31   23:59:59",        
  INTERVAL   1   SECOND);        
  ->   1998-01-01   00:00:00        
  mysql>   SELECT   DATE_ADD("1997-12-31   23:59:59",        
  INTERVAL   1   DAY);        
  ->   1998-01-01   23:59:59        
  mysql>   SELECT   DATE_ADD("1997-12-31   23:59:59",        
  INTERVAL   "1:1"   MINUTE_SECOND);        
  ->   1998-01-01   00:01:00        
  mysql>   SELECT   DATE_SUB("1998-01-01   00:00:00",        
  INTERVAL   "1   1:1:1"   DAY_SECOND);        
  ->   1997-12-30   22:58:59        
  mysql>   SELECT   DATE_ADD("1998-01-01   00:00:00",        
  INTERVAL   "-1   10"   DAY_HOUR);        
  ->   1997-12-30   14:00:00        
  mysql>   SELECT   DATE_SUB("1998-01-02",   INTERVAL   31   DAY);        
  ->   1997-12-02        
  mysql>   SELECT   EXTRACT(YEAR   FROM   "1999-07-02");        
  ->   1999        
  mysql>   SELECT   EXTRACT(YEAR_MONTH   FROM   "1999-07-02   01:02:03");        
  ->   199907        
  mysql>   SELECT   EXTRACT(DAY_MINUTE   FROM   "1999-07-02   01:02:03");        
  ->   20102        

如果你指定太短的间隔值(不包括type关键词期望的间隔部分),MySQL假设你省掉了间隔值的最左面部分。例如,    
  如果你指定一个type是DAY_SECOND,值expr被希望有天、小时、分钟和秒部分。如果你象"1:10"这样指定值,    
  MySQL假设日子和小时部分是丢失的并且值代表分钟和秒。换句话说,"1:10"   DAY_SECOND以它等价于"1:10"   MINUTE_SECOND    
  的方式解释,这对那MySQL解释TIME值表示经过的时间而非作为一天的时间的方式有二义性。如果你使用确实不正确的日期,    
  结果是NULL。如果你增加MONTH、YEAR_MONTH或YEAR并且结果日期大于新月份的最大值天数,日子在新月用最大的天调整。        
   
  mysql>   select   DATE_ADD('1998-01-30',   Interval   1   month);        
  ->   1998-02-28        
   
  注意,从前面的例子中词INTERVAL和type关键词不是区分大小写的。        
  TO_DAYS(date)        
  给出一个日期date,返回一个天数(从0年的天数)。        
  mysql>   select   TO_DAYS(950501);        
  ->   728779        
  mysql>   select   TO_DAYS('1997-10-07');        
  ->   729669        
   
  TO_DAYS()不打算用于使用格列高里历(1582)出现前的值。        
   
  FROM_DAYS(N)        
  给出一个天数N,返回一个DATE值。        
  mysql>   select   FROM_DAYS(729669);        
  ->   '1997-10-07'        
   
  TO_DAYS()不打算用于使用格列高里历(1582)出现前的值。        
   
  DATE_FORMAT(date,format)        
  根据format字符串格式化date值。下列修饰符可以被用在format字符串中:   %M   月名字(January……December)        
  %W   星期名字(Sunday……Saturday)        
  %D   有英语前缀的月份的日期(1st,   2nd,   3rd,   等等。)        
  %Y   年,   数字,   4   位        
  %y   年,   数字,   2   位        
  %a   缩写的星期名字(Sun……Sat)        
  %d   月份中的天数,   数字(00……31)        
  %e   月份中的天数,   数字(0……31)        
  %m   月,   数字(01……12)        
  %c   月,   数字(1……12)        
  %b   缩写的月份名字(Jan……Dec)        
  %j   一年中的天数(001……366)        
  %H   小时(00……23)        
  %k   小时(0……23)        
  %h   小时(01……12)        
  %I   小时(01……12)        
  %l   小时(1……12)        
  %i   分钟,   数字(00……59)        
  %r   时间,12   小时(hh:mm:ss   [AP]M)        
  %T   时间,24   小时(hh:mm:ss)        
  %S   秒(00……59)        
  %s   秒(00……59)        
  %p   AM或PM        
  %w   一个星期中的天数(0=Sunday   ……6=Saturday   )        
  %U   星期(0……52),   这里星期天是星期的第一天        
  %u   星期(0……52),   这里星期一是星期的第一天        
  %%   一个文字“%”。        
   
  所有的其他字符不做解释被复制到结果中。        
   
  mysql>   select   DATE_FORMAT('1997-10-04   22:23:00',   '%W   %M   %Y');        
  ->   'Saturday   October   1997'        
  mysql>   select   DATE_FORMAT('1997-10-04   22:23:00',   '%H:%i:%s');        
  ->   '22:23:00'        
  mysql>   select   DATE_FORMAT('1997-10-04   22:23:00',        
  '%D   %y   %a   %d   %m   %b   %j');        
  ->   '4th   97   Sat   04   10   Oct   277'        
  mysql>   select   DATE_FORMAT('1997-10-04   22:23:00',        
  '%H   %k   %I   %r   %T   %S   %w');        
  ->   '22   22   10   10:23:00   PM   22:23:00   00   6'        
  MySQL3.23中,在格式修饰符字符前需要%。在MySQL更早的版本中,%是可选的。        
   
  TIME_FORMAT(time,format)        
  这象上面的DATE_FORMAT()函数一样使用,但是format字符串只能包含处理小时、分钟和秒的那些格式修饰符。    
  其他修饰符产生一个NULL值或0。        
  CURDATE()        
           
  CURRENT_DATE        
  以'YYYY-MM-DD'或YYYYMMDD格式返回今天日期值,取决于函数是在一个字符串还是数字上下文被使用。        
  mysql>   select   CURDATE();        
  ->   '1997-12-15'        
  mysql>   select   CURDATE()   +   0;        
  ->   19971215        
   
  CURTIME()        
           
  CURRENT_TIME        
  以'HH:MM:SS'或HHMMSS格式返回当前时间值,取决于函数是在一个字符串还是在数字的上下文被使用。        
  mysql>   select   CURTIME();        
  ->   '23:50:26'        
  mysql>   select   CURTIME()   +   0;        
  ->   235026        
   
  NOW()        
           
  SYSDATE()        
           
  CURRENT_TIMESTAMP        
  以'YYYY-MM-DD   HH:MM:SS'或YYYYMMDDHHMMSS格式返回当前的日期和时间,取决于函数是在一个字符串还是在数字的    
  上下文被使用。        
  mysql>   select   NOW();        
  ->   '1997-12-15   23:50:26'        
  mysql>   select   NOW()   +   0;        
  ->   19971215235026        
   
  UNIX_TIMESTAMP()        
           
  UNIX_TIMESTAMP(date)        
  如果没有参数调用,返回一个Unix时间戳记(从'1970-01-01   00:00:00'GMT开始的秒数)。如果UNIX_TIMESTAMP()用一    
  个date参数被调用,它返回从'1970-01-01   00:00:00'   GMT开始的秒数值。date可以是一个DATE字符串、一个DATETIME    
  字符串、一个TIMESTAMP或以YYMMDD或YYYYMMDD格式的本地时间的一个数字。        
  mysql>   select   UNIX_TIMESTAMP();        
  ->   882226357        
  mysql>   select   UNIX_TIMESTAMP('1997-10-04   22:23:00');        
  ->   875996580        
   
  当UNIX_TIMESTAMP被用于一个TIMESTAMP列,函数将直接接受值,没有隐含的“string-to-unix-timestamp”变换。        
   
  FROM_UNIXTIME(unix_timestamp)        
  以'YYYY-MM-DD   HH:MM:SS'或YYYYMMDDHHMMSS格式返回unix_timestamp参数所表示的值,取决于函数是在一个字符串    
  还是或数字上下文中被使用。        
  mysql>   select   FROM_UNIXTIME(875996580);        
  ->   '1997-10-04   22:23:00'        
  mysql>   select   FROM_UNIXTIME(875996580)   +   0;        
  ->   19971004222300        
   
  FROM_UNIXTIME(unix_timestamp,format)        
  返回表示   Unix   时间标记的一个字符串,根据format字符串格式化。format可以包含与DATE_FORMAT()函数列出的条    
  目同样的修饰符。        
  mysql>   select   FROM_UNIXTIME(UNIX_TIMESTAMP(),        
  '%Y   %D   %M   %h:%i:%s   %x');        
  ->   '1997   23rd   December   03:43:30   x'        
   
  SEC_TO_TIME(seconds)        
  返回seconds参数,变换成小时、分钟和秒,值以'HH:MM:SS'或HHMMSS格式化,取决于函数是在一个字符串还是在数字    
  上下文中被使用。        
  mysql>   select   SEC_TO_TIME(2378);        
  ->   '00:39:38'        
  mysql>   select   SEC_TO_TIME(2378)   +   0;        
  ->   3938        
   
  TIME_TO_SEC(time)        
  返回time参数,转换成秒。        
  mysql>   select   TIME_TO_SEC('22:23:00');        
  ->   80580        
  mysql>   select   TIME_TO_SEC('00:39:38');        
  ->   2378    

可以算出你家的电话号码喔~

  首先~

  1.请将电话号码的【前】4位数字输入计算器

  (若你家电话号码不足8位时,就输入【前】3位)

  2.将它乘以80

  3.+1

  4.乘以250

  5.+电话号码的【后】4位数字

  6.+再加一次电话号码【后】4位

  7.将总数-250

  8.最后将屏幕上的数字【÷】2

  看看是不是你的电话~,,,

  看了就回贴

1. 预先的知识:
什么是RS232/RS484及其应用?
引用:
RS232接口就是串口,电脑机箱后方的9芯(或25芯)插座,旁边一般有 "|O|O|" 样标识。 
一般机箱有两个,新机箱有可能只有一个。笔记本电脑有可能没有。 
有很多工业仪器将它作为标准通信端口。通信的内容与格式一般附在仪器的用户说明书中。 

计算机与计算机或计算机与终端之间的数据传送可以采用串行通讯和并行通讯二种方式。由于串行通讯方式具有使用线路少、成本低,特别是在远程传输时,避免了多条线路特性的不一致而被广泛采用。 在串行通讯时,要求通讯双方都采用一个标准接口,使不同 的设备可以方便地连接起来进行通讯。 RS-232-C接口(又称 EIA RS-232-C)是目前最常用的一种串行通讯接口。它是在1970年由美国电子工业协会(EIA)联合贝尔系统、 调制解调器厂家及计算机终端生产厂家共同制定的用于串行通讯的标 准。它的全名是“数据终端设备(DTE)和数据通讯设备(DCE)之间 串行二进制数据交换接口技术标准”该标准规定采用一个25个脚的 DB25连接器,对连接器的每个引脚的信号内容加以规定,还对各种信 号的电平加以规定。 

(1)接口的信号内容 实际上RS-232-C的25条引线中有许多是很少使用的,在计算机与终端通讯中一般只使用3-9条引线。RS-232-C最常用的9条引线的信号内容见附表1所示 

(2)接口的电气特性 在RS-232-C中任何一条信号线的电压均为负逻辑关系。即:逻 辑“1”,-5— -15V;逻辑“0” +5— +15V 。噪声容限为2V。即 要求接收器能识别低至+3V的信号作为逻辑“0”,高到-3V的信号 作为逻辑“1” 
(3) 接口的物理结构 RS-232-C接口连接器一般使用型号为DB-25的25芯插头座,通常插头在DCE端,插座在DTE端. 一些设备与PC机连接的RS-232-C接口,因为不使用对方的传送控制信号,只需三条接口线,即“发送数据”、“接收数据”和“信号地”。所以采用DB-9的9芯插头座,传输线采用屏蔽双绞线。 

(4)传输电缆长度 由RS-232C标准规定在码元畸变小于4%的情况下,传输电缆长度应为50英尺,其实这个4%的码元畸变是很保守的,在实际应用中,约有99%的用户是按码元畸变10-20%的范围工作的,所以实际使用中最大距离会远超过50英尺,美国DEC公司曾规定允许码元畸变为10%而得出附表2 的实验结果。其中1号电缆为屏蔽电缆,型号为DECP.NO.9107723 内有三对双绞线,每对由22# AWG 组成,其外覆以屏蔽网。2号电缆为不带屏蔽的电缆。型号为DECP.NO.9105856-04是22#AWG的四芯电缆。 

1.RS-232-C是美国电子工业协会EIA(Electronic Industry Association)制定的一种串行物理接口标准。RS是英文“推荐标准”的缩写,232为标识号,C表示修改次数。RS-232-C总线标准设有25条信号线,包括一个主通道和一个辅助通道,在多数情况下主要使用主通道,对于一般双工通信,仅需几条信号线就可实现,如一条发送线、一条接收线及一条地线。RS-232-C标准规定的数据传输速率为每秒50、75、 100、150、300、600、1200、2400、4800、9600、19200波特。RS-232-C标准规定,驱动器允许有2500pF的电容负载,通信距离将受此电容限制,例如,采用150pF/m的通信电缆时,最大通信距离为15m;若每米电缆的电容量减小,通信距离可以增加。传输距离短的另一原因是RS-232属单端信号传送,存在共地噪声和不能抑制共模干扰等问题,因此一般用于20m以内的通信。 

2.RS-485总线,在要求通信距离为几十米到上千米时,广泛采用RS-485 串行总线标准。RS-485采用平衡发送和差分接收,因此具有抑制共模干扰的能力。加上总线收发器具有高灵敏度,能检测低至200mV的电压,故传输信号能在千米以外得到恢复。 RS-485采用半双工工作方式,任何时候只能有一点处于发送状态,因此,发送电路须由使能信号加以控制。RS-485用于多点互连时非常方便,可以省掉许多信号线。应用RS-485 可以联网构成分布式系统,其允许最多并联32台驱动器和32台接收器。 



以往,PC与智能设备通讯多借助RS232、RS485、以太网等方式,主要取决于设备的接口规范。但RS232、RS485只能代表通讯的物理介质层和链路层,如果要实现数据的双向访问,就必须自己编写通讯应用程序,但这种程序多数都不能符合ISO/OSI的规范,只能实现较单一的功能,适用于单一设备类型,程序不具备通用性。在RS232或RS485设备联成的设备网中,如果设备数量超过2台,就必须使用RS485做通讯介质,RS485网的设备间要想互通信息只有通过“主(Master)”设备中转才能实现,这个主设备通常是PC,而这种设备网中只允许存在一个主设备,其余全部是从(Slave)设备。而现场总线技术是以ISO/OSI模型为基础的,具有完整的软件支持系统,能够解决总线控制、冲突检测、链路维护等问题。

来源网址:http://zhidao.baidu.com/question/4578886.html




从串口双机对联线缆指南
引用:
  (一)串行通讯电缆的制作

  无论是9孔插头,还是25孔插头,其串行通讯电缆连接时都要遵循下列对接关系:

  SG←→SG TXD←→RXD RXD←→TXD RTS←→CTS
  CTS←→RTS DTR←→DSR DSR←→DTR

  根据上述对接关系,就可以非常方便地连接串行通讯电缆。这里顺便介绍一下上述各引脚所代表的含义:

  SG英文全称为Signal Ground/Common Return,表示信号地;
  TXD指Transmitted Data,表示数据发送;
  RXD指Received Data,表示接收数据;
  RTS指Request To Send,表示发送请求;
  CTS指Clear To Send,表示清除请求;
  DTR指Data Terminal Ready,表示数据终端准备就绪;
  DSR指Data Signal Rate Selector,表示数据置位准备就绪。

  在制作9芯串口连线时,需要2个9孔插头和1.5米长的至少7芯的扁平电缆,引脚连线如下所示。

  9孔插头-9孔插头引脚连线为:2-3、3-2、4-6、5-5、6-4、7-8、8-7。
  9孔插头-25孔插头引脚连线为:2-2、3-3、4-6、5-7、6-20、7-5、8-4。
  25孔插头-25孔插头引脚连线为:2-3、3-2、4-5、5-4、6-20、7-7、20-6。


来源网址:http://win2000server.vicp.net:88/Article_Show.asp?ArticleID=25




二、测试环境的构建:
1.  参考上面的《(一)串行通讯电缆的制作》,首先把两台电脑通过串口连结起来。
  当然,你也完全可以这么操作一台电脑上面的两个串口,而不需要两台电脑;如果你有两个串口的话。
  因为我以前做过工业控制底层开发,所以我可以很容易的构建这个基本的环境;
  实际上,只要:RxD TxD对接,GND直连即可,俗称三线连接。
  这一点不做任何答疑。

2. PHP运行环境的构建:
操作系统:WindowsXP(其他Windows系统没有测试)
PHP5.1.4: http://cn.php.net/get/php-5.1.4-Win32.zip/from/a/mirror
PECL5.1.4:http://cn.php.net/get/pecl-5.1.4-Win32.zip/from/a/mirror
解压PHP5.1.4,把PECL5.1.4之中的php_dio.dll放到PHP5.1.4的ext目录之下
把PHP5.1.4之中的php.ini-dist拷贝粘贴为php.ini,并打开设置然后保存:

extension=php_dio.dll


  这一点不做任何答疑。

三:参考资料:
1. 参考手册文档:
http://cn.php.net/manual/zh/ref.dio.php
http://cn.php.net/manual/zh/ref.exec.php
  如果代码之中有你没有见过,或者没有使用过,或者不熟悉的函数,请访问以上网址。
  主要使用了PHP的Direct IO Functions.

四:演示代码:
[font=Times New Roman]


<?php
// --------------------------------------------------------------------------
// File name   : RS232_Server.php
// Description : RS232演示上位机程序
// Requirement : PHP 5.1.4 (cli) (http://www.php.net)
//
// Copyright(C), HonestQiao, 2006, All Rights Reserved.
//
// Author: HonestQiao (honestqiao@hotmail.com/QQ:5601680) 
//
// 程序简介:
// 本程序与RS232_Client构成一个完整的演示系统,展示了PHP在RS232串口通讯上的应用。
// 程序之中实现了一个基础但是完整的RS232通讯协议(HQB232),通讯协议格式如下:
// 协议内容:
//             C->S 01 //请求通讯
//             S->C 02 //响应通讯
//             C->S LEN DATA //LEN表示数据(DATA)长度 DATA表示实际数据
//             C->S 03 //结束通讯
// 说明:S表示上位机 C表示下位机
//       HQB232表示HonestQiao演示的基础(Base)RS232通讯协议,包含了协议的
//   请求和响应,数据帧的结构。
//       演示过程为通讯的请求和响应,十次数据帧的发送, 通讯的结束
//       数据帧的结构为当前的序号,microtime(),随机字符串
//        
//       欢迎探讨PHP在RS232串口通讯上的应用。
// --------------------------------------------------------------------------
set_time_limit(0);
exec('mode COM1: baud=115200 data=8 stop=1 parity=n xon=on');

$fd = dio_open('COM1:', O_RDWR);
if(!$fd)
{
die("Error when open COM1");
}

$ff = dio_stat($fd);print_r($ff);
echo "HQB232 SERVER is listenning on COM1\n";
/// read
$len = 2;
$t=0;while (($t++)<1000) 
{
$data = dio_read($fd, $len);
if ($data) {
if($data==chr(0).chr(1)){
echo "S_RECV:01\n";
echo "S_SEND:02\n";
dio_write($fd,chr(0).chr(2));
break;
}
}
}

/// read
$len = 2;
$t=0;while (($t++)<1000) 
{
$len = 2;
$data = dio_read($fd, $len);
if($data==chr(0).chr(3)){
echo "S_RECV:03\n";
break;
}
elseif ($data) {
$len = intval($data);
$data = dio_read($fd, $len);
if($data){
echo "S_RECV:($len)$data\n";
}
}
}
dio_close($fd);
?> 



 


<?php
// --------------------------------------------------------------------------
// File name   : RS232_Client.php
// Description : RS232演示下位机程序
// Requirement : PHP 5.1.4 (cli) (http://www.php.net)
//
// Copyright(C), HonestQiao, 2006, All Rights Reserved.
//
// Author: HonestQiao (honestqiao@hotmail.com/QQ:5601680) 
//
// 程序简介:
// 本程序与RS232_Server构成一个完整的演示系统,展示了PHP在RS232串口通讯上的应用。
// 程序之中实现了一个基础但是完整的RS232通讯协议(HQB232),通讯协议格式如下:
// 协议内容:
//             C->S 01 //请求通讯
//             S->C 02 //响应通讯
//             C->S LEN DATA //LEN表示数据(DATA)长度 DATA表示实际数据
//             C->S 03 //结束通讯
// 说明:S表示上位机 C表示下位机
//       HQB232表示HonestQiao演示的基础(Base)RS232通讯协议,包含了协议的
//   请求和响应,数据帧的结构。
//       演示过程为通讯的请求和响应,十次数据帧的发送, 通讯的结束
//       数据帧的结构为当前的序号,microtime(),随机字符串
//        
//       欢迎探讨PHP在RS232串口通讯上的应用。
// --------------------------------------------------------------------------
set_time_limit(0);
exec('mode COM2: baud=115200 data=8 stop=1 parity=n xon=on');

$fd = dio_open('COM2:', O_RDWR);
if(!$fd)
{
die("Error when open COM2");
}

$ff = dio_stat($fd);print_r($ff);
echo "HQB232 CLIENT is start on COM2\n";
dio_write($fd,chr(0).chr(1));echo "C_SEND:01\n";
$len = 2;
$t=0;while(($t++)<1000)
{
$data = dio_read($fd, $len);
if($data==chr(0).chr(2)){
echo "C_RECV:02\n";
break;
}
}
$len = 2;
$t=0;while(($t++)<10)
{
$sdata = sprintf("%03d",$t) . "=" . microtime() . " (" . randomkeys(rand(0,35)) . ")";
$slen = strlen($sdata);
$stxlen = sprintf("%02d",$slen);
dio_write($fd,"$stxlen");
dio_write($fd,"$sdata");echo "C_SEND:($stxlen)$sdata\n";
//sleep(1);
}
dio_write($fd,chr(0).chr(3));echo "C_SEND:03\n";
dio_close($fd);

function randomkeys($length)
  {
   $pattern = "1234567890abcdefghijklmnopqrstuvwxyz";
   for($i=0;$i<$length;$i++)
   {
     $key .= $pattern{rand(0,35)};
   }
   return $key;
}
?>

[/font]

五、演示过程:
上位机:开始->运行->CMD
然后转到PHP5.1.4目录之下,执行:
php -f RS232_Server.php

下位机:开始->运行->CMD
然后转到PHP5.1.4目录之下,执行:
php -f RS232_Client.php


实际结果如下:



F:\usr\local\php5>php -f e:\RS232_Server.php
Array
(
    [device] => 3
    [inode] => 0
    [mode] => 8192
    [nlink] => 1
    [uid] => 0
    [gid] => 0
    [device_type] => 3
    [size] => 0
    [atime] => 0
    [mtime] => 0
    [ctime] => 0
)
HQB232 SERVER is listenning on COM1
S_RECV:01
S_SEND:02
S_RECV:(53)001=0.19238200 1150031774 (krruv981gpf1pmi1fz4qz09e9)
S_RECV:(42)002=0.19144800 1150031775 (jrhw41mphuy0ui)
S_RECV:(40)003=0.19148500 1150031776 (lqq560p6v17r)
S_RECV:(36)004=0.19148900 1150031777 (3ct02xmc)
S_RECV:(28)005=0.19212700 1150031778 ()
S_RECV:(33)006=0.19162500 1150031779 (2ilqf)
S_RECV:(34)007=0.19167800 1150031780 (vwmdfc)
S_RECV:(62)008=0.19168700 1150031781 (idb0laix4a6ryxz5nb7u74iaza601it6sv)
S_RECV:(56)009=0.19170100 1150031782 (r9ypgtvu4j7w1u141qx6im20ajy7)
S_RECV:(53)010=0.19171000 1150031783 (wq5mp1sdfuet1tp0x3vk67n47)
S_RECV:03

F:\usr\local\php5>



 



F:\usr\local\php5>php -f e:\RS232_Client.php
Array
(
    [device] => 3
    [inode] => 0
    [mode] => 8192
    [nlink] => 1
    [uid] => 0
    [gid] => 0
    [device_type] => 3
    [size] => 0
    [atime] => 0
    [mtime] => 0
    [ctime] => 0
)
HQB232 CLIENT is start on COM2
C_SEND:01
C_RECV:02
C_SEND:(53)001=0.19238200 1150031774 (krruv981gpf1pmi1fz4qz09e9)
C_SEND:(42)002=0.19144800 1150031775 (jrhw41mphuy0ui)
C_SEND:(40)003=0.19148500 1150031776 (lqq560p6v17r)
C_SEND:(36)004=0.19148900 1150031777 (3ct02xmc)
C_SEND:(28)005=0.19212700 1150031778 ()
C_SEND:(33)006=0.19162500 1150031779 (2ilqf)
C_SEND:(34)007=0.19167800 1150031780 (vwmdfc)
C_SEND:(62)008=0.19168700 1150031781 (idb0laix4a6ryxz5nb7u74iaza601it6sv)
C_SEND:(56)009=0.19170100 1150031782 (r9ypgtvu4j7w1u141qx6im20ajy7)
C_SEND:(53)010=0.19171000 1150031783 (wq5mp1sdfuet1tp0x3vk67n47)
C_SEND:03

F:\usr\local\php5>
六:说明
1. exec('mode COM1: baud=115200 data=8 stop=1 parity=n xon=on');
    exec('mode COM2: baud=115200 data=8 stop=1 parity=n xon=on');

mode是CMD下面的命令,表示设置串口的参数,因为dio_tcsetattr() 未在Windows下面实现,所以需要使用CMD的mode命令来进行设置,具体用法,请看:help mode

2. 通讯协议使用ASCII文本进行,没有使用HEX十六进制。因为是演示程序,所以协议非常简单,但是一个协议基本的内容都有了。

3. 下位机程序的sleep(1),这个是通讯之中常见的情况,数据传输和上位机处理需要一定的时间。

4. 演示的为RS232,以此类推,你也可以用到其他的场合。例如:简单修改,应用到HTTP通讯。

5. 硬件环境的建立,PHP环境的建立,不做任何答疑。

6. 欢迎探讨。

7. 感谢mikespook的意见,附加,如果是*nix,则:
'/dev/ttyS0'表示第一个COM端口,依此类推;端口的设置,应该在dio_open之后,使用:
dio_tcsetattr($fd, array(
  'baud' => 9600,
  'bits' => 8,
  'stop'  => 1,
  'parity' => 0
));
 mikespook回复于:2006-06-11 22:08:31

帮乔版补充一点~~
linux下com口读写采用文件的方式~比较简单~~所以dio这个ext只用于windows下~~


 HonestQiao回复于:2006-06-11 22:16:12

引用:原帖由 mikespook 于 2006-6-11 22:08 发表
帮乔版补充一点~~
linux下com口读写采用文件的方式~比较简单~~所以dio这个ext只用于windows下~~ 



注意,该模块完全适合在*nix下面使用。
为何:举一个例子:
dio_tcsetattr()这个函数是设置端口参数的,如果使用PHP文件读写,那么将不好设置了(虽然可以有方法设置)。


PHP supports the direct io functions as described in the Posix Standard (Section 6) for performing I/O functions at a lower level than the C-Language stream I/O functions (fopen(), fread(),..). The use of the DIO functions should be considered only when direct control of a device is needed. In all other cases, the standard filesystem functions are more than adequate.

[ 本帖最后由 HonestQiao 于 2006-6-11 22:18 编辑 ]


 mikespook回复于:2006-06-11 22:53:54

The use of the DIO functions should be considered only when direct control of a device is needed. In all other cases, the standard filesystem functions are more than adequate. 

我是这样理解这句话的~~
“DIO函数应当只用在有必要直接操作设备的时候。其他任何时候,标准的文件系统函数将更加适合。”
*nix下“一切皆文件”的思想,操作com亦可~~印象中WIN下的COM好像在WINNT家族中也是使用文件的方式访问~~

hCOM = CreateFile( "COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);

这样独占访问好像也可以~~
----------------------
不过使用 dio 可以在不编写ext的情况下访问如加密狗,刷读卡设备等等~~


 james.liu回复于:2006-06-11 22:59:13

赫赫,,你以前用什么语言写工控


 mikespook回复于:2006-06-11 23:03:57

没写过工控程序,之前在单片机上做试验都用的是ASM和C~~
好像也有PASCAL的解释器,但是那个是试验箱带的东西~~

对于工控程序这种实时要求很高的程序来说,角本语言非常不适合做核心开发~~ASM和C有着绝对的话语权~~
如果哪天像JAVA CPU一样出现固化的PHP解释器,那就比较爽了~~呵呵~~


 HonestQiao回复于:2006-06-11 23:06:46

是啊,既然提供了这么好的东西,应该多用用。

使用文件的方式,适合与你的程序可能会接受多个封装操作端,但是进行想通的处理。

C++做的,主要是ARM的。

原文链接:http://bbs.chinaunix.net/viewthread.php?tid=771726
转载请注明作者名及原文出处
分页: 1/1 第一页 1 最后页 [ 显示模式: 摘要 | 列表 ]