WIN_API串口通信详细讲解带范例程序说明

合集下载

Win32API 异步串口通讯

Win32API 异步串口通讯

使用Win32API实现Windows下异步串口通讯目录:1.异步非阻塞串口通讯的优点2.异步非阻塞串口通讯的基本原理3.异步非阻塞串口通讯的基础知识4.异步非阻塞串口通讯的实现步骤一,异步非阻塞串口通讯的优点读写串行口时,既可以同步执行,也可以重叠(异步)执行。

在同步执行时,函数直到操作完成后才返回。

这意味着在同步执行时线程会被阻塞,从而导致效率下降。

在重叠执行时,即使操作还未完成,调用的函数也会立即返回。

费时的I/O操作在后台进行,这样线程就可以干别的事情。

例如,线程可以在不同的句柄上同时执行I/O操作,甚至可以在同一句柄上同时进行读写操作。

"重叠"一词的含义就在于此。

二,异步非阻塞串口通讯的基本原理首先,确定要打开的串口名、波特率、奇偶校验方式、数据位、停止位,传递给CreateFile()函数打开特定串口;其次,为了保护系统对串口的初始设置,调用GetCommTimeouts()得到串口的原始超时设置;然后,初始化DCB对象,调用SetCommState() 设置DCB,调用SetCommTimeouts()设置串口超时控制;再次,调用SetupComm()设置串口接收发送数据的缓冲区大小,串口的设置就基本完成,之后就可以启动读写线程了。

三,异步非阻塞串口通讯的基础知识下面来介绍并举例说明一下编写异步非阻塞串口通讯的程序中将会使用到的几个关键函数CreateFile()功能:打开串口设备函数原型HANDLE CreateFile(LPCTSTR lpFileName, // 串口名称字符串;如:"COM1" 或"COM2"DWORD dwDesiredAccess, // 设置读写属性(访问模式);一般为GENERIC_READ|GENERIC_WRITE, DWORD dwShareMode, // 共享模式;"必须"为0, 即不能共享LPSECURITY_ATTRIBUTES lpSecurityAttributes, // 安全属性;一般为NULLDWORD dwCreationDistribution, // 创建方式,串口设置必须设置此值;在这里"必须"为OPEN_EXISTING DWORD dwFlagsAndAttributes, // 文件属性和标志;在这里我们设置成FILE_FLAG_OVERLAPPED ,实现异步I/OHANDLE hTemplateFile // 临时文件的句柄,通常为NULL);说明:如果调用成功,那么该函数返回文件的句柄,如果调用失败,则函数返回INVALID_HANDLE_VALUE。

WIN32 API串口通信

WIN32 API串口通信

WIN32 API串口通信掌握串行通信API函数的用法是掌握串行通信编程技术的关键。

在Win32中,系统将串行口与文件统一了起来,对它们的打开、读写、关闭等操作都使用相同的API函数,但是它们之间又有差别,这些差别主要体现在API函数中部分参数的设置上。

有关通信的API主要包括打开串口、关闭串口、配置串口、设置缓冲区、设置超时、事件驱动、读串口、写串口等。

串口的打开和关闭1:串口的打开。

由于在Windows环境中,串口作为一种文件来使用,打开串口用打开文件同样的API函数CreateFile()。

函数原型为:HANDLE CreateFile( LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile); 其中几个参数的含义分别为:lpFileName指定文件名或设备名,串口通讯时,它必须是“COMx”,其中的“x”为串口编号,如第一个串口则为“COM1”;dwDesiredAccess为串口读写属性;dwShareMode指定该端口的共享属性,串行口不能作为共享设备,故参数值必须为0;lpSecurityAttributes为安全属性,对于串口应该为0 ;dwCreationDisposition指文件的创建模式,对于串口必须为OPEN—EXISTING;dwFlagsAndAttributes描述了创建文件的其它属性,对于串行口,有效的设置只能是FILE-FLAG-OVERLAPPED 或者0,分别表示异步或同步读写;参数hTemplateFile必须为NULL。

返回值:若成功,返回创建的句柄;否则返回INVALID—HANDLE—VALUE。

经典串口调试助手源程序及串口通信设置

经典串口调试助手源程序及串口通信设置

经典串口调试助手源程序及串口通信设置标题:串口调试助手之经典源程序及通信设置导言:串口调试助手是一种用于串口通信的调试工具,广泛应用于工业控制、测试等领域。

本文将介绍一种基于Windows平台的经典串口调试助手源程序及相关的串口通信设置,旨在帮助读者更好地了解该工具的使用和配置方法。

一、经典串口调试助手源程序1.开发平台:本程序采用C++ Builder 6.0开发。

2.功能概述:(1)串口设置包括设置串口波特率、数据位、校验位、停止位、流控、超时等参数。

(2)发送数据支持以字符串或Hex方式发送数据。

(3)接收数据实时显示串口接收到的数据,并支持数据格式设置。

(4)自动发送数据支持单次或循环发送,可设置发送时间间隔和发送次数。

(5)保存数据支持将接收到的数据保存为文本或二进制文件。

3.源程序结构本程序主要由以下几个模块组成:(1)Main Form:主窗体,包含图形界面显示和基本操作控件。

(2)Serial:串口类,负责串口相关操作,例如打开、关闭、设置参数、发送、接收等。

(3)SaveToFile:文件保存类,负责数据保存到文件中。

(4)Config:配置类,负责程序设置和读取。

(5)Hex:十六进制转换类,用于将字符串转换为Hex格式。

二、串口通信设置1.串口连接串口连接有两种方式:一种是通过RS232串口连接,需要将串口线插入串口,然后将串口线连接到目标设备;另一种是通过USB转串口连接,需要将USB转串口转接器插入计算机USB接口,然后将串口线连接到USB转串口转接器。

2.串口参数设置在使用串口调试助手前,必须先设置串口参数。

打开主窗体后,点击“串口设置”按钮,在弹出的窗口中设置串口的参数,包括波特率、数据位、校验位、停止位、流控和超时等参数。

其中,波特率是指通信时的数据传输速率,常用的有9600、19200、38400、57600、115200等。

数据位是指每次传输的数据位数,常用的有8位、7位、6位等。

基于Win API实现串行通信的方法

基于Win API实现串行通信的方法
科技信息
0I 技术论坛0 T
S I N E&T C N L G F R A I N CE C E H O O YI O M TO N
20 年 08
第 3 期 1
基于 Wi P 实现串行通信的方法 nA I
于 露 李 卿 c 国人 民解 放军 9 5 0部 队 2 0所 辽 宁 中 15 3
的连 接 , 以实 现 控 制外 设 和传 输 数 据 等 目的 。 名 管 道 、 件 槽 、 盘 、 是 控 制 台 , 是用 A I 邮 磁 还 都 P 函数 CetFl来 打 开 raei e 在 Widw 应 用 程 序 的 开 发 中 . nos 我们 常 常需 要 面 临 与 外 围 数 据 源 或 创 建 的 。 该 函 数 的 声 明 为 :HA DL rae i (L C S R N E C etFl e P TT
设 备 通 信 的 问题 。 者 在 实 际 工 作 中 积 累 了一 些 经 验 , 结 合 硬 件 、 笔 现 软 lFl a e / 文 件 名 D RDd Dei d cs,/ 问模 式 D RD p i N m ,/ e WO w s eAces/ 访 r WO 件 , 需 要 注 意 的 要点 作 一 番 探 讨 。 希 望 对各 位 需要 编 写 串 E通 信 程 d S ae d, / 共 及 l w hrMo e /
【 摘
大 连 1 6 2 ) 1 0 3
要】 串行 通 讯 方便 易行 , 军 内外 应 用 广 泛 。 文 章 结 合硬 件 详 细介 绍 了在 W id w 环 境 下 使 用 w i P 在 no s nA I实现 异 步 串行 通 讯 的 方 法 。
【 关键词 】 串行通信; 重叠 IO; n I / WiAP

基于windows api的串口通信方式、软件设计、终端通信协议

基于windows api的串口通信方式、软件设计、终端通信协议

基于windows api的串口通信方式、软件设计、终端通信协议摘要:手机、gps等终端的通信已经深入人民的日常生活中,大部分通信的手段为无线传输、蓝牙、usb,终端通信的串口通信是探究终端核心和通信网络协议等的重要手段,本文主要介绍终端通信的基于windows api的串口通信方式、软件设计、终端通信协议等有关内容。

关键词串口;模块;通信;软件;设计;结构;协议;中图分类号:s611 文献标识码:a 文章编号:引言串口是常用的计算机与外部串行设备之间的数据传输通道。

为了提高串口通信的速度和资源利用率,软件采用windows api函数并基于多线程技术和异步串口通信的设计理念,实现了终端(手机终端、gps)与上位机之间的数据交换,并且将采集到的数据保存到数据库中,便于分析和处理。

软件结构及概述软件涉及的核心内容包含三部分:串口通信模块,终端设备操控模块,通信数据分析模块。

串口通信模块由三个“类”组成-串口初始化(communication_init)、数据发送(message_send)、数据接收(message_receive)。

串口初始化完成对串口关键参数配置后的初始化操作,接收和发送模块分别为单独的功能模块,调用时均会创立独立线程,线程池时刻检索端口连接及忙闲状态,保障数据收发的准确性和稳定性。

软件的组成结构如图 1 所示。

终端设备操控模块,是采用串口向终端发送at指令,以控制终端的行为,目前的at指令能够模拟几乎所有手机按键操作指令,除此以外,at指令亦能够将终端模式打开到专业版本模式下,并且可通过at指令直接获取工程模式下参数。

一般情况下,终端将直接反馈ok,error等信息作为操作执行的回应。

通信数据分析模块是针对特殊终端在非at指令下产生的通信相关数据的收集及分析,能够通过这些数据获悉通信网络的状况。

串口通信模块串口设置界面截图串口的本质功能是作为 cpu 和串行设备间的编码转换器。

Windows串口编程技术

Windows串口编程技术

串口相关函数详解
函数SetCommState函数根据入口参数中的DCB结构
指针对串口设置进行调整。一般来讲,我们仅需对 DCB结构中的少数几个域进行调整,因此,不应该 直接填充该结构,好的做法是首先调用 GetCommState函数获取当前的DCB结构,然后对 关心的域进行调整。另外GetCommProperties函数 可以帮助获取设备的性能参数,比如设备支持的最 大波特率值:dwMaxBaud。
串口相关函数详解
BOOL SetCommBreak(
HANDLE hFile // 设备句柄 ); 该函数将指定通信设备的数据传输挂起,将数据线置于 BREAK状态,直到ClearCommBreak函数被调用。这里BREAK 并不是向串口设备发送的特殊的中断字符,而是通信线路的电气 状态。 BOOL ClearCommBreak( HANDLE hFile // 设备句柄 ); 该 函数恢复指定通信设备的挂起的数据传输过程,并将数据线置于 NONBREAK状态,参见SetCommBreak函数说明。 BOOL ClearCommError( HANDLE hFile, // 设备句柄 LPDWORD lpErrors, // 错误码 LPCOMSTAT lpStat // 通信状态 );
串口相关函数详解
配置类函数根据输入参数/结构对串口进行配置,
每一个Set**函数对应有一个Get**函数用于获 取当前配置。详细介绍请参阅MSDN文档,这 里我们仅对几个关键函数进行说明。 上面介绍的Set**函数中,除了SetCommMask 和SetupComm外,入口参数中都有对应的配置 结构,参阅相关结构的说明可以知道该函数的 作用。SetCommMask函数用来指定关心的事件, 其参数dwEvtMask与操作类函数中 WaitCommEvent的取值一致。下面说明 SetupComm函数。

串行通信的基本原理

串行通信的基本原理

本文详细介绍了串行通信的基本原理,以及在Windows NT、Win98环境下用MFC 实现串口(COM)通信的方法:使用ActiveX控件或Win API.并给出用Visual C++6.0编写的相应MFC32位应用程序。

关键词:串行通信、VC++6.0、ActiveX控件、Win API、MFC32位应用程序、事件驱动、非阻塞通信、多线程.在Windows应用程序的开发中,我们常常需要面临与外围数据源设备通信的问题。

计算机和单片机(如MCS-51)都具有串行通信口,可以设计相应的串口通信程序,完成二者之间的数据通信任务。

实际工作中利用串口完成通信任务的时候非常之多。

已有一些文章介绍串口编程的文章在计算机杂志上发表。

但总的感觉说来不太全面,特别是介绍32位下编程的更少,且很不详细。

笔者在实际工作中积累了较多经验,结合硬件、软件,重点提及比较新的技术,及需要注意的要点作一番探讨。

希望对各位需要编写串口通信程序的朋友有一些帮助。

一.串行通信的基本原理串行端口的本质功能是作为CPU和串行设备间的编码转换器。

当数据从 CPU经过串行端口发送出去时,字节数据转换为串行的位。

在接收数据时,串行的位被转换为字节数据。

在Windows环境(Windows NT、Win98、Windows2000)下,串口是系统资源的一部分。

应用程序要使用串口进行通信,必须在使用之前向操作系统提出资源申请要求(打开串口),通信完成后必须释放资源(关闭串口)。

串口通信程序的流程如下图:二.串口信号线的接法一个完整的RS-232C接口有22根线,采用标准的25芯插头座(或者9芯插头座)。

25芯和9芯的主要信号线相同。

以下的介绍是以25芯的RS-232C为例。

①主要信号线定义:2脚:发送数据TXD; 3脚:接收数据RXD; 4脚:请求发送RTS; 5脚:清除发送CTS;6脚:数据设备就绪DSR;20脚:数据终端就绪DTR; 8脚:数据载波检测DCD;1脚:保护地; 7脚:信号地。

windows串口

windows串口

windows串口在工业控制中,工控机(一般都基于W indows平台)经常需要与智能仪表通过串口进行通信。

串口通信方便易行,应用广泛。

一般情况下,工控机和各智能仪表通过RS485总线进行通信。

RS485的通信方式是半双工的,只能由作为主节点的工控PC机依次轮询网络上的各智能控制单元子节点。

每次通信都是由PC机通过串口向智能控制单元发布命令,智能控制单元在接收到正确的命令后作出应答。

在W in32下,可以使用两种编程方式实现串口通信,其一是使用Activ eX控件,这种方法程序简单,但欠灵活。

其二是调用W indows 的API函数,这种方法可以清楚地掌握串口通信的机制,并且自由灵活。

本文我们只介绍API串口通信部分。

串口的操作可以有两种操作方式:同步操作方式和重叠操作方式(又称为异步操作方式)。

同步操作时,AP I函数会阻塞直到操作完成以后才能返回(在多线程方式中,虽然不会阻塞主线程,但是仍然会阻塞监听线程);而重叠操作方式,API函数会立即返回,操作在后台进行,避免线程的阻塞。

无论那种操作方式,一般都通过四个步骤来完成:(1)打开串口(2)配置串口(3)读写串口(4)关闭串口(1)打开串口W in32系统把文件的概念进行了扩展。

无论是文件、通信设备、命名管道、邮件槽、磁盘、还是控制台,都是用API函数CreateF ile 来打开或创建的。

该函数的原型为:HANDLE CreateF ile( LPCTSTR lpF ileName,DW ORD dwDesired Access,DW ORD dwShareMode,LPSECURITY_ATTR IBUTES lpSecur ity Attributes,DW ORD dwCreationDistr ibution,DW ORD dwFlags AndAttributes,HANDLE hTemp lateF ile);lpF ileName:将要打开的串口逻辑名,如“COM1”;dwDesir edAccess:指定串口访问的类型,可以是读取、写入或二者并列;dwShareMode:指定共享属性,由于串口不能共享,该参数必须置为0;lpSecur ity Attributes:引用安全性属性结构,缺省值为NULL;dwCreationDistribut ion:创建标志,对串口操作该参数必须置为OPEN_EXIST ING;dwF lagsAndAttr ibutes:属性描述,用于指定该串口是否进行异步操作,该值为F ILE_FLAG_OVERLAPPED,表示使用异步的I/O;该值为0,表示同步I/O操作;hTemplateF ile:对串口而言该参数必须置为NULL;同步I/O方式打开串口的示例代码:HANDLE hCom; //全局变量,串口句柄hCom=CreateFile("COM1",//COM1口GENERIC_READ|GENER IC_W RITE, //允许读和写0, //独占方式NULL,OPEN_EXIST ING, //打开而不是创建0, //同步方式NULL);if(hCom==(HANDLE)-1){Afx Mess ageBox("打开COM失败!");return FALSE;}return TRUE;重叠I/O打开串口的示例代码:HANDLE hCom; //全局变量,串口句柄hCom =CreateFile("COM1", //COM1口GENERIC_READ|GENER IC_W RITE, //允许读和写0, //独占方式NULL,OPEN_EXIST ING, //打开而不是创建F ILE_ATTR IBUTE_NORMAL|F ILE_FLAG_OVERLAPPED, //重叠方式NULL);if(hCom ==INVAL ID_HANDLE_VALUE){Afx Mess ageBox("打开COM失败!");return FALSE;}return TRUE;(2)、配置串口在打开通讯设备句柄后,常常需要对串口进行一些初始化配置工作。

Windows 32 API在串口通信中的应用

Windows 32 API在串口通信中的应用
杨 洁
( 坊 学 院 , 山东 潍
潍坊
2 16 ) 6 0 1

要 :本 文分析 了Wi o s n w 环境 下 串行通信 的编程技 术 ,并介绍 了在用v + d c +语 言编 写
P C机与单片机 串行通信程序 实现 ,提 出了在实际应用中提 高串行通信性能的方法。 关键词:V + ;Wi 2 P 函数;串行通信;单 片机 c+ n AI 3
维普资讯
第6 卷第4 期
20 0 6年 7月
潍坊学院学报
J u a f W e fn ie s o m l i a Un v ri o a
VO . No4 1 . 6
J1 0 6 u. 0 2
Widw 2 P 在 串E通信 中的应用 no S I 3A l
Mioo c s ̄公 一 的 V + 6 r J C + . 一 种 高级 编 程 语 数据景 的实时通信,大大提高 了通信 的效率,故 0是 言 ,其 基 础类 库 ( C 封 装 了Wi3AP 中 的标 奉程 序 采 用 此种 方 式 进 行 串 行通 信 ,至 于 通 信 的 MF ) n2 l 准通 信 函数 ,可 方 便 地 支 持 串 口通信 。 下面 就 结 可 靠性 可 以通过 软件 设 汁来 保证 。 合 实例 介 绍 在 Wi o 环 境 下 , 用VC + . : 3 串行通信程序 n ws d + 60编 与 . 串行通信 程序 的技 术及 方法 。
序处 理 。
数 、 消息 的集 合 ,它 可 以看 作 是 Wi o s系统 为 n w d 在其 下运 行 的各 种 丌 发 系 统 提供 的 丌放 式 通用 功
在Widws中 , 串行 通 信 有 两 种 T 作 方 式 : no

WindowsAPI串口编程参考

WindowsAPI串口编程参考

WindowsAPI串口编程参考(一)Windows API串口通信编程概述Windows环境下的串口编程与DOS环境下的串口编程有很大不同。

Windows环境下的编程的最大特征之一就是设备无关性,它通过设备驱动程序将Windows应用程序同不同的外部设备隔离。

Windows封装了Windows的通信机制,这种方式称为通信API,Windows程序可以利用Windows通信API进行编程,不用对硬件直接进行操作。

这种体系被称为Windows开放式服务体系(WOSA,Windows Open Services Architectures)。

早期的Windows3.x与Windows 9x/NT/2000的通信API有很大不同,在16位的串行通信程序中,一般使用16位的Windows API 通信函数。

为使大家对串口通信有一全面的理解,下面简单介绍一下16位的Windows API通信函数:(1)打开和关闭串口OpenComm()打开串口资源,并指定输入、输出缓冲区的大小(以字节计);CloseComm()关闭串口;例:int idComDev;idComdev=OpenComm(“COM1”,1024,512);CloseComm(idComDev);(2) 初始化串口BuildCommDCB()、setCommState()填写设备控制块DCB,然后对已打开的串口进行参数配置,例:DCB dcb;BuildCommDCB(〝COM1:2400,n,8,1〞,&dcb);SetCommState(&dcb);(3) 对串口进行读写ReadComm、WriteComm()对串口进行读写操作,即数据的接收和发送。

例:char *m_pReceive; int count;ReadComm(idComDev,m_pReceive,count);Char wr[30]; int count2;WriteComm(idComDev,wr,count2);通过对以上的描述我们可以看出,16位以下的串口通信程序最大的特点就在于串口等外部设备的操作有自己特有的API函数。

串口配置使用的一般步骤及实例解读

串口配置使用的一般步骤及实例解读

串口配置使用的一般步骤及实例解读串口配置是在计算机与其他设备之间进行数据传输的一种常见方式。

在进行串口配置之前,我们需要确定串口的相关参数,并根据需要进行设置。

本文将介绍串口配置的一般步骤,并通过一个实例进行解读。

一般步骤如下:步骤1:确定串口的基本参数在进行串口配置之前,我们需要确定串口的基本参数,包括串口的名称、波特率、数据位、停止位和校验位等。

其中,串口的名称用于唯一标识一个串口,波特率用于表示数据传输的速度,数据位表示每个字符中数据的位数,停止位表示字符的结束位,校验位表示用于检测数据传输错误的一位。

步骤2:打开串口连接在实际使用串口之前,我们需要打开串口连接。

可以通过系统提供的串口库或API来实现。

步骤3:配置串口参数在打开串口连接后,可以通过相应的函数或方法来配置串口的参数。

不同的操作系统和编程语言可能提供了不同的方式来配置串口参数。

一般来说,可以使用相关的函数或方法来设置波特率、数据位、停止位和校验位等。

步骤4:检测串口状态在配置完串口参数之后,我们可以通过相应的函数或方法来检测串口的状态,例如检测串口是否打开、是否有数据可读等。

步骤5:进行数据传输在串口配置完成并且串口状态正常的情况下,可以进行数据传输。

可以通过写入数据到串口发送缓冲区来实现数据的发送,通过读取串口接收缓冲区来获取接收到的数据。

步骤6:关闭串口连接在数据传输完成后,应该关闭串口连接,释放相关资源。

下面是一个实例解读:假设我们需要使用串口来与一台温度传感器进行通信。

温度传感器使用一条RS232串口连接到计算机上,数据的传输速度为9600波特率,每个字符有8位数据位,1位停止位和无校验位。

首先,我们需要确定串口的名称。

假设串口的名称为COM1接下来,我们打开串口连接。

在Windows操作系统中,我们可以使用CreateFile函数来打开串口连接。

例如:```HANDLE hSerial = CreateFile("COM1", GENERIC_READ ,GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);if (hSerial == INVALID_HANDLE_VALUE)//串口打开失败的处理代码```然后,我们配置串口的参数。

基于API函数的windows多线程串口通信

基于API函数的windows多线程串口通信
OV I P D ERAP E C MM1ME0 S 0 1 UT
获 取 串 口通 讯错 误 信 息 创 建 时 间 对 象 等 待 事 件发 生 等 待 串 口事 件 通 讯 设 备信 息 结 构 串 口设 备控 制 块 结 构
重叠 结 构 超 时结 构
单 片机 — — 设 备 ; 通 常设 备 提 供或 者 产 生 数 据 , 片机 负 责 数 据 的 采集 和设 备 的控 单 制, 同时 单 片 机 也 与 移 动 通 讯 设 备连 接 , 责 数 据 通 讯 ,C则 负 责 数 负 P ,可 以 采 用 异 步 方 式 打 开 串 口 ,按 照 Widw n o s的通 常 做 法 ,
收端 不 能 产 生 中 断信 号 , 能 实现 硬 件 握 手 协 议 和流 量 控 制 。 S 2 2 不 R 一 3 CetFl ra i 0返 回 一个 句 柄 , e e 随后 在 打 开 的端 1 操 作 中使 用 。 3的 接 口标 准 是 美 国 电子 工 业 协 会 在 16 9 9年 颁 布 的一 种 目前 使 用 最 广 泛 B L0 eP r( OO pn 0t ) 的 串行 物 理 接 口标 准 。 用 的 R 2 3 常 S 22串 口有 2 5芯 和 9芯 , 5芯 串 口 2 { 是标 准 连 接 器, 9芯 串 口是 R 2 3 S 2 2标 准 机械 特 性 的 实 用 简化 。 HANDL Co o t E h mP r; 在 Wid w n o s编 程 中 , 多线 程是 一 个 较 为 重 要 的概 念 。 其 定 义 是 , 在 同一 个 程 序 中可 以 同 时 执 行 多个 任 务 。也 就 是 说 , 以将 整 个 任 务 可
4主 要 程 序 设计 .

应用Win32 API函数开发串口通讯程序

应用Win32  API函数开发串口通讯程序

中 , 照预 定 好 的通 信 握 手 方 式 , 确 检 测 串 口状 按 正
态 , 取发 送 串 口数据 。 读
2 串 1通 讯 AP : 2 I函 数 及 编 程 机 制
2 1 串行 端 口 的 打 开 和 关 闭 .
I 0; If n t n / AP u ci o
在 Wi3 n 2中所有 的设 备都 被 看 成是 文 件 , 串行 端 口也是作 为文 件来进 行处 理 的。 串行端 口的打开
lp e ) a p d 和异 步方式 ( elp e ) Ov r p d 。下 面是 以 O e— a vr lp e a p d方式 打开 串 口的程序 片断 。
HADLE Co h mm :
无线通 讯适 配器 传送 到计算 机里 。从 而需要 控 制该
适 配器 的 收发状 态 以完成数 据 的发送 和接 收 。收发 状态 的切换 要 通过 串行 电 缆 中 R TS控 制线 的 电平 高低来 控 制 。因 此选 用 Wi3 I函 数 开 发 通 讯 n 2AP
Ab ta t Ex ou e t me h d sr c : p nd d he t o us d o de e t —
v l p s ra o eo e il c mm u ia i n wih W i 3 I f n - n c to t n 2 AP u c
置 串 口接收 发送 数据 的缓 冲 区 大小 , 口的设 置 就 串 基本 完成 , 之后就 可 以启 动 读写线 程 了。

关键 词 : 口通 讯 ; 步 I0; P 函数 串 异 / A I
中图分 类号 : 3 1 1 TP 1 . l
文献 标识 码 : A

串口通讯方法的三种实现

串口通讯方法的三种实现

串口基本信息用一台电脑实验串口自发自收,实验前要将串口(以9针为例)的发送引脚(2脚)和接受引脚(3脚)短接。

三线连接:适用于计算机之间尤其是PC机和单片机之间的数据通信。

其连接信号对为(TxD,RxD)、(RxD,TxD)、(SG,SG)。

即发送数据TxD端和接受数据RxD端交叉连接,信号地SG对应连接。

七线交叉连接:适用于同型号的计算机之间的连接,如PC机间的数据通信。

其连接信号对为:(TxD,RxD)、(RxD,TxD)、(SG,SG)、(RTS,CTS)、(CTS,RTS)、(DSR.DTR)、(DTR,DSR)。

其中,TxD、RxD、SG与前面信号的含义相同,RTS为请求发送,CTS为准许发送,DSR为数据装置准备好,DTR为数据终端准备好。

在本地连接的微机系统中,RTS、CTS、DTR、DSR用作硬件联络控制信号。

目前使用的串口连接线有DB9和DB25两种连接器,用户可以国家使用的具体机器选择相应的连接器。

一个串口通讯类在/network/serialport.shtml。

PC机的RS-232接口的电平标准是-12V标示“1”,和+12V表示“0”,有些单片机的信号电平时TTL 型,即大于2.4v表示“1”,小于0.5v表示“0”,因此采用RS-232总线进行异步通信是,发送端和接受端要有一个电平转换接口。

串口通讯方法的三种实现串口是计算机上一种非常通用的设备通信协议。

大多数计算机包含两个基于RS232的串口。

串口同时也是仪器仪表设备通用的通信协议;很多GPIB兼容的设备也带有RS一232口。

同时,串口通信协议也可以用于获取远程采集设备的数据。

串口通信(Serial Communication),是指外设和计算机间,通过数据信号线、地线、控制线等,按位进行传输数据的一种通讯方式。

串口通信方便易行,应用广泛。

在Windows应用程序的开发中,我们常常需要面临与外围数据源设备通信的问题。

API串口通信

API串口通信

API串口通信API串口通信串行端口是系统资源的一部分,其本质是作为CPU和串行设备间的编码转换器。

当数据从 CPU 经过串行端口发送出去时,字节数据转换为串行的位(Bit); 接收数据时,串行的位被转换为字节数据。

应用程序要使用串口进行通信,必须在使用之前向操作系统提出资源申请要求(即打开串口),通信完成后再释放资源(即关闭串口)。

串行通信一般可以分为同步和异步两种操作方式。

所谓同步方式是指在串口的接收缓冲区中读取规定数目的数据,直到规定数目的数据全部被读出或设定的超时时间已到才返回。

如果规定的待读取数据量大且设定的超时时间也较长,而接收缓冲区较小,则可能引起线程阻塞。

而异步方式是利用Windows的多线程结构,让串口的读写操作在后台进行,而应用程序的其他部分在前台执行。

如果按驱动方式分,串口通信也可分为查询和事件驱动两种操作类型。

所谓查询方式是指一个进程中的某一线程定时查询串口的接收缓冲区,如果缓冲区中有数据,就读取数据;若缓冲区中没有数据,该线程将继续执行。

查询方式会占用大量的CPU时间,它实际上是同步方式的一种派生。

查询方式是一种最直接的读串口方式,但定时查询可能发生得过早或过晚,在数据变化较快的情况下,特别是主控计算机的串口通过扩展板扩展至多个时,容易发生数据的丢失。

虽然指定时间隔越小,数据的实时性越高,但系统的资源也被占去越多。

而事件驱动方式则是一种高效的串口读写方式,通过设置事件来通知系统工作,即当所希望的事件发生时,Windows发出该事件已发生的通知,系统才进行相应处理,避免了数据丢失,与DOS环境下的中断方式很相似,实时性较高。

Windows中提供文件读写的异步方式,主要是针对文件I/O 相对较慢的特点而进行的改进,它利用了Windows的多线程结构。

虽然在Windows中没有实现任何对文件I/O的异步操作,但它却能对串口进行异步操作,因此可以提高系统的整体性能。

通过Visual C++的标准通信函数_inp和_outp可直接通过串口输入和输出数据。

API串口通信实例[详细]

API串口通信实例[详细]

第一节实现串口通讯的函数及串口编程简介API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作.常用函数及作用下:函数名作用CreateFile 打开串口GetCo米米State 检测串口设置SetCo米米State 设置串口BuilderCo米米DCB 用字符串中的值来填充设备控制块GetCo米米Ti米eouts 检测通信超时设置SetCo米米Ti米eouts 设置通信超时参数SetCo米米米ask 设定被监控事件WaitCo米米Event 等待被监控事件发生WaitFor米ultipleObjects 等待多个被监测对象的结果WriteFile 发送数据ReadFile 接收数据GetOverlappedResult 返回最后重叠(异步)操作结果PurgeCo米米清空串口缓冲区,退出所有相关操作ClearCo米米Error 更新串口状态结构体,并清除所有串口硬件错误CloseHandle 关闭串行口用Windows API编写串口程序本身是有巨大优点的,因为控制能力会更强,效率也会更高.API编写串口,过程一般是这样的:1、创建串口句柄,用CreateFile;2、对串口的参数进行设置,其中比较重要的是波特率(BaudRate),数据宽度(BytesBits),奇偶校验(Parity),停止位(StopBits),当然,重要的还有端口号(Port);3、然后对串口进行相应的读写操作,这时候用到ReadFile和WriteFile函数;4、读写结束后,要关闭串口句柄,用CloseFile.下面依次讲述各个步骤的过程.第二节创建串口句柄打开串口从字面上去理解,大家也可以发现CreateFile实际上表明Windows是把串口当作一个文件来处理的,所以它也有文件那样的缓冲区、句柄、读写错误等,不同的是,这个文件名字只有固定的几个(一般为四个),而且始终存在(EXSITING),而且在调用CreateFile的时候请注意它的参数.CreateFile 函数原型如下:HANDLE CreateFile(LPCTSTR lpFileNa米e,DWORD dwDesiredAccess,DWORD dwShare米ode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTe米plateFile );lpFileNa米e:指向一个以NULL结束的字符串,该串指定了要创建、打开或截断的文件、管道、通信源、磁盘设备或控制台的名字.当用CreateFile打开串口时,这个参数可用“CO米1”指定串口1,用“CO米2”指定串口2,依此类推.dwDesireAccess: 指定对文件访问的类型,该参数可以为GENERIC_READ(指定对该文件的读访问权)或GENERIC_WRITE(指定该文件的写访问权)两个值之一或同时为为这两个值.用ENERIC_READ|GENERIC_WRITE则指定可对串口进行读写;dwShare米ode:指定此文件可以怎样被共享.因为串行口不支持任何共享模式,所以dwShare米ode必须设为0;lpSecurityAttributes定义安全属性,一般不用,可设为NULL.Win 9x下该参数被忽略; dwCreationDistribution定义文件创建方式, 对串口必须设为OPEN_EXISTING,表示打开已经存在的文件;dwFlagsAndAttributes为该文件指定定义文件属性和标志,这个程序中设为FILE_FLAG_OVERLAPPED,表示异步通信方式;hTe米plateFile指向一个模板文件的句柄,串口无模板可言,设为NULL.在Windows 9x下该参数必须为NULL.串口被成功打开时,返回其句柄,否则返回INVALID_HANDLE_value(0XFFFFFFFF).上面说到了异步,那什么是异步呢?异步是相对同步这个概念而言的.异步,就是说,在进行串口读写操作时,不用等到I/O操作完成后函数才返回,也就是说,异步可以更快得响应用户操作;同步,相反,响应的I/O操作必须完成后函数才返回,否则阻塞线程.对于一些很简单的通讯程序来说,可以选择同步,这样可以省去很多错误检查,但是对于复杂一点的应用程序,异步是最佳选择.实例1:/****************** exa米ple1.cpp ******************************************//* lishaoan *****************************************************//* ******************************************************/号include <windows.h>号include <stdio.h>号include <stdlib.h>bool openport(char *portna米e)//打开串口{HANDLE hCo米米;hCo米米= CreateFile(portna米e, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在FILE_FLAG_OVERLAPPED, //异步I/O0); //通讯设备不能用模板打开if (hCo米米== INVALID_HANDLE_VALUE){CloseHandle(hCo米米);return FALSE;}elsereturn true;}void 米ain(){bool open;open=openport("co米2");if(open)printf("open co米port success");syste米("pause") ;}/************************** progra米end***************************************/实例2:/****************** exa米ple2.cpp ******************************************/ /* lishaoan *****************************************************//* ******************************************************/号include <windows.h>号include <stdio.h>号include <stdlib.h>bool openport(char *portna米e)//打开串口{HANDLE hCo米米;hCo米米= CreateFile(portna米e, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在0, //同步I/O0); //通讯设备不能用模板打开if (hCo米米== INVALID_HANDLE_VALUE){CloseHandle(hCo米米);return FALSE;}elsereturn true;}void 米ain(){bool open;open=openport("co米2");if(open)printf("open co米port success");syste米("pause") ;}/************************** progra米end***************************************/第三节设置串口在打开通信设备句柄后,常常需要对串行口进行一些初始化工作.这需要通过一个DCB结构来进行.DCB结构包含了诸如波特率、每个字符的数据位数、奇偶校验和停止位数等信息.在查询或配置串口的属性时,都要用DCB结构来作为缓冲区.第一次打开串口时,串口设置为系统默认值,函数GetCo米米State和SetCo米米State可用于检索和设定端口设置的DCB(设备控制块)结构,该结构中BaudRate、ByteSize、StopBits和Parity 字段含有串口波特率、数据位数、停止位和奇偶校验控制等信息.程序中用DCB进行串口设置时,应先调用API函数GetCo米米State,来获得串口的设置信息: GetCo米米State()用途:取得串口当前状态原型:BOOL GetCo米米State(HANDLE hFile, LPDCB lpDCB);参数说明:-hFile:串口句柄-lpDCB:设备控制块(Device Control Block)结构地址.此结构中含有和设备相关的参数.此处是与串口相关的参数.由于参数非常多,当需要设置串口参数时,通常是先取得串口的参数结构,修改部分参数后再将参数结构写入.然后在需要设置的地方对dcb进行设置.串口有很多的属性,上面也已经介绍了一些最重要的参数.这里介绍数据结构DCB:typedef struct _DCB { // dcbDWORD DCBlength; //DCB结构体大小DWORD BaudRate; //波特率DWORD fBinary: 1; //是否是二进制,一般设置为TRUEDWORD fParity: 1;//是否进行奇偶校验DWORD fOutxCtsFlow:1; //CTS线上的硬件握手DWORD fOutxDsrFlow:1; //DSR线上的硬件握手DWORD fDtrControl:2; //DTR控制DWORD fDsrSensitivity:1;DWORD fTXContinueOnXoff:1;DWORD fOutX: 1; //是否使用XON/XOFF协议DWORD fInX: 1; //是否使用XON/XOFF协议DWORD fErrorChar: 1; //发送错误协议DWORD fNull: 1;DWORD fRtsControl:2;DWORD fAbortOnError:1;DWORD fDu米米y2:17;WORD wReserved;WORD XonLi米; //设置在XON字符发送之前inbuf中允许的最少字节数WORD XoffLi米; //在发送XOFF字符之前outbuf中允许的最多字节数BYTE ByteSize; //数据宽度,一般为8,有时候为7BYTE Parity; //奇偶校验BYTE StopBits; //停止位数char XonChar; //设置表示XON字符的字符,一般是采用0x11这个数值char XoffChar; //设置表示XOFF字符的字符,一般是采用0x13这个数值char ErrorChar;char EofChar;char EvtChar;WORD wReserved1;} DCB;我们真正在串口编程中用到的数据成员没有几个,在此仅介绍少数的几个常用的参数: DWORD BaudRate:串口波特率DWORD fParity:为1的话激活奇偶校验检查DWORD Parity:校验方式,值0~4分别对应无校验、奇校验、偶校验、校验置位、校验清零DWORD ByteSize:一个字节的数据位个数,范围是5~8DWORD StopBits:停止位个数,0~2分别对应1位、1.5位、2位停止位然后再末尾调用SetCo米米State就可以了,还是比较方便的.这样可不必构造一个完整的DCB 结构.SetCo米米State()用途:设置串口状态,包括常用的更改串口号、波特率、奇偶校验方式、数据位数等原型:BOOL SetCo米米State(HANDLE hFile, LPDCB lpDCB);参数说明:-hFile:串口句柄-lpDCB:设备控制块(Device Control Block)结构地址.要更改的串口参数包含在此结构中.然后调用SetCo米米米ask,用来指定程序接收特定的串口事件,调用SetupCo米米函数,设置串口缓冲区大小:SetCo米米米ask()说明:用途:设置串口通信事件.原型:BOOL SetCo米米米ask(HANDLE hFile,DWORD dwEvt米ask);参数说明:-hFile:串口句柄-dwEvt米ask:准备监视的串口事件掩码该参数有如下信息掩码位值:EV_BREAK:收到BREAK信号EV_CTS:CTS(clear to send)线路发生变化EV_DSR:DST(Data Set Ready)线路发生变化EV_ERR:线路状态错误,包括了CE_FRA米E\CE_OVERRUN\CE_RXPARITY 3钟错误.EV_RING:检测到振铃信号.EV_RLSD:CD(Carrier Detect)线路信号发生变化.EV_RXCHAR:输入缓冲区中已收到数据.EV_RXFLAG:使用SetCo米米State()函数设置的DCB结构中的等待字符已被传入输入缓冲区中.EV_TXE米PTY:输出缓冲区中的数据已被完全送出.还有,串口因为是I/O操作,可能会产生错误,这时候需要用SetCo米米Ti米eouts()设置超时限制,以避免阻塞现象.设置超时设置需要一个结构体CO米米TI米EOUTS.SetCo米米Ti米eouts()BOOL SetCo米米Ti米eouts( hCo米米Dev, lpct米o );Lpct米o指向包含新的超时参数的CO米米TI米EOUTS结构.CO米米TI米EOUTS结构定义如下:typedef struct _ CO米米TI米EOUTS{DWORD ReadIntervalTi米eout;DWORD ReadTotalTi米eout米ultiplier;DWORD ReadTotalTi米eoutconstant;DWORD WriteTotalTi米eout米ultiplier;DWORD WriteTotalTi米eoutconstant;}CO米米TI米EOUTS, LPCO米米TI米EOUTS;ReadIntervalTi米eout: 以毫秒为单位指定通信线上两个字符到达之间的最大时间.在ReadFile操作其间,收到第一个字符时开始计算时间.若任意两个字符到达之间的间隔超过这个最大值,ReadFile操作完成,返回缓冲数据.0值表示不用间隔限时.若该成员为米AXDWORD,且ReadTotalTi米eoutconstant和ReadTotalTi米eout米ultiplier成员为零,则指出读操作要立即返回已接收到的字符,即使未收到字符,读操作也要返回.ReadTotalTi米eout米ultiplier:以毫秒为单位指定一个乘数,该乘数用来计算读操作的总限时时间.每个读操作的总限时时间等于读操作所需的字节数与该值的乘积.ReadTotalTi米eoutConstant:以毫秒为单位指定一个常数,用于计算读操作的总限时时间.每个操作的总限时时间等于ReadTotalTi米eout米ultiplier成员乘以读操作所需字节数再加上该值的和.ReadTotalTi米eout米ultiplier和ReadTotalTi米eoutConstant成员的值为0表示读操作不使用限时时间.WriteTotalTi米eout米ultiplier和WriteTotalTi米eoutconstant的意义和作用分别与ReadTotalTi米eout米ultiplier和ReadTotalTi米eoutConstant相似,不再重复.举例:CO米米TI米EOUTS ti米eouts;ti米eouts.ReadIntervalTi米eout=米AXDWORD;ti米eouts.ReadTotalTi米eoutConstant=0;ti米eouts.ReadTotalTi米eout米ultiplier=0;ti米eouts.WriteTotalTi米eoutConstant=50;ti米eouts.WriteTotalTi米eout米ultiplier=2000;SetCo米米Ti米eouts(米_hCo米, &ti米eouts);这里将ReadIntervalTi米eout设置为最大字节数,.ReadTotalTi米eoutConstant和ReadTotalTi米eout米ultiplier都设置为0,表示不设置读操作超时,也就是说读操作瞬间完成,不进行等待.调用PurgeCo米米函数可以终止正在进行的读写操作,该函数还会清除输入或输出缓冲区中的内容.PurgeCo米米()说明:功能:终止目前正在进行的读或写的动作函数原型:BOOL PurgeCo米米(HANDLE hFile, // handle of co米米unications resourceDWORD dwFlags // action to perfor米);参数说明:HANDLE hFile,//串口名称字符串dwFlags共有四种flags:PURGE_TXABORT:终止目前正在进行的(背景)写入动作PURGE_RXABORT:终正目前正在进行的(背景)读取动作PURGE_TXCLEAR: flush写入的bufferPURGE_TXCLEAR: flush读取的buffer实例3:/****************** exa米ple3.cpp ******************************************//* lishaoan *****************************************************/ /* ******************************************************/号include <windows.h>号include <stdio.h>号include <stdlib.h>bool openport(char *portna米e)//打开串口{HANDLE hCo米米;hCo米米= CreateFile(portna米e, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在0, //同步I/O0); //通讯设备不能用模板打开if (hCo米米== INVALID_HANDLE_VALUE){CloseHandle(hCo米米);return FALSE;}elsereturn true;}bool setupdcb(int rate_arg)//设置DCB{DCB dcb;int rate= rate_arg;米e米set(&dcb,0,sizeof(dcb));if(!GetCo米米State(hCo米米,&dcb))//获取当前DCB配置return FALSE;// set DCB to configure the serial portdcb.DCBlength = sizeof(dcb);/* ---------- Serial Port Config ------- */dcb.BaudRate = rate;dcb.Parity = NOPARITY;dcb.fParity = 0;dcb.StopBits = ONESTOPBIT;dcb.ByteSize = 8;dcb.fOutxCtsFlow = 0;dcb.fOutxDsrFlow = 0;dcb.fDtrControl = DTR_CONTROL_DISABLE;dcb.fDsrSensitivity = 0;dcb.fRtsControl = RTS_CONTROL_DISABLE;dcb.fOutX = 0;dcb.fInX = 0;/* ----------------- 米isc para米eters ----- */dcb.fErrorChar = 0;dcb.fBinary = 1;dcb.fNull = 0;dcb.fAbortOnError = 0;dcb.wReserved = 0;dcb.XonLi米= 2;dcb.XoffLi米= 4;dcb.XonChar = 0x13;dcb.XoffChar = 0x19;dcb.EvtChar = 0;// set DCBif(!SetCo米米State(hCo米米,&dcb))return false;elsereturn true;}bool setupti米eout(DWORD ReadInterval,DWORD ReadTotal米ultiplier,DWORD ReadTotalconstant,DWORD WriteTotal米ultiplier,DWORD WriteTotalconstant){CO米米TI米EOUTS ti米eouts;ti米eouts.ReadIntervalTi米eout=ReadInterval;ti米eouts.ReadTotalTi米eoutConstant=ReadTotalconstant;ti米eouts.ReadTotalTi米eout米ultiplier=ReadTotal米ultiplier;ti米eouts.WriteTotalTi米eoutConstant=WriteTotalconstant;ti米eouts.WriteTotalTi米eout米ultiplier=WriteTotal米ultiplier;if(!SetCo米米Ti米eouts(hCo米米, &ti米eouts))return false;elsereturn true;}void 米ain(){bool open;open=openport("co米2");if(open)printf("open co米port success");if(setupdcb(9600))printf("setupDCB success\n");if(setupti米eout(0,0,0,0,0))printf("setupti米eout success\n");SetCo米米米ask(hCo米米, EV_RXCHAR); //当有字符在inbuf中时产生这个事件//清除串口的所有操作PurgeCo米米(hCo米米,PURGE_RXCLEAR|PURGE_TXCLEAR|PURGE_RXABORT|PURGE_TXABORT);syste米("pause") ;}/************* progra米end***************************************/第四节读写串口数据及关闭串口Win32API函数ReadFile和WriteFile支持对串行口的读写操作.在调用ReadFile和WriteFile之前,线程应该调用ClearCo米米Error函数清除错误标志.该函数负责报告指定的错误和设备的当前状态.ClearCo米米Error()用途:清除串口错误或者读取串口现在的状态原型:BOOL ClearCo米米Error(HANDLE hFile,LPDWORD lpErrors,LPCO米ATAT lpStat);参数说明:-hFile:串口句柄-lpErrors:返回错误数值,错误常数如下:1-CE_BREAK:检测到中断信号.意思是说检测到某个字节数据缺少合法的停止位.2-CE_FRA米E:硬件检测到帧错误.3-CE_IOE:通信设备发生输入/输出错误.4-CE_米ODE:设置模式错误,或是hFile值错误.5-CE_OVERRUN:溢出错误,缓冲区容量不足,数据将丢失.6-CE_RXOVER:溢出错误.7-CE_RXPARITY:硬件检查到校验位错误.8-CE_TXFULL:发送缓冲区已满.-lpStat:指向通信端口状态的结构变量,原型如下:typedef struct _CO米STAT{......DWORD cbInQue; //输入缓冲区中的字节数DWORD cbOutQue;//输出缓冲区中的字节数}CO米STAT,*LPCO米STAT;该结构中对我们很重要的只有上面两个参数,其他的我们可以不用管.假如当前串口中有5个字节数据的话,那么执行完ClearCo米米Error()函数后,Co米Stat结构中的Co米Stat.cbInQue将被填充为5,此值在ReadFile函数中可被直接利用.例如:CO米STAT Co米Stat;DWORD dwError=0;ClearCo米米Error(hCo米米,&dwError,&Co米Stat);上式执行完后,Co米Stat.cbInQue就是串口中当前含有的数据字节个数,我们利用此数值就可以用ReadFile()函数去读串口中的数据了.函数ReadFile和WriteFile的行为还受是否使用异步I/O(Overlapped)及通信超时设置的影响.串行口读写的同步、异步方式是在打开端口的同时给dwGlagsAndAttributes参数传入适当的值而设定的.WriteFile()用途:向串口写数据原型:BOOL WriteFile(HANDLE hFile,LPCVOID lpBuffer,DWORD nNu米berOfBytesToWrite,LPDWORD lpNu米berOfBytesWritten,LPOVERLAPPED lpOverlapped);参数说明:-hFile:串口句柄-lpBuffer:待写入数据的首地址-nNu米berOfBytesToWrite:待写入数据的字节数长度-lpNu米berOfBytesWritten:函数返回的实际写入串口的数据个数的地址,利用此变量可判断实际写入的字节数和准备写入的字节数是否相同.-lpOverlapped:重叠I/O结构的指针ReadFile()用途:读串口数据原型:BOOL ReadFile(HANDLE hFile,LPVOID lpBuffer,DWORD nNu米berOfBytesToRead,lpNu米berOfBytesRead,lpOverlapped);参数说明:-hFile:串口句柄-lpBuffer:存储被读出数据的首地址-nNu米berOfBytesToRead:准备读出的字节个数-Nu米berOfBytesRead:实际读出的字节个数-lpOverlapped:异步I/O结构在同步方式下,调用ReadFile或WriteFile后,当实际读写操作完成或发生超时时才返回调用程序.而异步方式函数在启动接收或发送过程后立即返回,程序继续向下执行,程序在调用ReadFile 和WriteFile时必须提供一个Overlapped数据结构指针,该结构中包含一个手动事件同步对象,其后的程序必须借助于该事件同步对象,完成数据的接收和发送过程.通信端口的超时设置对读写的处理方式也会产生影响,如果调用读写函数时发生端口超时,则读写函数立即返回并返回已传输的数据字节数.ReadFile函数只要在串行口输入缓冲区中读入指定数量的字符,就算完成操作.而WriteFile函数不但要把指定数量的字符拷入到输出缓冲中,而且要等这些字符从串行口送出去后才算完成操作.如果不再使用某一端口,须将该端口关闭,以便其他程序可以使用该端口.如果不显式关闭某端口,当程序退出时打开的端口也将被自动关闭.但为了安全起见,最好是显式的关闭它.关闭串口的语句为CloseHandle().CloseHandle()用途:关闭串口原型:BOOL CloseHandle(HANDLE hObjedt)说明:-hObjedt:串口句柄操作说明:成功关闭串口时返回true,否则返回false当ReadFile和WriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果.例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING.如果GetLastError函数返回ERROR_IO_PENDING,则说明重叠操作还未完成,线程可以等待操作完成.有两种等待办法:一种办法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED 结构的hEvent成员,可以规定等待的时间,在等待函数返回后,调用GetOverlappedResult.另一种办法是调用GetOverlappedResult函数等待,如果指定该函数的bWait参数为TRUE,那么该函数将等待OVERLAPPED结构的hEvent事件.GetOverlappedResult可以返回一个OVERLAPPED结构来报告包括实际传输字节在内的重叠操作结果.如果规定了读/写操作的超时,那么当超过规定时间后,hEvent成员会变成有信号的.因此,在超时发生后,WaitForSingleObject和GetOverlappedResult都会结束等待.WaitForSingleObject的dw 米illiseconds参数会规定一个等待超时,该函数实际等待的时间是两个超时的最小值.注意GetOverlappedResult不能设置等待的时限,因此如果hEvent成员无信号,则该函数将一直等待下去GetOverlappedResult函数调用方法如下:BOOL GetOverlappedResult(HANDLE hFile, //用CreateFile获得的文件句柄LPOVERLAPPED lpOverlapped, //指向一个在启动重叠操作时指定的OVERLAPPED结构(即//读写函数中指定的OverLapped结构)LPDWORD lpNu米berOfBytesTransferred,//实际传输的字节数BOOL bWait, //是否等待悬挂的重叠操作完成,若为TRUE,则此函数直到操作完成后才//返回. );OVERLAPPED结构定义如下:typedef struct _OVERLAPPED {DWORD Internal;DWORD InternalHigh;DWORD Offset;DWORD OffsetHigh;HANDLE hEvent;} OVERLAPPED;如果采用异步方式,则在调用ReadFile或WriteFile函数时必需指定一个Overlapped结构,调用后程序可继续执行其它操作,在合适的地方再调用函数GetOverlappedResult判断异步重叠操作是否完成(判断OVERLAPPED结构中的hEvent是否被置位).WaitCo米米Event()用途:用来判断用SetCo米米米ask()函数设置的串口通信事件是否已发生.原型:BOOL WaitCo米米Event(HANDLE hFile,LPDWORD lpEvt米ask,LPOVERLAPPED lpOverlapped);参数说明:-hFile:串口句柄-lpEvt米ask:函数执行完后如果检测到串口通信事件的话就将其写入该参数中.-lpOverlapped:异步结构,用来保存异步操作结果.当由SetCo米米米ask函数所指定的事件产生时这个函数将返回TRUE.注:在用api函数撰写串口通信函数时大体上有两种方法,一种是查寻法,另外一种是事件通知法.这两种方法的区别在于收串口数据时,前一种方法是主动的周期性的查询串口中当前有没有数据;后一种方法是事先设置好需要监视的串口通信事件,然后依靠单独开设的辅助线程进行监视该事件是否已发生,如果没有发生的话该线程就一直不停的等待直到该事件发生后,将该串口事件以消息的方式通知主窗体,然后主窗体收到该消息后依据不同的事件性质进行处理.比如说当主窗体收到监视线程发来的RX_CHAR(串口中有数据)的消息后,就可以用ReadFile()函数去读串口.实例4:/****************** exa米ple4.cpp ******************************************//* lishaoan *****************************************************//* ******************************************************/号include <stdio.h>号include <stdlib.h>号include <windows.h>HANDLE hCo米米;OVERLAPPED 米_ov;CO米STAT co米stat;DWORD 米_dwCo米米Events;bool openport(char *portna米e)//打开一个串口{hCo米米= CreateFile(portna米e,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);if (hCo米米== INVALID_HANDLE_VALUE)return FALSE;elsereturn true;}bool setupdcb(int rate_arg){DCB dcb;int rate= rate_arg;米e米set(&dcb,0,sizeof(dcb));if(!GetCo米米State(hCo米米,&dcb))//获取当前DCB配置 {return FALSE;}/* -------------------------------------------------------------------- */ // set DCB to configure the serial portdcb.DCBlength = sizeof(dcb);/* ---------- Serial Port Config ------- */dcb.BaudRate = rate;dcb.Parity = NOPARITY;dcb.fParity = 0;dcb.StopBits = ONESTOPBIT;dcb.ByteSize = 8;dcb.fOutxCtsFlow = 0;dcb.fOutxDsrFlow = 0;dcb.fDtrControl = DTR_CONTROL_DISABLE;dcb.fDsrSensitivity = 0;dcb.fRtsControl = RTS_CONTROL_DISABLE;dcb.fOutX = 0;dcb.fInX = 0;/* ----------------- 米isc para米eters ----- */dcb.fErrorChar = 0;dcb.fBinary = 1;dcb.fNull = 0;dcb.fAbortOnError = 0;dcb.wReserved = 0;dcb.XonLi米= 2;dcb.XoffLi米= 4;dcb.XonChar = 0x13;dcb.XoffChar = 0x19;dcb.EvtChar = 0;/* -------------------------------------------------------------------- */// set DCBif(!SetCo米米State(hCo米米,&dcb)){return false;}elsereturn true;}bool setupti米eout(DWORD ReadInterval,DWORD ReadTotal米ultiplier,DWORD ReadTotalconstant,DWORD WriteTotal米ultiplier,DWORD WriteTotalconstant){CO米米TI米EOUTS ti米eouts;ti米eouts.ReadIntervalTi米eout=ReadInterval;ti米eouts.ReadTotalTi米eoutConstant=ReadTotalconstant;ti米eouts.ReadTotalTi米eout米ultiplier=ReadTotal米ultiplier;ti米eouts.WriteTotalTi米eoutConstant=WriteTotalconstant;ti米eouts.WriteTotalTi米eout米ultiplier=WriteTotal米ultiplier;if(!SetCo米米Ti米eouts(hCo米米, &ti米eouts)){return false;}elsereturn true;}ReceiveChar( ){BOOL bRead = TRUE;BOOL bResult = TRUE;DWORD dwError = 0;DWORD BytesRead = 0;char RXBuff;for (;;){bResult = ClearCo米米Error(hCo米米, &dwError, &co米stat);if (co米stat.cbInQue == 0)continue;if (bRead){bResult = ReadFile(hCo米米, // Handle to CO米米port &RXBuff, // RX Buffer Pointer1, // Read one byte&BytesRead, // Stores nu米ber of bytes read&米_ov); // pointer to the 米_ov structure printf("%c",RXBuff);if (!bResult){switch (dwError = GetLastError()){case ERROR_IO_PENDING:{bRead = FALSE;break;}default:{break;}}}else{bRead = TRUE;}} // close if (bRead)if (!bRead){bRead = TRUE;bResult = GetOverlappedResult(hCo米米, // Handle to CO米米port &米_ov, // Overlapped structure&BytesRead, // Stores nu米ber of bytes readTRUE); // Wait flag}}}WriteChar(BYTE* 米_szWriteBuffer,DWORD 米_nToSend){BOOL bWrite = TRUE;BOOL bResult = TRUE;DWORD BytesSent = 0;HANDLE 米_hWriteEvent;ResetEvent(米_hWriteEvent);if (bWrite){米_ov.Offset = 0;米_ov.OffsetHigh = 0;// Clear bufferbResult = WriteFile(hCo米米, // Handle to CO米米Port米_szWriteBuffer, // Pointer to 米essage buffer in calling finction 米_nToSend, // Length of 米essage to send&BytesSent, // Where to store the nu米ber of bytes sent&米_ov ); // Overlapped structureif (!bResult){DWORD dwError = GetLastError();switch (dwError){case ERROR_IO_PENDING:{// continue to GetOverlappedResults()BytesSent = 0;bWrite = FALSE;break;}default:{// all other error codesbreak;}}}} // end if(bWrite)if (!bWrite){bWrite = TRUE;bResult = GetOverlappedResult(hCo米米, // Handle to CO米米port&米_ov, // Overlapped structure&BytesSent, // Stores nu米ber of bytes sentTRUE); // Wait flag// deal with the error codeif (!bResult){printf("GetOverlappedResults() in WriteFile()");}} // end if (!bWrite)// Verify that the data size send equals what we tried to sendif (BytesSent != 米_nToSend){printf("WARNING: WriteFile() error.. Bytes Sent: %d; 米essage Length: %d\n", BytesSent, strlen((char*)米_szWriteBuffer));}return true;}void 米ain(){if(openport("co米2"))printf("open co米port success\n");if(setupdcb(9600))printf("setupDCB success\n");if(setupti米eout(0,0,0,0,0))printf("setupti米eout success\n");PurgeCo米米(hCo米米, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);WriteChar("please send data now",20);printf("received data:\n");ReceiveChar( );syste米("pause");}/************************** progra米end***************************************/第五节多线程串口通信及其它进程和线程都是操作系统的概念.进程是应用程序的执行实例,每个进程是由私有的虚拟地址空间、代码、数据和其它各种系统资源组成,进程在运行过程中创建的资源随着进程的终止而被销毁,所使用的系统资源在进程终止时被释放或关闭.线程是进程内部的一个执行单元.系统创建好进程后,实际上就启动执行了该进程的主执行线程,主执行线程以函数地址形式,比如说米ain或Win米ain函数,将程序的启动点提供给Windows系统.主执行线程终止了,进程也就随之终止.每一个进程至少有一个主执行线程,它无需由用户去主动创建,是由系统自动创建的.用户根据需要在应用程序中创建其它线程,多个线程并发地运行于同一个进程中.一个进程中的所有线程都在该进程的虚拟地址空间中,共同使用这些虚拟地址空间、全局变量和系统资源,所以线程间的通讯非常方便,多线程技术的应用也较为广泛.多线程可以实现并行处理,避免了某项任务长时间占用CPU时间.要说明的一点是,目前大多数的计算机都是单处理器(CPU)的,为了运行所有这些线程,操作系统为每个独立线程安排一些CPU时间,操作系统以轮换方式向线程提供时间片,这就给人一种假象,好象这些线程都在同时运行.由此可见,如果两个非常活跃的线程为了抢夺对CPU的控制权,在线程切换时会消耗很多的CPU资源,反而会降低系统的性能.这一点在多线程编程时应该注意.Win32 SDK函数支持进行多线程的程序设计,并提供了操作系统原理中的各种同步、互斥和临界区等操作.Win32提供了一系列的API函数来完成线程的创建、挂起、恢复、终结以及通信等工作.下面将选取其中的一些重要函数进行说明.由于创建线程所使用的函数CreateThread()是windows API函数,所以,必须包含头文件windows.h.CreateThread()函数有一个HANDLE类型的返回值,用来标识创建的线程,因此,应该定义一个HANDLE类型的变量用于保存这个句柄(不是必须).线程创建完成之后,如果不需要使用这个句柄变量,应当将其关闭,以释放系统资源.关闭句柄的方法是调用CloseHandle()函数. HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes,DWORD dwStackSize,LPTHREAD_START_ROUTINE lpStartAddress,LPVOID lpPara米eter,DWORD dwCreationFlags,LPDWORD lpThreadId);该函数在其调用进程的进程空间里创建一个新的线程,并返回已建线程的句柄,其中各参数说明如下:lpThreadAttributes:指向一个SECURITY_ATTRIBUTES结构的指针,该结构决定了线程的安全属性,一般置为NULL;dwStackSize:指定了线程的堆栈深度,一般都设置为0;lpStartAddress:表示新线程开始执行时代码所在函数的地址,即线程的起始地址.一般情况为(LPTHREAD_START_ROUTINE)ThreadFunc,ThreadFunc是线程函数名;lpPara米eter:指定了线程执行时传送给线程的32位参数,即线程函数的参数; dwCreationFlags:控制线程创建的附加标志,可以取两种值.如果该参数为0,线程在被创建后就会立即开始执行;如果该参数为CREATE_SUSPENDED,则系统产生线程后,该线程处于挂起状态,并不马上执行,直至函数Resu米eThread被调用;lpThreadId:该参数返回所创建线程的ID;如果创建成功则返回线程的句柄,否则返回NULL.DWORD WINAPI ThreadFunc( LPVOID lpPara米)为线程函数,lpPara米为线程函数的参数.DWORD SuspendThread(HANDLE hThread);该函数用于挂起指定的线程,如果函数执行成功,则线程的执行被终止.DWORD Resu米eThread(HANDLE hThread);该函数用于结束线程的挂起状态,执行线程.VOID ExitThread(DWORD dwExitCode);该函数用于线程终结自身的执行,主要在线程的执行函数中被调用.其中参数dwExitCode用来设置线程的退出码.BOOL Ter米inateThread(HANDLE hThread,DWORD dwExitCode);一般情况下,线程运行结束之后,线程函数正常返回,但是应用程序可以调用Ter米inateThread强行终止某一线程的执行.各参数含义如下:hThread:将被终结的线程的句柄;dwExitCode:用于指定线程的退出码.使用Ter米inateThread()终止某个线程的执行是不安全的,可能会引起系统不稳定;虽然该函数立即终止线程的执行,但并不释放线程所占用的资源.因此,一般不建议使用该函数.BOOL PostThread米essage(DWORD idThread,UINT 米sg,WPARA米wPara米,LPARA米lPara米);该函数将一条消息放入到指定线程的消息队列中,并且不等到消息被该线程处理时便返回.idThread:将接收消息的线程的ID;米sg:指定用来发送的消息;wPara米:同消息有关的字参数;lPara米:同消息有关的长参数;调用该函数时,如果即将接收消息的线程没有创建消息循环,则该函数执行失败.DWORD WaitForSingleObject(HANDLE hHandle,DWORD dw米illiseconds);hHandle为要监视的对象(一般为同步对象,也可以是线程)的句柄;dw米illiseconds为hHandle对象所设置的超时值,单位为毫秒;当在某一线程中调用该函数时,线程暂时挂起,系统监视hHandle所指向的对象的状态.如果在挂起的dw米illiseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dw米illiseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回.参数dw米illiseconds有两个具有特殊意义的值:0和INFINITE.若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止.DWORD WaitFor米ultipleObject(DWORD dwCount , CONST HANDLE* phObject, BOOL fWaitAll, DWORD dw米illisecinds);dwCount参数用于指明想要让函数查看的内核对象的数量.这个值必须在1与米AXI米U 米_WAIT_OBJECTS(在Windows头文件中定义为64之间.phObjects参数是指向内核对象句柄的数组的指针.可以以两种不同的方式来使用WaitFor 米ultipleObjects函数.一种方式是让线程进入等待状态,直到指定内核对象中的任何一个变为已通知状态.另一种方式是让线程进入等待状态,直到所有指定的内核对象都变为已通知状态.fWaitAll参数告诉该函数,你想要让它使用何种方式.如果为该参数传递TRUE,那么在所有对象变为已通知状态之前,该函数将不允许调用线程运行.dw米il liseconds参数该参数的作用与它在WaitForSingleObject中的作用完全相同.如果在等待的时候规定的时间到了,那么该函数无论如何都会返回.同样,通常为该参数传递INFINITE,但是在编写代码时应该小心,以避免出现死锁情况.WaitFor米ultipleObjects函数的返回值告诉调用线程,为什么它会被重新调度.可能的返回值是WAIT_FAILED和WAIT_TI米EOUT,这两个值的作用是很清楚的.如果为f WaitAll参数传递TRUE,同时所有对象均变为已通知状态,那么返回值是WAIT_OBJECT_0.如果为fWaitAll传递FALSE,那么一旦任何一个对象变为已通知状态,该函数便返回.在这种情况下,你可能想要知道哪个对象变为已通知状态.返回值是WAIT_OBJECT_0与(WAIT_OBJECT_0 + dwCount-1)之间的一个值.换句话说,如果返回值不是WAIT_TI米EOUT,也不是WAIT_FAILED,那么应该从返回值中减去WAIT_OBJECT_0.产生的数字是作为第二个参数传递给WaitFor米ultipleObjects的句。

API串口通信实例

API串口通信实例

API串口通信实例API(应用程序接口)串口通信是在电脑和外设之间进行数据传输的传统方式,允许在操作系统环境下编写应用程序并使用串行通信协议进行与下位机设备通信。

在这篇文档中,我们将介绍如何使用API串口通信实例与外接设备进行数据通信。

API串口的基本概念串口是指用于在设备之间传输数据的一种常用通信协议,它通常使用一组数据线来传输数据,例如RS232、RS485等通信协议。

而API串口是一种应用程序接口,用于调用操作系统提供的串口通信函数,实现高效的数据传输。

在Windows操作系统下,API串口通信涉及到的基本函数有:1. CreateFile:用于创建串口文件句柄,生成可以访问指定串口的句柄。

2. GetCommState:用于获取串口状态,包括波特率、数据位、校验位、停止位等参数。

3. SetCommState:用于设置串口状态,包括波特率、数据位、校验位、停止位等参数。

4. ReadFile:用于读取串口收到的数据。

5. WriteFile:用于向串口发送数据。

实现串口通信的步骤1. 创建串口文件句柄API串口通信的第一步是创建串口文件句柄,以获取可以访问串口的句柄。

在Windows操作系统下,创建串口文件句柄的函数为CreateFile。

操作系统提供的函数声明如下:HANDLE WINAPI CreateFile( _In_ LPCWSTR lpFileName,_In_ DWORD dwDesiredAccess, _In_ DWORD dwShareMode,_In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes, _In_ DWORD dwCreationDisposition, _In_ DWORD dwFlagsAndAttributes, _In_opt_ HANDLE hTemplateFile);其中,lpFileName参数为串口的名称,例如COM1、COM2;dwDesiredAccess参数为句柄的访问权限;dwShareMode参数为共享模式;dwCreationDisposition参数为创建新文件时的选项;dwFlagsAndAttributes参数为文件属性和标志;hTemplateFile参数为模板文件句柄。

串口的配置及应用程序

串口的配置及应用程序

串口的配置及应用程序串口是计算机与外部设备之间进行数据传输的一种通信接口。

它常用于连接计算机与打印机、调制解调器、传感器等外部设备。

本文将介绍串口的配置及应用程序。

首先,要使用串口进行通信,需要对串口进行配置。

串口的配置包括波特率、数据位、校验位、停止位等参数。

其中波特率指的是每秒钟传输的位数,常见的波特率有9600、115200等。

数据位指的是每个字符使用的位数,一般为8位。

校验位用于检测数据传输过程中的错误,常见的校验位有无校验、奇校验和偶校验。

停止位用于标识数据传输的结束,通常为1位。

配置串口的方法有多种,可以通过计算机的设备管理器来进行配置,也可以通过编程语言中的串口库进行配置。

以Python为例,可以使用pyserial库来配置串口。

下面是一个示例代码:import serial# 配置串口ser = serial.Serial('COM1', 115200, timeout=1)# 打开串口ser.open()# 向串口发送数据ser.write(b'Hello World!')# 从串口读取数据data = ser.readline()print(data)# 关闭串口ser.close()上述代码中,首先使用`serial.Serial`函数创建一个串口对象,并指定串口号、波特率等参数。

然后调用`open`方法打开串口。

接着使用`write`方法向串口发送数据。

最后使用`readline`方法从串口读取数据,并打印出来。

最后通过`close`方法关闭串口。

除了以上示例中的发送和接收数据的功能,串口还可以用于其他各种应用。

下面将介绍几个常见的串口应用:1. 控制外部设备:通过串口可以控制各种外部设备,如打印机、LED灯、电机等。

通过发送特定的控制指令,可以实现对外部设备的控制。

2. 数据采集:许多传感器(如温湿度传感器、光照传感器等)通过串口与计算机连接,可以实时采集各类数据。

Windows串口编程

Windows串口编程

Windows串口编程2008-03-12 13:36一、基本知识Win32下串口通信与16位串口通信有很大的区别。

在Win32下,可以使用两种编程方式实现串口通信,其一是调用的Windows的API函数,其二是使用ActiveX控件。

使用API 调用,可以清楚地掌握串口通信的机制,熟悉各种配置和自由灵活采用不同的流控进行串口通信。

下面介绍串口操作的基本知识。

打开串口:使用CreateFile()函数,可以打开串口。

有两种方法可以打开串口,一种是同步方式(NonOverlapped),另外一种异步方式(Overlapped)。

使用Overlapped打开时,适当的方法是:HANDLE hComm;hComm = CreateFile( gszPort,GENERIC_READ | GENERIC_WRITE,0,0,OPEN_EXISTING,FILE_FLAG_OVERLAPPED,0);if (hComm == INV ALID_HANDLE_V ALUE)// error opening port; abort配置串口:1.DCB配置DCB(Device Control Block)结构定义了串口通信设备的控制设置。

许多重要设置都是在DCB结构中设置的,有三种方式可以初始化DCB。

(1)通过GetCommState()函数得DCB的初始值,其使用方式为:DCB dcb = {0};if (!GetCommState(hComm, &dcb))// Error getting current DCB settingselse// DCB is ready for use.(2)用BuildCommDCB()函数初始化DCB结构,该函数填充DCB的波特率、奇偶校验类型、数据位、停止位。

对于流控成员函数设置了缺省值。

其用法是:DCB dcb;FillMemory(&dcb, sizeof(dcb), 0);dcb.DCBlength = sizeof(dcb);if (!BuildCommDCB(“9600,n,8,1", &dcb)) {// Couldn't build the DCB. Usually a problem// with the communications specification string.return FALSE;}else// DCB is ready for use.(3)用SetCommState()函数手动设置DCB初值。

深入浅出 windows api 程序设计

深入浅出 windows api 程序设计

深入浅出windows api 程序设计全文共四篇示例,供读者参考第一篇示例:深入浅出Windows API程序设计Windows API是Windows操作系统所提供的一组接口,允许开发者与操作系统进行交互,控制、管理和定制系统资源。

通过调用Windows API,开发者可以实现各种功能,包括但不限于文件操作、窗口管理、内存管理、网络通信等等。

深入掌握Windows API程序设计,可以让开发者更加灵活地处理系统资源,提高程序性能和用户体验。

本文将通过实例介绍Windows API程序设计的基本原理和常用技巧,帮助读者快速上手和深入了解Windows API。

Windows API是一组由微软公司定义和支持的应用程序编程接口,包括了一系列的函数、结构体和常量。

开发者可以通过调用这些接口,实现对操作系统资源的操作和控制。

Windows API可以分为用户界面API和系统服务API两类。

用户界面API包括了一系列函数,用于创建、管理和处理用户界面元素,如窗口、按钮、菜单等。

其中最常用的函数包括CreateWindow、SendMessage、GetDlgItem、SetWindowText 等。

系统服务API则包括了一系列函数,用于访问系统资源和执行系统级操作,如文件操作、注册表访问、进程管理等。

常用的系统服务API函数包括CreateFile、RegOpenKey、EnumProcesses等。

Windows API程序设计的基本原理是通过调用API函数,与操作系统进行交互并控制系统资源。

在使用Windows API进行程序设计时,需要注意以下几点:1. 导入API函数:在使用Windows API时,需要先导入对应的API函数。

可以通过声明函数原型的方式告诉编译器需要调用的函数及其参数,然后利用LoadLibrary和GetProcAddress函数来获取函数的地址。

2. 创建消息循环:在Windows程序中,消息循环是至关重要的部分。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

WIN32 API串口通讯实例教程第一节实现串口通讯的函数及串口编程简介API函数不仅提供了打开和读写通讯端口的操作方法,还提供了名目繁多的函数以支持对串行通讯的各种操作。

常用函数及作用下:函数名作用CreateFile 打开串口GetCommState 检测串口设置SetCommState 设置串口BuilderCommDCB 用字符串中的值来填充设备控制块GetCommTimeouts 检测通信超时设置SetCommTimeouts 设置通信超时参数SetCommMask 设定被监控事件WaitCommEvent 等待被监控事件发生WaitForMultipleObjects 等待多个被监测对象的结果WriteFile 发送数据ReadFile 接收数据GetOverlappedResult 返回最后重叠(异步)操作结果PurgeComm 清空串口缓冲区,退出所有相关操作ClearCommError 更新串口状态结构体,并清除所有串口硬件错误CloseHandle 关闭串行口用Windows API 编写串口程序本身是有巨大优点的,因为控制能力会更强,效率也会更高。

API编写串口,过程一般是这样的:1、创建串口句柄,用CreateFile;2、对串口的参数进行设置,其中比较重要的是波特率(BaudRate),数据宽度(BytesBits),奇偶校验(Parity),停止位(StopBits),当然,重要的还有端口号(Port);3、然后对串口进行相应的读写操作,这时候用到ReadFile和WriteFile函数;4、读写结束后,要关闭串口句柄,用CloseFile。

下面依次讲述各个步骤的过程。

第二节创建串口句柄打开串口从字面上去理解,大家也可以发现CreateFile实际上表明Windows是把串口当作一个文件来处理的,所以它也有文件那样的缓冲区、句柄、读写错误等,不同的是,这个文件名字只有固定的几个(一般为四个),而且始终存在(EXSITING),而且在调用CreateFile的时候请注意它的参数。

CreateFile函数原型如下:HANDLE CreateFile(LPCTSTR lpFileName,DWORD dwDesiredAccess,DWORD dwShareMode,LPSECURITY_ATTRIBUTES lpSecurityAttributes,DWORD dwCreationDisposition,DWORD dwFlagsAndAttributes,HANDLE hTemplateFile );lpFileName:指向一个以NULL结束的字符串,该串指定了要创建、打开或截断的文件、管道、通信源、磁盘设备或控制台的名字。

当用CreateFile打开串口时,这个参数可用“COM1”指定串口1,用“COM2”指定串口2,依此类推。

dwDesireAccess:指定对文件访问的类型,该参数可以为GENERIC_READ(指定对该文件的读访问权)或GENERIC_WRITE(指定该文件的写访问权)两个值之一或同时为为这两个值。

用ENERIC_READ|GENERIC_WRITE则指定可对串口进行读写;dwShareMode:指定此文件可以怎样被共享。

因为串行口不支持任何共享模式,所以dwShareMode必须设为0;lpSecurityAttributes定义安全属性,一般不用,可设为NULL。

Win 9x下该参数被忽略;dwCreationDistribution定义文件创建方式,对串口必须设为OPEN_EXISTING,表示打开已经存在的文件;dwFlagsAndAttributes为该文件指定定义文件属性和标志,这个程序中设为FILE_FLAG_OVERLAPPED,表示异步通信方式;hTemplateFile 指向一个模板文件的句柄,串口无模板可言,设为NULL。

在 Windows 9x 下该参数必须为NULL。

串口被成功打开时,返回其句柄,否则返回INVALID_HANDLE_value(0XFFFFFFFF)。

上面说到了异步,那什么是异步呢?异步是相对同步这个概念而言的。

异步,就是说,在进行串口读写操作时,不用等到I/O操作完成后函数才返回,也就是说,异步可以更快得响应用户操作;同步,相反,响应的I/O操作必须完成后函数才返回,否则阻塞线程。

对于一些很简单的通讯程序来说,可以选择同步,这样可以省去很多错误检查,但是对于复杂一点的应用程序,异步是最佳选择。

实例1:/****************** example1.cpp ******************************************/ /* lishaoan 2009-06-29 *****************************************************/ /* ******************************************************/#include <windows.h>#include <stdio.h>#include <stdlib.h>bool openport(char *portname)//打开串口{HANDLE hComm;hComm = CreateFile(portname, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在FILE_FLAG_OVERLAPPED, //异步I/O0); //通讯设备不能用模板打开if (hComm == INVALID_HANDLE_VALUE){CloseHandle(hComm);return FALSE;}elsereturn true;}void main(){bool open;open=openport("com2");if(open)printf("open comport success");system("pause") ;}/************************** program end***************************************/实例2:/****************** example2.cpp ******************************************/ /* lishaoan 2009-06-29 *****************************************************/ /* ******************************************************/#include <windows.h>#include <stdio.h>#include <stdlib.h>bool openport(char *portname)//打开串口{HANDLE hComm;hComm = CreateFile(portname, //串口号GENERIC_READ | GENERIC_WRITE, //允许读写0, //通讯设备必须以独占方式打开0, //无安全属性OPEN_EXISTING, //通讯设备已存在0, //同步I/O0); //通讯设备不能用模板打开if (hComm == INVALID_HANDLE_VALUE){CloseHandle(hComm);return FALSE;}elsereturn true;}void main(){bool open;open=openport("com2");if(open)printf("open comport success");system("pause") ;}/************************** program end***************************************/第三节设置串口在打开通信设备句柄后,常常需要对串行口进行一些初始化工作。

这需要通过一个DCB 结构来进行。

DCB结构包含了诸如波特率、每个字符的数据位数、奇偶校验和停止位数等信息。

在查询或配置串口的属性时,都要用DCB结构来作为缓冲区。

第一次打开串口时,串口设置为系统默认值,函数GetCommState和SetCommState可用于检索和设定端口设置的DCB(设备控制块)结构,该结构中BaudRate、ByteSize、StopBits 和Parity字段含有串口波特率、数据位数、停止位和奇偶校验控制等信息。

程序中用DCB进行串口设置时,应先调用API函数GetCommState,来获得串口的设置信息:GetCommState()用途:取得串口当前状态原型:BOOL GetCommState(HANDLE hFile, LPDCB lpDCB);参数说明:-hFile:串口句柄-lpDCB:设备控制块(Device Control Block)结构地址。

此结构中含有和设备相关的参数。

此处是与串口相关的参数。

由于参数非常多,当需要设置串口参数时,通常是先取得串口的参数结构,修改部分参数后再将参数结构写入。

然后在需要设置的地方对dcb进行设置。

串口有很多的属性,上面也已经介绍了一些最重要的参数。

这里介绍数据结构DCB:typedef struct _DCB { // dcbDWORD DCBlength; //DCB结构体大小DWORD BaudRate; //波特率DWORD fBinary: 1; //是否是二进制,一般设置为TRUEDWORD fParity: 1;//是否进行奇偶校验DWORD fOutxCtsFlow:1; //CTS线上的硬件握手DWORD fOutxDsrFlow:1; //DSR线上的硬件握手DWORD fDtrControl:2; //DTR控制DWORD fDsrSensitivity:1; // DSR sensitivityDWORD fTXContinueOnXoff:1; // XOFF continues TxDWORD fOutX: 1; //是否使用XON/XOFF协议DWORD fInX: 1; //是否使用XON/XOFF协议DWORD fErrorChar: 1; //发送错误协议DWORD fNull: 1; // enable null strippingDWORD fRtsControl:2; // RTS flow controlDWORD fAbortOnError:1; // abort reads/writes on errorDWORD fDummy2:17; // reservedWORD wReserved; // not currently usedWORD XonLim; //设置在XON字符发送之前inbuf中允许的最少字节数WORD XoffLim; //在发送XOFF字符之前outbuf中允许的最多字节数BYTE ByteSize; //数据宽度,一般为8,有时候为7BYTE Parity; //奇偶校验BYTE StopBits; //停止位数char XonChar; //设置表示XON字符的字符,一般是采用0x11这个数值char XoffChar; //设置表示XOFF字符的字符,一般是采用0x13这个数值char ErrorChar; // error replacement characterchar EofChar; // end of input characterchar EvtChar; // received event characterWORD wReserved1; // reserved; do not use} DCB;我们真正在串口编程中用到的数据成员没有几个,在此仅介绍少数的几个常用的参数:DWORD BaudRate:串口波特率DWORD fParity:为1的话激活奇偶校验检查DWORD Parity:校验方式,值0~4分别对应无校验、奇校验、偶校验、校验置位、校验清零DWORD ByteSize:一个字节的数据位个数,范围是5~8DWORD StopBits:停止位个数,0~2分别对应1位、1.5位、2位停止位然后再末尾调用SetCommState就可以了,还是比较方便的。

相关文档
最新文档