异步方式串口收发数据

举报
Rolle 发表于 2024/10/30 23:40:33 2024/10/30
【摘要】 在现代软件开发中,串口通信仍然是一个重要的领域,尤其是在嵌入式系统、工业控制和物联网设备中。Windows操作系统提供了一套完整的API来支持串口通信,包括同步和异步两种模式。本文将重点介绍如何在Windows平台上使用异步方式进行串口数据的收发。异步串口通信概述异步串口通信是指在数据传输过程中,发送方和接收方不需要严格的时钟同步,而是依赖于数据包的起始位和停止位来标识数据的开始和结束。这种...

在现代软件开发中,串口通信仍然是一个重要的领域,尤其是在嵌入式系统、工业控制和物联网设备中。Windows操作系统提供了一套完整的API来支持串口通信,包括同步和异步两种模式。本文将重点介绍如何在Windows平台上使用异步方式进行串口数据的收发。

  1. 异步串口通信概述
    异步串口通信是指在数据传输过程中,发送方和接收方不需要严格的时钟同步,而是依赖于数据包的起始位和停止位来标识数据的开始和结束。这种方式适用于数据传输速率较低、传输距离较短的场景。

  2. 异步串口通信的特点
    异步串口通信具有以下特点:

字符为单位:以字符为单位进行数据传输。
起始位和停止位:每个字符的开始和结束由起始位和停止位标识。
无外部时钟同步:发送方和接收方不需要外部时钟信号同步。
适用于低速传输:由于每个字符都需要额外的起始位和停止位,因此传输效率相对较低。
3. Windows串口编程API
Windows提供了一系列的API来支持串口编程,包括:

CreateFile:用于打开串口。
CloseHandle:用于关闭串口。
ReadFile和WriteFile:用于同步读取和写入串口数据。
SetCommMask和WaitCommEvent:用于设置串口事件和等待事件。
SetupComm:用于设置串口的输入输出缓冲区大小。
GetCommState和SetCommState:用于获取和设置串口的配置参数。
GetCommTimeouts和SetCommTimeouts:用于获取和设置串口的超时参数。
DeviceIoControl:用于发送IOCTL命令。
4. 异步串口通信的实现
4.1 打开串口
使用CreateFile函数打开串口时,需要指定FILE_FLAG_OVERLAPPED标志以启用异步模式。
HANDLE hSerial = CreateFile(L"COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (hSerial == INVALID_HANDLE_VALUE) {
// 打开串口失败处理
}
4.2 配置串口
使用SetCommState函数配置串口的波特率、数据位、停止位和奇偶校验等参数。
DCB dcbSerialParams = {0};
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
GetCommState(hSerial, &dcbSerialParams);
dcbSerialParams.BaudRate = CBR_9600;
dcbSerialParams.ByteSize = 8;
dcbSerialParams.StopBits = ONESTOPBIT;
dcbSerialParams.Parity = NOPARITY;
SetCommState(hSerial, &dcbSerialParams);
4.3 设置异步读写缓冲区
使用SetupComm函数设置串口的输入输出缓冲区大小。
SetupComm(hSerial, 4096, 4096); // 设置输入输出缓冲区大小
4.4 异步读取串口数据
使用ReadFile函数进行异步读取时,需要提供一个OVERLAPPED结构体,并且可以指定一个事件句柄来等待操作完成。
OVERLAPPED overlappedRead;
ZeroMemory(&overlappedRead, sizeof(OVERLAPPED));
overlappedRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (overlappedRead.hEvent == NULL) {
// 创建事件失败处理
}

DWORD bytesRead;
BOOL bReadStatus = ReadFile(hSerial, buffer, sizeof(buffer), &bytesRead, &overlappedRead);
if (!bReadStatus && GetLastError() != ERROR_IO_PENDING) {
// 读取失败处理
}
4.5 异步发送串口数据
使用WriteFile函数进行异步发送时,同样需要提供一个OVERLAPPED结构体。
OVERLAPPED overlappedWrite;
ZeroMemory(&overlappedWrite, sizeof(OVERLAPPED));
overlappedWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (overlappedWrite.hEvent == NULL) {
// 创建事件失败处理
}

DWORD bytesWritten;
BOOL bWriteStatus = WriteFile(hSerial, dataToSend, sizeof(dataToSend), &bytesWritten, &overlappedWrite);
if (!bWriteStatus && GetLastError() != ERROR_IO_PENDING) {
// 发送失败处理
}
4.6 等待异步操作完成
使用WaitForSingleObject或GetOverlappedResult函数等待异步操作完成。
DWORD waitResult = WaitForSingleObject(overlappedRead.hEvent, INFINITE);
if (waitResult == WAIT_OBJECT_0) {
// 读取操作完成
}

// 或者使用GetOverlappedResult函数
if (GetOverlappedResult(hSerial, &overlappedRead, &bytesRead, FALSE)) {
// 读取操作完成
}
4.7 关闭串口
完成串口操作后,应使用CloseHandle函数关闭串口。
CloseHandle(hSerial);
5. 异步串口通信的注意事项
在异步操作中,确保正确处理OVERLAPPED结构体和事件句柄。
使用ClearCommError和GetCommError函数来处理串口错误。
在多线程环境中,注意线程安全和同步问题。

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。