【转载】基于VC++的特殊波特率的实现方法

1 引言
  
  串口是计算机上一种非常通用的接口。大多数计算机包含一个基于RS232的串口。串口本质上是计算机的CPU和外部串行设备间的编码转换器。当数据从CPU经过串口发送出去时,字节数据被转换为串行的位。而在接收数据时,串行的位则被转换为字节数据。
  串口同时也是工业过程控制中仪器仪表设备通用的接口,可以用于获取远程采集设备的数据。目前在进行工业设备改造的过程中,通常是在Windows环境中进行应用程序开发,常常需要通过串口与工业设备通信。为了适应工业设备(尤其是国外进口设备)接口速率,这时对通信速率会有特殊要求,就不能使用计算机串口通常提供的速率(9600bps,19200bps,38400bps,57600bps,115200bps),而是76800bps。本文就Window环境下基于VC++开发串口通信程问题展开讨论,并介绍一种串口特殊波特率的实现方法。
  
  2Windows环境下基于VC++串口通信编程
  
  2.1采用Windows API 函数
  串口在Windows 中是作为文件来进行处理的, 不是直接对物理端口进行操作。对于串行通信, Windows 提供了相应的文件I/O 函数与通信函数, 通过了解这些函数的使用, 可以编制出符合不同需要的通信程序。与通信设备相关的结构有COMMCONFIG , COMMPROP, COMMTIMEOUTS, COMSTAT,DCB, MODEMDEVCAPS,MODEMSETTINGS 共七个, 与通信有关的Windows API 函数共有26 个, 详细说明可参考MSDN 帮助文件 。
  操作串行口一般遵从以下四个步骤:
  1) 打开串口。VC 中将串口作为文件操纵, 所以打开串口时, 也使用与打开文件相同的API 函数, 如下:
  HANDLE CreateFile( LPCTSTR lpFileName, //串口名称或设备路径
  DWORD dwDesiredAccess, // 存取方式, 读或写
  DWORD dwShareMode, //共享方式, 独占或共享
  LPSECURITY_ATTRIBUTES lpSecurityAttributes, //安全描述符
  DWORD dwCreationDisposition, //创建方式
  DWORD dwFlagsAndAttributes, //文件属性
  HANDLE hTemplateFile // 参照模板
  ) ;
  但是dwDesiredAccess 必须为0, 因为串口是独占设备;dwCreationDisposition 必须为OPEN_EXISTING, 因为只有串口存在时才能被打开; dwCreationDisposition 一般为FILE_FLAG_OVERLAPPED, 表示串行口以异步方式工作。
  2) 设置串口工作参数。串口能够顺利通信必须保证通信参数设置正确, 这些通信参数包括波特率、数据长度、停止位、校验方式等, 所以在串口打开之后必须进行串口设置。设置串口属性的一般思路是先利用GetCommState()获得串口的设备控制块DCB, 修改必要的部分之后, 再利用SetCommState( ) 将修改后的属性信息写回DCB 中。
  3) 从串口读取或向串口写入数据。串口的读写主要通过两个文件读写API 函数来实现, 即ReadFile( ) 和WriteFile( )。但是由于串口的通信并不是绝对的稳定, 所以应该采用异步方式, 以防止通信故障使程序陷入无限等待中。串口的读写方式也有两种, 一种是简单的查询方式, 这种方式比较容易实现, 但是浪费了大量的CPU时间; 另一种是基于事件驱动的方式, Windows 中共提供了九种串口通信时间, 请参见MSDN 帮助文件 。
  4) 关闭串口。串口是非共享资源,所以打开串口后,一定要关闭串口。关闭串口函数的原型:BOOL CloseHandle(HANDLE hObject);其中hObject参数为CreateFile()返回的端口句柄。返回值非0,则调用成功。
  2.2采用MScomm控件编程
  Microsoft Communications Control(简称MSComm)是Microsoft公司提供的简化Windows下串行通信编程的控件,它为应用程序提供了通过串行接口收发数据的简便方法。具体地说,它提供了两种处理通信问题的方法:1) 事件驱动(Event-driven)方法:主要是在comEvReceive(接收到数据)事件发生时响应并获取缓冲区的数据;2)查询法:每当应用程序执行完某一串行口操作后,应不断检查MSComm控件的CommEvent属性以检查执行结果或者检查某一事件是否发生。
  VC集成开发环境下对该控件编程的步骤:
  1)在当前的Workspace中插入MSComm控件
  在VC环境下,创建基于对话框的MFC应用程序,在设置项目选项时必须选上ActiveX Controls,其他的按照缺省设置。然后进行以下步骤:Project菜单→Add to Project→Components and Controls→Registered ActiveX Controls→选择Components: Microsoft Communications Control,version 6.0插入到当前的Workspace中。
  结果添加了类CMSComm(对应相应文件mscomm.h和mscomm.cpp也自动加入工程)。
  2)在MainFrm.h中加入MSComm控件
  protected:
  CMSComm m_ComPort;
  在Mainfrm.cpp::OnCreate()中加入:
  DWORD style=WS_VISIBLE|WS_CHILD;
  if(!m_ComPort.Create(NULL,style,CRect(0,0,0,0),this,ID_COMMCTRL)){
TRACE0(“Failed to create OLE Communications Control/n”);
  return-1;//创建失败}
  3)初始化串口
  4)捕捉串口事件
  MSComm控件可以采用轮询或事件驱动的两种方法从端口获取数据。比较常用的是事件驱动方法:有事件(接收到数据)时通知程序。在程序中需要捕获并处理这些通讯事件。
  5)读写串口
  2.3 利用VC++库标准通信函数实现串口编程
  利用VC进行异步通信编程,其实是对串口内部寄存器的读出或写入操作。VC可利用VC++类库中提供的标准通信函数_inp()、_outp()函数对其进行编程。
  通过计算机串口进行串行通信之前,必须根据设备的有关通信参数,约定双方的通信方式,包括波特率的设置、奇偶位校验及停止位的设立,确定数据传输帧格式和UART操作方式,逐个对线路控制寄存器、波特率因子寄存器等寄存器写入操作,可以利用VC运行库提供的通信函数_inp(),_outp()来实现串口通信。
  
  3 串口特殊波特率的实现方法
  
  许多工业设备以串行方式传送数据,但传输速率往往使用计算机上不支持的76800bpps,尤其是国外进口设备。决定计算机串口的通信速率是晶振频率,这决定了本质上是通过改变波特率因子来确定传输速率的标准串口是不支持76800bps速率的。
  这一问题可以通过使用USB转串口的接口解决,目前许多这类接口都提供比标准串口多的传输速率,其中包含76800bps的速率。在此基础上,利用USB转串口的设备结合所提供的库函数PComm.lib,编程实现特殊波特率的方法。
  1)程序开发环境设置:
  将PComm.lib添加到链接库列表中,确保PComm.h 和PComm.lib 文件在搜索路径中。
  添加PComm.h文件到程序头部:
  #include <windows.h>// PComm.h 文件需要Windows.h文件
  #include “PComm.h”
  2)采用PComm.lib进行串口通信的典型步骤:
  首先调用控制函数(打开、速率设置、校验方式等),然后调用输入、输出函数进行通信,调用串口状态查询函数(如果需要),关闭串口。典型示例如下:
  port = 2; //串口2
  ret = sio_open (port);// 打开
  if (ret == 0) {//成功打开
   sio_ioctl (port, B19200, P_NONE | BIT_8 | STOP_1 );// 速率、校验方式、位数等设置
  sio_write (port, "ABCDE", 5);//输出
  sio_read (port, ibuf, length);//输入
  }
  sio_close (port);//关闭
  3)主要库函数功能:
  串口控制函数:功能包括串口的打开、关闭、传输参数的设置等,主要函数有sio_open()、sio_close ()、sio_ioctl()sio_baud ( )。其中可以通过sio_ioctl()设置速率、校验方式、位数等,要使用特殊波特率则可以通过sio_baud ( )设置串口的实际波特率,例如设置串口2的波特率为76800可以用sio_baud (2,76800L),如果串口不支持该波特率,则会选择最接近的波特率来工作。
  串口读写控制函数:功能包括串口读写、超时设置等,主要函数有sio_read()、sio_SetReadTimeouts()、sio_write()、sio_SetWriteTimeouts ()等。
  串口状态查询函数:功能包括输入输出队列、串口参数等,主要函数有sio_iqueue ()、sio_oqueue () sio_getmode ()等。
  串口中断事件服务函数:当收到特定字符或收到设定的字符数时,触发相应的例程,主要函数有sio_term_irq()、 sio_cnt_irq()等。
  
  4 结束语
  
  PComm串行通信库函数完全兼容Microsoft Win32 API。它完全适合Win32环境下所有类型的串口,使用它提供的函数可以很容易实现多线程,结合目前常用的USB转串口的接口,可以实现较标准串口更多的传输速率,为开发工业环境下需要特殊速率的串行通信程序提供非常方便的途径。

 

原文地址:http://www.zhonghualunwen.com/article/sort011/sort0147/info-24468.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
int WINAPI sio_ioctl(int port, int baud, int mode); int WINAPI sio_getch(int port); int WINAPI sio_read(int port, char *buf, int len); int WINAPI sio_putch(int port, int term); int WINAPI sio_write(int port, char *buf, int len); int WINAPI sio_flush(int port, int func); long WINAPI sio_iqueue(int port); long WINAPI sio_oqueue(int port); int WINAPI sio_lstatus(int port); int WINAPI sio_lctrl(int port, int mode); int WINAPI sio_cnt_irq(int port, VOID (CALLBACK *func)(int port), int count); int WINAPI sio_modem_irq(int port, VOID (CALLBACK *func)(int port)); int WINAPI sio_break_irq(int port, VOID (CALLBACK *func)(int port)); int WINAPI sio_Tx_empty_irq(int port, VOID (CALLBACK *func)(int port)); int WINAPI sio_break(int port, int time); int WINAPI sio_flowctrl(int port, int mode); int WINAPI sio_Tx_hold(int port); int WINAPI sio_close(int port); int WINAPI sio_open(int port); long WINAPI sio_getbaud(int port); int WINAPI sio_getmode(int port); int WINAPI sio_getflow(int port); int WINAPI sio_DTR(int port, int mode); int WINAPI sio_RTS(int port, int mode); int WINAPI sio_baud(int port, long speed); int WINAPI sio_data_status(int port); int WINAPI sio_term_irq(int port, VOID (CALLBACK *func)(int port), char code); int WINAPI sio_linput(int port, char *buf, int lne, int term); int WINAPI sio_putb_x(int port, char *buf, int len, int tick); int WINAPI sio_putb_x_ex(int port, char *buf, int len, int tms); int WINAPI sio_view(int port, char *buf, int len); int WINAPI sio_TxLowWater(int port, int size); int WINAPI sio_AbortWrite(int port); int WINAPI sio_SetWriteTimeouts(int port, DWORD TotalTimeouts); int WINAPI sio_GetWriteTimeouts(int port, DWORD *TotalTimeouts); int WINAPI sio_SetReadTimeouts(int port, DWORD TotalTimeouts, DWORD IntervalTimeouts);Pcomm串口动态链接库
Moxa是一家做了几十年工业串口卡、串口服务器之类设备的公司,PComm Lite是一套易用性、可靠性久经考验串口编程开发包。相比用API或mscomm控件开发简单太多了。 版本:目前最新版是Version 1.6 Released May 14, 2012 支持XP/win7, 32/64bit的库都有,开发环境支持VC/VB/Delphi。注意可以会搜到另外一个Version 2.6. Released Jul 8, 2008,那是在WIN9x/NT4用的,不要看版本号高下错了。 使用方法:运行安装后有类库、例程、帮助和几个小工具。关键的有四个文件:pcomm.h/pcomm.lib两个文件复制到项目目录并引用,pcomm.dll丢到windows\system32下或跟应用程序放在一起,pcomm.chm帮助备查。 函数介绍:整个库包含50多个函数,最常用的也就10来个: 打开、关闭、设波特率的:sio_open ()、sio_close()、sio_baut() 发送数据的:sio_putch(),sio_write() 接收数据的:sio_getch(),sio_read() 查询输入输出缓冲区状态的:sio_iqueue(), sio_oqueue() 有时可能要设读写超时:sio_SetReadTimeouts(), sio_SetWriteTimeouts() 这些函数见名知义,用法查一下PComm.chm就行了。 编程方法: 接收数据一般免不了要开线程的,在接收线程里sio_iqueue()看一下有没有数据,有就处理,没就Sleep()一会。接收数据时它至少会帮你缓冲几十k,一般也不会丢数据。也可以用sio_term_irq()指定接收一定长数据数据就调用一个CALLBACK函数。 这些基本就齐活了。需要控制DTS/RTS、自动流控制都有,甚至还有Xmoderm/Ymoderm/Zmoderm发送文件。如果要Modbus之类的协议就要自己写了。 与其它串口开发方式比较:简单地说API是基础零件,自己做起来麻烦。MSComm控件、CSerialPort类是实验室产品,Pcomm lite是工业成熟产品。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值