用API函数实现串行通讯.docx
- 文档编号:30112296
- 上传时间:2023-08-05
- 格式:DOCX
- 页数:10
- 大小:19.82KB
用API函数实现串行通讯.docx
《用API函数实现串行通讯.docx》由会员分享,可在线阅读,更多相关《用API函数实现串行通讯.docx(10页珍藏版)》请在冰豆网上搜索。
用API函数实现串行通讯
用API函数实现串行通讯
责任编辑:
admin 更新日期:
2005-8-6
以往的DOS系统是通过DOS中断和BIOS中断向用户提供串行接口的通讯能力。
在Windows环境下,C++的开发工具既没有提供象DOS和BIOS中那样专门的串行通讯控制方法,也不允许用户直接控制串口的中断。
为了保证资源共享,Windows系统完全接管了各种硬件资源,使用中断来控制端口将破坏系统的多任务性,使系统的稳定性受到影响。
但Windows同时也提供了功能强大的API函数使用户能间接的控制串行通讯。
1、实现串行通讯的相关API函数
API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作。
常用函数及作用如表5-1所示。
表5-1常用串行通讯API函数及其作用
函数名 作用
CreateFile打开串口
GetmState 检测串口设置
SetmState设置串口
BuildermDCB用字符串中的值来填充设备控制块
GetmTimeouts检测通信超时设置
SetmTimeouts设置通信超时参数
SetmMask设定被监控事件
WaitmEvent等待被监控事件发生
WaitForMultipleObjects等待多个被监测对象的结果
WriteFile发送数据
ReadFile 接收数据
GetOverlappedResult返回最后重叠(异步)操作结果
Purgem清空串口缓冲区,退出所有相关操作
ClearmError更新串口状态结构体,并清除所有串口硬件错误
CloseHandle 关闭串行口
2、打开串口
函数CreateFile原本用于打开文件,但它同样可用于打开一个通信端口。
与系统中其他对象一样,通信端口也是用句柄来标识的。
CreateFile函数返回被操作的通信端口句柄,其调用方法如下:
HANDLECreateFile(
LPCTSTRlpFileName, //指向文件名字符串的指针
DWORDdwDesireAccess, //操作模式
DWORDdwShareMode, //共享方式
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
//指向安全属性的指针
DWORDdwCreationDistribution,//文件建立方式
DWORDdwFlagsAndAttributes //文件属性
HANDLEhTemplateFile) //模板文件句柄
lpFileName:
指向一个以NULL结束的字符串,该串指定了要创建、打开或截断的文件、管道、通信源、磁盘设备或控制台的名字。
当用CreateFile打开串口时,这个参数可用“1”指定串口1,用“2”指定串口2,依此类推。
dwDesireAccess:
指定对文件访问的类型,该参数可以为GENERIC_READ(指定对该文件的读访问权)或ENERIC_WRITE(指定该文件的写访问权)两个值之一或同时为为这两个值。
用ENERIC_READ|GENERIC_WRITE则指定可对串口进行读写;
dwShareMode:
指定此文件可以怎样被共享。
因为串行口不支持任何共享模式,所以dwShareMode必须设为0;
lpSecurityAttributes定义安全属性,一般不用,可设为NULL。
Win9x下该参数被忽略;
dwCreationDistribution定义文件创建方式,对串口必须设为OPEN_EXISTING,表示打开已经存在的文件;
dwFlagsAndAttributes为该文件指定定义文件属性和标志,这个程序中设为FILE_FLAG_OVERLAPPED,表示异步通信方式;
hTemplateFile指向一个模板文件的句柄,串口无模板可言,设为NULL。
在Windows9x下该参数必须为NULL。
用异步读写方式打开串口1的函数调用如下:
m_hm=CreateFile(“1”, //打开串口1
GENERIC_READ|GENERIC_WRITE,//读写方式
0, //不能共享
NULL, //不用安全结构
OPEN_EXISTING, //打开已存在的设备
FILE_FLAG_OVERLAPPED, //异步方式
0); //无模板
串口被成功打开时,返回其句柄,否则返回INVALID_HANDLE_VALUE(0XFFFFFFFF)。
3、串口设置
第一次打开串口时,串口设置为系统默认值,函数GetmState和SetmState可用于检索和设定端口设置的DCB(设备控制块)结构,该结构中BaudRate、ByteSize、StopBits和Parity字段含有串口波特率、数据位数、停止位和奇偶校验控制等信息。
程序中可先用GetmState检索端口的当前设置,修改其中的部分字段后再用SetmState进行端口设定。
这样可不必构造一个完整的DCB结构。
下面介绍几个主要的函数和结构体:
(1)GetmState
BOOL GetmState(hmDev,lpdcb);
参数hmDev标识通信设备,应使用CreateFile返回的句柄。
Lpdcb是指向DCB结构的指针,函数调用后当前串口配置信息将被保存在这个结构内。
如果函数成功返回值为TRUE;否则返回值为FALSE。
SetmState用法与GetmState相似,在此不再重复。
DCB结构定义如下(只介绍主要的几项):
typedef struct_DCB{
……
DWORD BardRate; //波特率的设置
BYTE ByteSize; //数据位的个数
BYTE Parity; //是否有奇偶校验位
BYTE StopBits; //停止位的个数
……
}DCB;
(2)SetmTimeouts
BOOL SetmTimeouts(hmDev,lpctmo);
Lpctmo指向包含新的超时参数的MTIMEOUTS结构。
MTIMEOUTS结构定义如下:
typedef struct_MTIMEOUTS{
DWORD ReadIntervalTimeout;
DWORD ReadTotalTimeoutMultiplier;
DWORD ReadTotalTimeoutconstant;
DWORD WriteTotalTimeoutMultiplier;
DWORD WriteTotalTimeoutconstant;
}MTIMEOUTS,LPMTIMEOUTS;
ReadIntervalTimeout:
以毫秒为单位指定通信线上两个字符到达之间的最大时间。
在ReadFile操作其间,收到第一个字符时开始计算时间。
若任意两个字符到达之间的间隔超过这个最大值,ReadFile操作完成,返回缓冲数据。
0值表示不用间隔限时。
若该成员为MAXDWORD,且ReadTotalTimeoutconstant和ReadTotalTimeoutMultiplier成员为零,则指出读操作要立即返回已接收到的字符,即使未收到字符,读操作也要返回。
ReadTotalTimeoutMultiplier:
以毫秒为单位指定一个乘数,该乘数用来计算读操作的总限时时间。
每个读操作的总限时时间等于读操作所需的字节数与该值的乘积。
ReadTotalTimeoutConstant:
以毫秒为单位指定一个常数,用于计算读操作的总限时时间。
每个操作的总限时时间等于ReadTotalTimeoutMultiplier成员乘以读操作所需字节数再加上该值的和。
ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant成员的值为0表示读操作不使用限时时间。
WriteTotalTimeoutMultiplier和WriteTotalTimeoutconstant的意义和作用分别与ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant相似,不再重复。
(3)BuildermDCB
BOOLBuildermDCB(lpszDef,lpdcb)
这个函数按lpszDef字符串所指定的格式来配置串口的DCB。
LpszDef:
指向一个以NULL结束的字符串,该字符串指定串口的控制信息。
比如,“1200,N,8,1”指定波特率为1200,无奇偶校验位,有8个数据位和1个停止位。
lpdcb:
指向被填充的DCB结构。
(4)SetmMask
BOOLSetmMask(hmDev,fdwEvtMask);
fdwEvtMask指向一个32位的屏蔽码,如果指定为EV_RXCHAR|EV_CTS,表示程序监控串口的收、发事件。
下面以简单的例子说明串口设置的步骤:
m_mTimeouts.ReadIntervalTimeout=1000;
m_mTimeouts.ReadTotalTimeoutMultiplier=1000;
m_mTimeouts.ReadTotalTimeoutConstant=1000;
m_mTimeouts.WriteTotalTimeoutMultiplier=1000;
m_mTimeouts.WriteTotalTimeoutConstant=1000;
if(SetmTimeouts(m_hm,&m_mTimeouts))
//串口超时参数设置
if(SetmMask(m_hm,dwmEvents))
//设置串口事件掩码
if(GetmState(m_hm,&m_dcb))
//获取串口当前状态
if(BuildmDCB(“1200,N,8,1”,&m_dcb))
//建立串口设备控制块
用API函数实现串行通讯
责任编辑:
admin 更新日期:
2005-8-6
; if(SetmState(m_hm,&m_dcb));
//设置串口参数
……
以上任何一个if语句的判断条件为假时都将调用GetLastError函数获取错误信息,进行错误处理。
4、读写串口数据
Win32API函数ReadFile和WriteFile支持对串行口的读写操作。
这些函数的行为还受是否使用异步I/O(Overlapped)及通信超时设置的影响。
串行口读写的同步、异步方式是在打开端口的同时给dwGlagsAndAttributes参数传入适当的值而设定的。
在同步方式下,调用ReadFile或WriteFile后,当实际读写操作完成或发生超时时才返回调用程序。
而异步方式函数在启动接收或发送过程后立即返回,程序继续向下执行。
程序在调用ReadFile和WriteFile时必须提供一个Overlapped数据结构指针,该结构中包含一个手动的事件同步对象,其后的程序必须借助于该事件同步对象,完成数据的接收和发送过程。
通信端口的超时设置对读写的处理方式也会产生影响,如果调用读写函数时发生端口超时,则读写函数立即返回并返回已传输的数据字节数。
下面介绍主要的用于串口读写的函数:
(1)ReadFile函数的调用方法如下:
BOOLReadFile(
HANDLEhFile, //用CreateFile获得的文件句柄
LPVOIDlpBuffer, //输入缓冲区首址
DWORDnNumberOfBytesToRead,//设定读入字节数
LPDWORDlpNumberOfByteRead,//实际读入字节数
LPOVERLAPPEDlpOverlapped //重叠操作方式数据结构地址
);
(2)WriteFile函数的调用方法如下:
BOOLWriteFile(
HANDLEhFile, //用CreateFile获得的文件句柄
LPCVOIDlpBuffer, //输出缓冲区首址
DWORDnNumberOfBytesToWrite, //要求输出的字节数
LPDWORDlpNumberOfBytesWritten,//实际输出字节数
LPOVERLAPPEDlpOverlapped):
//重叠操作方式数据结构地址
(3)GetOverlappedResult函数调用方法如下:
BOOLGetOverlappedResult(
HANDLE hFile,//用CreateFile获得的文件句柄
LPOVERLAPPED lpOverlapped,
//指向一个在启动重叠操作时指定的
OVERLAPPED结构(即读写函数中指定的OverLapped结构)
LPDWORDlpNumberOfBytesTransferred,//实际传输的字节数
BOOL bWait, //是否等待悬挂的重叠操作完成,若为
//TRUE,则此函数直到操作完成后才返回。
);
OVERLAPPED结构定义如下:
typedefstruct_OVERLAPPED{
DWORDInternal;
DWORDInternalHigh;
DWORDOffset;
DWORDOffsetHigh;
HANDLEhEvent;
}OVERLAPPED;
如果采用异步方式,则在调用ReadFile或WriteFile函数时必需指定一个Overlapped结构,调用后程序可继续执行其它操作,在合适的地方再调用函数GetOverlappedResult判断异步重叠操作是否完成(判断OVERLAPPED结构中的hEvent是否被置位)。
(4)WaitmEvent函数的调用法如下:
BOOLWaitmEvent(
HANDLEhmDev, //串口句柄
LPDWORDlpfdwEvtMask, //见SetmEvent函数说明
LPOVERLAPPEDlpo, //重叠操作方式数据结构地址
);
当由SetmMask函数所指定的事件产生时这个函数将返回TRUE。
下面是一个串口读写的流程图。
串口操作流程图
5、关闭串口
如果不再使用某一端口,须将该端口关闭,以便其他程序可以使用该端口。
如果不显式关闭某端口,当程序退出时打开的端口也将被自动关闭。
但为了安全起见,最好是显式的关闭它。
关闭串口的语句为CloseHandle(hmDev);其中hmDev为用CreateFile建立的串口句柄。
6、一个完整的例子
这个串口控制类是我做的一个软件中使用的,基本用WINAPI实现,在Win95/Win98/Win2000下运行良好,可不做修改的用在其它BCB程序中。
读数据采用事件驱动方式,用一个线程处理相应事件,收到的字符用消息发往父窗口;由于我编的软件中写串口的数据不多,所以采用直接写的方式,而没用线程。
串口控制类.h.cpp
串口控制类中使用的读串口线程Thread.hThread.cpp
打包下载
这个类的使用方法如下:
1、建立串口类的实例,如:
SerialPort=newTSerialPort(); //实例化一个串口控制类
//初始化串口,Baud:
9600,DataBits:
8,StopBits:
1,无校验位
SerialPort->InitPort(this,g_iSerialPort,9600);
SerialPort->StartMonitoring(); //创建串口监控线程,开始监控
2、接收串口数据
(1)映射串口消息,在创建以上实例的窗口类的声明中加入:
void__fastcallOnRx(TMessage&Message);
//指定消息WM_M_RXCHAR(由串口监控线程发出的消息,表示接收到一个字符)的处理函数为OnRx
BEGIN_MESSAGE_MAP
MESSAGE_HANDLER(WM_M_RXCHAR,TMessage,OnRx)
END_MESSAGE_MAP(TForm)
(2)实现函数OnRx(),如:
//---------------------------------------------------------------------------
//串口消息(接收到一个字符)处理函数
//消息的参数WParam就是接收到的字符
void__fastcallTDlgProgram:
:
OnRx(TMessage&Message)
{
unsignedcharucRxData=(unsignedchar)Message.WParam; //串口监控线程收到的字符
………………
}
//---------------------------------------------------------------------------
3、向串口发送数据
调用函数boolWriteToPort(unsignedcharucTxChar)可向串口写一个字符。
如SerialPort->WriteToPort(0x55);
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- API 函数 实现 串行 通讯