Windows Embedded CE 7串口通信应用程序实例(上)

本章将介绍Windows Embedded CE 7.0的串口通信。一些基于Windows CE的设备可以与其他计算机、打印机、调制解调器,或全球定位系统(GPS)卫星通信由串行连接方式。

串行I / OWindows CE支持的最简单的通信方式。两个设备之间建立一个直接的、一对一的连接。串行I / O可以通过多种方式的硬件连接,但是,大多数基于Windows CE的设备使用串行电缆或PC卡设备,如调制解调器或红外(IR)收发器。串行电缆之间的数据交换类似于文件的读取或写入。

Windows CE支持基于标准的基于Windows桌面的串行通讯函数。这些函数可用于打开、关闭、并操纵串行端口、发送和接收数据,并管理连接。

虽然目前很多设备都没有外置串口,因为有更快更稳定的接口代替了串口。但是基于Windows CE的设备仍然保留着串口,因为目前常用的基于Windows CE的设备都具体导航、电话等功能,而GPSGSM/GPRS的模块都是外置串口的终端设备。因此,串口仍会作为Windows CE设备中不可缺少的部分。

9.1 设计说明

Windows CE下的串口编程不同于MS-DOS下的编程。每个Windows CE设备都拥有各自不同的物理内存映射表。即使能够查找到串口设备对应的基地址,也不能直接对寄存器进行编程。因为串行硬件与串口端口不能保证完全兼容,程序对寄存器的操作并不一定能够成功或正确写入到相应的串行硬件中。

一个与串口进行交互的应用程序,涉及到打开串行设备驱动程序以及与其通信。与大部分的现代操作系统一样,Windows CE通过文件系统的一系列API来访问设备驱动程序。串口通信中常用的API既包括了设备基本通信函数,如CreateFile, ReadFile, WriteFile, CloseHandle函数分别用于串口的建立、,数据传输以及关闭,也包括了设备控制函数,如GetCommState/SetCommStateGetCommTimeouts/SetCommTimeoutsGetCommMask/SetCommMask,以及WatiCommEvent函数分别用于串口状态、参数以及事件条件等的查询和设定。

9.2 开启序列通信端口

开启序列通信端口通过调用CreateFile函数来打开。因为硬件供应商和设备驱动程序开发者可以给端口指定任意的名字,应用程序应该列出可用的端口,并允许用户指定需要打开的端口。如果指定的端口不存在,CreateFile函数返回ERROR_FILE_NOT_FOUND,并应通知用户端口不可用。

CreateFile函数的功能在于创建、打开或截断文件、通信资源,磁盘设备或控制台。它返回一个可以用来访问对象的句柄,也可以打开并返回目录的句柄。

CreateFile函数的原型如下:

HANDLE CreateFile(

LPCTSTR lpFileName, 

DWORD dwDesiredAccess, 

DWORD dwShareMode, 

LPSECURITY_ATTRIBUTES lpSecurityAttributes, 

DWORD dwCreationDispostion , 

DWORD dwFlagsAndAttributes, 

HANDLE hTemplateFile);

参数lpFileName是一个指向空结束字符串的指针,这个字符串描述了需要创建或打开的对象的名称(文件,控制台,磁盘设备,通信资源,或目录)。如果参数lpFileName的值是文件路径,那么默认的字符串长度限制为MAX_PATH;如果参数lpFileName指向了通信资源的对象,那么在名称的末尾必须加上,如“COM1:”

参数dwDesiredAccess指定访问对象的类型。应用程序可以获取读访问,写访问,读写访问,或设备查询的访问​​。这个参数可以是下列值的任意组合:如表9-1所示

描述

0

允许设备对象被查询访问。应用程序可以不用访问设备而能够查询到设备的属性

GENERIC_READ

允许对象被读取访问。可以从文件中读取数据,也可以移动文件指针。结合属性GENERIC_WRITE允许读写访问

GENERIC_WRITE

允许对象被写入访问。可以向文件中写入数据,也可以移动文件指针。结合属性GENERIC_ READ允许读写访问

    表9-1对象类型说明

参数dwShareMode指定对象被共享的方式。如果dwShareMode0,对象不能共享。第一次之后打开对象的操作将失败,直到句柄被关闭。这个参数可以是下列值的任意组合:如表9-2所示

描述

FILE_SHARE_READ

如果请求是读访问,以后每次打开对象的操作会成功。

FILE_SHARE_WRITE

如果请求是写访问,以后每次打开对象的操作会成功。

9-2对象返回值说明

参数lpSecurityAttributes被忽略,值为NULL

参数dwCreationDispostion指定当文件存在以及不存在时分别采取的动作此参数必须是以下值之一:如表9-3所示。

描述

CREATE_NEW

创建一个新文件。如果指定的文件已经存在,该函数将失败。

CREATE_ALWAYS

创建一个新文件。如果该文件存在,函数将覆盖该文件,并清除现有的属性。

OPEN_EXISTING

打开该文件。如果该文件不存在,该函数将失败

OPEN_ALWAYS

如果文件存在,则打开它;如果该文件不存在,该函数创建新文件,就像dwCreationDisposition参数的值是 CREATE_NEW

TRUNCATE_EXISTING

打开该文件。一旦打开,该文件被截断,因此,它的大小为零字节。调用程序至少需要用GENERIC_WRITE属性来打开文件。如果该文件不存在,该函数将失败

9-3参数说明

参数dwFlagsAndAttributes指定文件的文件属性和标志。下列属性的任意组合都是dwFlagsAndAttributes参数的可选值,除非其他文件属性覆盖FILE_ATTRIBUTE_NORMAL。如表9-4所示。

描述

FILE_ATTRIBUTE_ARCHIVE

应当归档的文件。应用程序使用此属性标记备份或删除的文件

FILE_ATTRIBUTE_HIDDEN

该文件是隐藏的。它不被普通的目录列表包括

FILE_ATTRIBUTE_NORMAL

文件有没有设置其他的属性。仅当此属性单独使用才有效

FILE_ATTRIBUTE_READONLY

该文件是只读的。应用程序可以读取该文件,但不能写入或删除它

FILE_ATTRIBUTE_SYSTEM

该文件是操作系哦他能够的一部分,或是被操作系统所独占

9-4返回值说明

下列标志的任意组合dwFlagsAndAttributes参数是可以接受的。如表9-5所示。

描述

FILE_FLAG_WRITE_THROUGH

指示系统对中间缓存执行写穿透策略,直接写入到磁盘。系统仍然可以缓存写入操作,但不能采取懒惰方式将数据刷入。

FILE_FLAG_OVERLAPPED

这个标志不支持,但是,多个读/写设备等候在同一时刻是被允许的。

FILE_FLAG_RANDOM_ACCESS

表示该文件是随机访问。该系统可以作为一个提示使用此优化文件缓存。

9-5返回值说明

参数hTemplateFile忽视;因此, CreateFile不会复制到新文件的扩展属性。

函数执行成功返回句柄。如果在函数调用之前指定的文件存在,而且参数dwCreationDisposition的值是 CREATE_ALWAYSOPEN_ALWAYS,调用GetLastError返回ERROR_ALREADY_EXISTS,即使功能已成功。如果文件在调用前不存在,GetLastError返回零。 INVALID_HANDLE_VALUE表示失败。

要打开一个串口,基本的操作如下:

1. 在第一个参数lpzPortName后插入一个冒号。例如,指定“COM1:”作为通信端口。

2. 设置参数dwShareMode的值为零,除非使用的驱动程序允许被打开多次。只有一个设备可以执行读/写或改变端口行为的操作;其他应用程序可以执行例如端口监控,控制线的状态。

3. 设置dwCreationDisposition参数的值为OPEN_EXISTING。这个标志是必需的。

4. 设置dwFlagsAndAttributes参数的值为零。 Windows CE支持只nonoverlapped I / O

下面的例子给出了如何打开一个序列通信端口:

// Open the serial port.

  hPort = CreateFile (lpszPortName, // Pointer to the name of the port

                      GENERIC_READ | GENERIC_WRITE,

                                    // Access (read-write) mode

                      0,            // Share mode

                      NULL,         // Pointer to the security attribute

                      OPEN_EXISTING,// How to open the serial port

                      0,            // Port attributes

                      NULL);        // Handle to port with attribute

                                    // to copy

在从端口写入或读取数据前,必须先配置端口。当一个应用程序打开一个端口,它使用默认的配置设置,可能不适合连接的另一端。

9.3 设定序列通信端口

在串行通信编程的最关键的步骤是通过DCB结构体对端口进行设置。错误地初始化DCB结构,是一个普遍问题。当一个串行通信功能没有产生预期的结果,DCB结构可能会犯错。

DCB结构体定义了一个串行通信设备的控制设置。结构体的定义如下:

typedef struct _DCB {

DWORD DCBlength;

DWORD BaudRate; 

DWORD fBinary:1;

DWORD fParity:1;

DWORD fOutxCtsFlow:1;

DWORD fOutxDsrFlow:1;

DWORD fDtrControl:2;

DWORD fDsrSensitivity:1;

DWORD fTXContinueOnXoff:1;

DWORD fOutX: 1;

DWORD fInX: 1;

DWORD fErrorChar:1;

DWORD fNull:1; 

DWORD fRtsControl:2; 

DWORD fAbortOnError:1;

DWORD fDummy2:17;

WORD wReserved;

WORD XonLim; 

WORD XoffLim; 

BYTE ByteSize; 

BYTE Parity; 

BYTE StopBits;

char XonChar; 

char XoffChar; 

char ErrorChar;

char EofChar; 

char EvtChar; 

WORD wReserved1; 

} DCB;

DCB结构体涵括了与一个串行通信设备相关的所有基本参数与信息,例如数据传输速度、数据包的格式、传输协议、流量控制以及信号处理等。

调用CreateFile函数利用默认端口设置来打开一个串行端口。通常,应用程序需要更改默认值。使用GetCommState函数来检索的默认设置,使用SetCommState函数来设置新的端口设置。GetCommState函数的原型为:

BOOL GetCommState(

HANDLE hFile, 

LPDCB lpDCB);

SetCommState函数的原型为:

BOOL SetCommState(

HANDLE hFile, 

LPDCB lpDCB);

两个函数的参数相同。参数hFile代表进行通信的设备的句柄,而lpDCB是存放或写入DCB的结构体。

此外,端口配置使用COMMTIMEOUTS结构设置读/写操作的超时值。当发生超时,ReadFileWriteFile函数返回成功传输的字符的具体数目。

设定串口的步骤如下:

1. 初始化DCB结构体DCBlength的成员结构的大小。在使用DCB结构体之前,DCBlength成员的值必须完成初始化。DCB结构必须是完整的,包括硬件和软件流控制。

2. 调用GetCommState函数来查询用CreateFile函数打开的端口的默认设置。利用CreateFile函数返回的句柄来识别端口。

3. 根据需要修改DCB结构体成员的值。下表显示了DCB结构成员。如表9-6所示。

成员

描述

DCBlength

调用GetCommState函数之前,利用这个成员来设置DCB结构的长度。不设置正确的长度,可能会导致失败或返回错误的数据。

BaudRate

指定设备的通讯速率。成员的值或者是实际的波特率,或者是指向CBR_constan常量的索引。

fBinary

指定是否启用二进制模式。 Win32 API中不支持非二进制模式传输,因此成员的值必须为TURE,使用FALSE将无法工作。

fParity

指定是否启用奇偶校验。如果这个成员是TRUE,执行奇偶校验,并报告错误。

fOutxCtsFlow

打开或关闭CTS流量控制开关。要使用RTS / CTS流量控制,该成员的值指定为TRUE,而且指定fRtsControl成员的值为RTS_CONTROL_HANDSHAKE TRUE

fOutxDsrFlow

打开或关闭DSR流控制开关。 DSR流控制很少使用;在使能DTR线时,该成员一般被设置为FALSE

fDtrControl

设定DTR流量控制。 DTR_CONTROL_ENABL打开DTR线; DTR_CONTROL_HANDSHAKE打开DTR握手; DTR_CONTROL_DISABLE关闭DTR线。

fDsrSensitivity

在通讯驱动程序对DSR信号状态比较敏感时,设置这个成员。如果这个成员为TRUE,则驱动程序忽略任何接收字节,除非DSR modem输入线为高。

fTXContinueOnXoff

在输入缓冲区已满时,而且驱动已经发送了XoffChar字符,该成员指定是否停止传输。

fOutX

指定是否在传输过程中使用XON/ XOFF流量控制。如果这个成员是TRUE,在接收到XoffChar字符时传输停止;当接收到XonChar字符时,再次启动时传输。

fInX

指定是否在接受过程中使用XON/ XOFF流量控制。如果这个成员是TRUE,当输入缓冲区内剩余XoffLim字节时,发送XoffChar字符;当输入缓冲区内只剩XonLim字节时,发送XonChar字符。

fErrorChar

指定是否将发生奇偶校验错误的字节替换为ErrorChar成员指定的字符。如果这个成员是TRUE而且fParity成员为TRUE,允许替换。

fNull

指定是否丢弃空字节。

fRtsControl

打开或关闭RTS流控制。 RTS_CONTROL_ENABLE在连接过程中打开RTS线; RTS_CONTROL_HANDSHAKE打开RTS握手; RTS_CONTROL_DISABLE轮流关闭RTS线。;RTS_CONTROL_TOGGLE在可以传输数据时指定RTS线为高。如果所有缓冲的字节都被发送,RTS线设置为低。

fAbortOnError

指定在出错错误时,是否终止读取和写入操作。如果这个成员是TRUE,驱动程序在出现错误的时候将终止所有读写操作。驱动程序将不接受任何通信,直至应用程序调用ClearCommError函数进行确认。

fDummy2

保留,不可用。

wReserved

不可用,设置为0

XonLim

指定发送XON字符之前,输入缓冲区中最少的字节数。

XoffLim

指定发送XOFF字符之前,输入缓冲区中最多能接收的字节数。

ByteSize

指定发送和接收的字节所包含的位数。

Parity

指定的奇偶机制。不要与打开或关闭奇偶校验的fParity成员混淆。因为很少使用奇偶,这个成员通常设置为NOPARITY

StopBits

指定停止位的数目。 ONESTOPBIT是最常用的设置。

XonChar

指定传输和接收时XON字符的值。

XoffChar

指定传输和接收时XOFF字符的值。

ErrorChar

指定了在发生奇偶错误用于替换的字符的值。

EofChar

指定了用于标识数据结束的字符的值。

EvtChar

指定了用于标识发生事件的字符的值。

WReserved1

保留,不可用。

    表9-6 DCB结构说明

4. 调用SetCommState函数设置新的端口设置。

下面的例子给出了如何设定序列通信端口:

DCB PortDCB;

// Initialize the DCBlength member. 

PortDCB.DCBlength = sizeof (DCB); 

// Get the default port setting information.

GetCommState (hPort, &PortDCB);

// Change the DCB structure settings.

PortDCB.BaudRate = 9600;              // Current baud 

PortDCB.fBinary = TRUE;               // Binary mode; no EOF check 

PortDCB.fParity = TRUE;               // Enable parity checking 

PortDCB.fOutxCtsFlow = FALSE;         // No CTS output flow control 

PortDCB.fOutxDsrFlow = FALSE;         // No DSR output flow control 

PortDCB.fDtrControl = DTR_CONTROL_ENABLE; 

                                      // DTR flow control type 

PortDCB.fDsrSensitivity = FALSE;      // DSR sensitivity 

PortDCB.fTXContinueOnXoff = TRUE;     // XOFF continues Tx 

PortDCB.fOutX = FALSE;                // No XON/XOFF out flow control 

PortDCB.fInX = FALSE;                 // No XON/XOFF in flow control 

PortDCB.fErrorChar = FALSE;           // Disable error replacement 

PortDCB.fNull = FALSE;                // Disable null stripping 

PortDCB.fRtsControl = RTS_CONTROL_ENABLE; 

                                      // RTS flow control 

PortDCB.fAbortOnError = FALSE;        // Do not abort reads/writes on 

                                      // error

PortDCB.ByteSize = 8;                 // Number of bits/byte, 4-8 

PortDCB.Parity = NOPARITY;            // 0-4=no,odd,even,mark,space 

PortDCB.StopBits = ONESTOPBIT;        // 0,1,2 = 1, 1.5, 2 

// Configure the port according to the specifications of the DCB 

// structure.

if (!SetCommState (hPort, &PortDCB))

{

  // Could not configure the serial port.

  MessageBox (hMainWnd, TEXT("Unable to configure the serial port"), 

              TEXT("Error"), MB_OK);

  dwError = GetLastError ();

  return FALSE;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

胡耀文

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值