简介:串口通信广泛应用于工业控制等领域,本文以"CommTest"为例,详细讲解基于VC6.0进行串口通信的程序设计。通过理解串口通信基础、Windows API函数的使用以及关键步骤的实现,开发者可以掌握串口打开、配置、数据传输和异常处理等技术,编写出稳定可靠的串口通信程序。本课程设计项目经过测试,旨在帮助学生掌握串口通信的原理和实践,为在相关领域的应用打下坚实基础。
1. 串口通信基础**
1.1 串口通信概念
串口通信是一种通过串行接口进行数据传输的通信方式,它使用一根或多根导线将两个设备连接起来。串口通信的优点是简单、可靠,并且在工业控制、嵌入式系统等领域得到广泛应用。
1.2 串口通信协议
串口通信协议定义了数据传输的规则,包括数据格式、传输速率、校验方式等。常用的串口通信协议有RS-232、RS-485和RS-422。
2. Windows API函数使用
Windows API概述
Windows API(应用程序编程接口)是微软为Windows操作系统提供的编程接口,它允许应用程序与操作系统交互。Windows API函数提供了广泛的功能,包括文件操作、窗口管理、图形显示、网络通信等。
串口相关API函数
CreateFile()
函数原型:
HANDLE CreateFile(
LPCTSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
);
参数:
| 参数 | 说明 | |---|---| | lpFileName
| 串口设备名称,如"COM1" | | dwDesiredAccess
| 访问模式,如GENERIC_READ
或GENERIC_WRITE
| | dwShareMode
| 共享模式,如FILE_SHARE_READ
或FILE_SHARE_WRITE
| | lpSecurityAttributes
| 安全属性,通常为NULL
| | dwCreationDisposition
| 创建方式,如OPEN_EXISTING
或CREATE_NEW
| | dwFlagsAndAttributes
| 文件属性,如FILE_ATTRIBUTE_NORMAL
| | hTemplateFile
| 模板文件句柄,通常为NULL
|
返回值:
成功返回串口设备句柄,失败返回INVALID_HANDLE_VALUE
。
WriteFile()
函数原型:
BOOL WriteFile(
HANDLE hFile,
LPCVOID lpBuffer,
DWORD nNumberOfBytesToWrite,
LPDWORD lpNumberOfBytesWritten,
LPOVERLAPPED lpOverlapped
);
参数:
| 参数 | 说明 | |---|---| | hFile
| 串口设备句柄 | | lpBuffer
| 发送缓冲区 | | nNumberOfBytesToWrite
| 发送字节数 | | lpNumberOfBytesWritten
| 实际发送字节数 | | lpOverlapped
| 重叠I/O操作,通常为NULL
|
返回值:
成功返回TRUE
,失败返回FALSE
。
ReadFile()
函数原型:
BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);
参数:
| 参数 | 说明 | |---|---| | hFile
| 串口设备句柄 | | lpBuffer
| 接收缓冲区 | | nNumberOfBytesToRead
| 接收字节数 | | lpNumberOfBytesRead
| 实际接收字节数 | | lpOverlapped
| 重叠I/O操作,通常为NULL
|
返回值:
成功返回TRUE
,失败返回FALSE
。
SetCommState()
函数原型:
BOOL SetCommState(
HANDLE hCommDev,
LPCOMMCONFIG lpCC
);
参数:
| 参数 | 说明 | |---|---| | hCommDev
| 串口设备句柄 | | lpCC
| 串口配置结构体 |
返回值:
成功返回TRUE
,失败返回FALSE
。
GetCommState()
函数原型:
BOOL GetCommState(
HANDLE hCommDev,
LPCOMMCONFIG lpCC
);
参数:
| 参数 | 说明 | |---|---| | hCommDev
| 串口设备句柄 | | lpCC
| 串口配置结构体 |
返回值:
成功返回TRUE
,失败返回FALSE
。
3. 串口打开与配置
3.1 串口打开步骤
串口打开操作是串口通信程序的基础,主要步骤如下:
- 获取串口设备句柄:使用
CreateFile()
函数获取指定串口设备的句柄,该句柄用于后续的串口操作。 - 配置串口参数:使用
SetCommState()
函数配置串口通信参数,包括波特率、数据位、停止位和校验位等。 - 设置事件通知:使用
SetCommMask()
函数设置串口事件通知,以便程序可以及时响应串口事件,如数据接收或错误发生。
3.2 串口配置参数
串口配置参数是影响串口通信质量和效率的重要因素,主要包括以下几个方面:
3.2.1 波特率
波特率表示串口每秒传输的数据位数,单位为 bps(比特/秒)。常见的波特率有 9600、19200、38400、57600、115200 等。波特率需要与通信设备匹配,否则会导致数据传输错误。
3.2.2 数据位
数据位表示每个字符传输的数据位数,通常为 5、6、7 或 8 位。数据位越多,传输的数据量越大,但传输速度也会相应降低。
3.2.3 停止位
停止位表示数据传输结束后,发送端发送的停止位数,通常为 1 或 2 位。停止位用于表示数据传输的结束,确保接收端能够正确识别数据帧。
3.2.4 校验位
校验位用于检测数据传输过程中是否发生错误。常见的校验位类型有无校验、奇校验和偶校验。无校验不进行错误检测,奇校验和偶校验则根据数据位中 1 的个数进行校验。
3.3 配置参数示例
以下代码示例展示了如何使用 SetCommState()
函数配置串口通信参数:
// 配置串口通信参数
DCB dcb;
dcb.DCBlength = sizeof(DCB);
GetCommState(hComm, &dcb);
dcb.BaudRate = 9600;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.Parity = NOPARITY;
SetCommState(hComm, &dcb);
其中:
hComm
是串口设备句柄。dcb
是DCB
结构体,用于保存串口通信参数。DCBlength
是DCB
结构体的长度。GetCommState()
函数获取当前串口通信参数。SetCommState()
函数设置串口通信参数。
3.4 参数配置注意事项
在配置串口通信参数时,需要考虑以下注意事项:
- 波特率、数据位、停止位和校验位必须与通信设备匹配。
- 数据位和停止位不能随意更改,否则会导致数据传输错误。
- 校验位可以根据实际需要选择,无校验效率最高,但错误检测能力最弱。
- 配置参数后,需要使用
SetCommState()
函数更新串口通信参数。
4. 数据传输与接收
数据发送流程
数据发送流程包括以下步骤:
- 打开串口:使用
CreateFile()
函数打开串口设备,并获取串口句柄。 - 配置串口:使用
SetCommState()
函数配置串口参数,如波特率、数据位、停止位和校验位。 - 准备发送数据:将要发送的数据准备为字节数组。
- 发送数据:使用
WriteFile()
函数将字节数组发送到串口设备。 - 等待发送完成:使用
WaitForSingleObject()
函数或GetOverlappedResult()
函数等待发送操作完成。
代码块:
// 打开串口
HANDLE hCom = CreateFile(L"COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
// 配置串口
DCB dcb;
GetCommState(hCom, &dcb);
dcb.BaudRate = CBR_9600;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.Parity = NOPARITY;
SetCommState(hCom, &dcb);
// 准备发送数据
char data[] = "Hello world!";
// 发送数据
DWORD dwBytesWritten;
WriteFile(hCom, data, strlen(data), &dwBytesWritten, NULL);
// 等待发送完成
WaitForSingleObject(hCom, INFINITE);
逻辑分析:
CreateFile()
函数打开串口设备,并返回一个句柄hCom
。GetCommState()
函数获取当前串口配置参数。SetCommState()
函数设置串口配置参数,包括波特率、数据位、停止位和校验位。WriteFile()
函数将字节数组data
发送到串口设备。WaitForSingleObject()
函数等待发送操作完成。
数据接收流程
数据接收流程包括以下步骤:
- 打开串口:使用
CreateFile()
函数打开串口设备,并获取串口句柄。 - 配置串口:使用
SetCommState()
函数配置串口参数,如波特率、数据位、停止位和校验位。 - 准备接收数据:分配一个字节数组用于接收数据。
- 接收数据:使用
ReadFile()
函数从串口设备接收数据到字节数组中。 - 等待接收完成:使用
WaitForSingleObject()
函数或GetOverlappedResult()
函数等待接收操作完成。
代码块:
// 打开串口
HANDLE hCom = CreateFile(L"COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
// 配置串口
DCB dcb;
GetCommState(hCom, &dcb);
dcb.BaudRate = CBR_9600;
dcb.ByteSize = 8;
dcb.StopBits = ONESTOPBIT;
dcb.Parity = NOPARITY;
SetCommState(hCom, &dcb);
// 准备接收数据
char data[1024];
// 接收数据
DWORD dwBytesRead;
ReadFile(hCom, data, sizeof(data), &dwBytesRead, NULL);
// 等待接收完成
WaitForSingleObject(hCom, INFINITE);
逻辑分析:
CreateFile()
函数打开串口设备,并返回一个句柄hCom
。GetCommState()
函数获取当前串口配置参数。SetCommState()
函数设置串口配置参数,包括波特率、数据位、停止位和校验位。ReadFile()
函数从串口设备接收数据到字节数组data
中。WaitForSingleObject()
函数等待接收操作完成。
数据处理
接收到的数据需要进行处理,以提取有用的信息。数据处理过程因具体应用而异,但通常包括以下步骤:
- 解析数据:将接收到的字节数组解析为有意义的数据结构。
- 验证数据:检查接收到的数据是否完整且正确。
- 存储数据:将验证通过的数据存储到数据库或其他持久化存储中。
- 显示数据:将处理后的数据显示给用户或其他应用程序。
代码块:
// 解析数据
char *p = data;
int value = atoi(p);
// 验证数据
if (value < 0 || value > 100) {
// 数据不合法
return;
}
// 存储数据
// ...
// 显示数据
printf("接收到的数据:%d\n", value);
逻辑分析:
atoi()
函数将字符串p
转换为整数value
。- 如果
value
不在 [0, 100] 范围内,则数据不合法。 - 将合法数据存储到数据库或其他持久化存储中。
printf()
函数将处理后的数据显示到控制台上。
5. 异常处理**
5.1 串口通信常见异常
在串口通信过程中,可能会遇到各种异常情况,常见异常包括:
- 设备不可用异常:串口设备未正确连接或已损坏。
- 端口已占用异常:串口已被其他程序占用。
- 参数设置错误异常:串口配置参数设置不正确,如波特率、数据位、停止位或校验位。
- 数据传输错误异常:数据传输过程中发生错误,如数据丢失或损坏。
- 缓冲区溢出异常:数据接收缓冲区已满,导致数据丢失。
5.2 异常处理机制
为了处理串口通信异常,可以采用以下机制:
- 错误代码检查:使用Windows API函数
GetLastError()
获取异常错误代码,并根据错误代码进行异常处理。 - 超时机制:设置数据传输和接收超时时间,当超时发生时,视为异常。
- 事件通知:使用Windows API函数
SetCommMask()
和WaitCommEvent()
监听串口事件,并根据事件类型进行异常处理。
5.3 异常恢复策略
异常发生后,可以采取以下恢复策略:
- 重试:重新打开串口,重新配置参数,或重新发送数据。
- 忽略:忽略异常,继续通信。
- 关闭串口:关闭串口,释放资源,并重新打开串口。
- 提示用户:向用户显示异常信息,并提示用户采取相应操作。
代码示例:
// 错误代码检查
DWORD dwError = GetLastError();
switch (dwError) {
case ERROR_INVALID_HANDLE:
// 串口设备不可用
break;
case ERROR_ACCESS_DENIED:
// 端口已占用
break;
// ...
}
// 超时机制
DWORD dwTimeout = 1000; // 1秒超时
BOOL bSuccess = ReadFile(hComm, lpBuffer, dwBytesToRead, &dwBytesRead, &o);
if (!bSuccess && GetLastError() == ERROR_TIMEOUT) {
// 数据接收超时
}
// 事件通知
SetCommMask(hComm, EV_RXCHAR); // 监听接收字符事件
DWORD dwEventMask;
WaitCommEvent(hComm, &dwEventMask, NULL);
if (dwEventMask & EV_RXCHAR) {
// 接收到字符事件
}
简介:串口通信广泛应用于工业控制等领域,本文以"CommTest"为例,详细讲解基于VC6.0进行串口通信的程序设计。通过理解串口通信基础、Windows API函数的使用以及关键步骤的实现,开发者可以掌握串口打开、配置、数据传输和异常处理等技术,编写出稳定可靠的串口通信程序。本课程设计项目经过测试,旨在帮助学生掌握串口通信的原理和实践,为在相关领域的应用打下坚实基础。