使用C语言在Windows 上实现串口通信,可用于嵌入式中通过PC注入数据
【代码】使用C语言在Windows 上实现串口通信,可用于嵌入式中通过PC注入数据。
·
1.完整Demo code
#include <windows.h>
#include <stdio.h>
#define BUFFER_SIZE 256
// 全局变量,存储串口句柄
HANDLE hSerial;
HANDLE hReadThread;
BOOL threadRunning = FALSE;
// 初始化串口
int initialize_serial_port(const char* port_name) {
// 打开串口
hSerial = CreateFile(
port_name, // 串口号,例如 "COM3"
GENERIC_READ | GENERIC_WRITE, // 读写权限
0, // 共享模式,0表示独占
NULL, // 安全属性
OPEN_EXISTING, // 打开已存在的设备
FILE_ATTRIBUTE_NORMAL, // 文件属性
NULL // 模板文件句柄
);
if (hSerial == INVALID_HANDLE_VALUE) {
printf("Error opening serial port\n");
return 1;
}
// 配置串口参数
DCB dcbSerialParams = {0};
if (!GetCommState(hSerial, &dcbSerialParams)) {
printf("Error getting serial port state\n");
CloseHandle(hSerial);
return 1;
}
dcbSerialParams.BaudRate = CBR_9600; // 波特率
dcbSerialParams.ByteSize = 8; // 数据位
dcbSerialParams.StopBits = ONESTOPBIT;// 停止位
dcbSerialParams.Parity = NOPARITY; // 校验位
if (!SetCommState(hSerial, &dcbSerialParams)) {
printf("Error setting serial port state\n");
CloseHandle(hSerial);
return 1;
}
// 设置超时
COMMTIMEOUTS timeouts = {0};
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(hSerial, &timeouts)) {
printf("Error setting timeouts\n");
CloseHandle(hSerial);
return 1;
}
printf("Serial port initialized successfully\n");
return 0;
}
// 关闭串口
void close_serial_port() {
if (hSerial != INVALID_HANDLE_VALUE) {
CloseHandle(hSerial);
printf("Serial port closed\n");
}
}
// 写数据到串口
int write_to_serial_port(const char* data) {
DWORD bytesWritten;
if (!WriteFile(hSerial, data, strlen(data), &bytesWritten, NULL)) {
printf("Error writing to serial port\n");
return 1;
}
printf("Sent: %s\n", data);
return 0;
}
// 从串口读取数据
int read_from_serial_port(char* buffer, int buffer_size) {
DWORD bytesRead;
if (!ReadFile(hSerial, buffer, buffer_size - 1, &bytesRead, NULL)) {
printf("Error reading from serial port\n");
return 1;
}
buffer[bytesRead] = '\0'; // 添加字符串结束符
printf("Received: %s\n", buffer);
return 0;
}
// 读取线程函数
DWORD WINAPI SerialReadThread(LPVOID lpParam)
{
OVERLAPPED ov = {0};
char buffer[BUFFER_SIZE];
DWORD bytesRead;
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (ov.hEvent == NULL)
{
ErrorHandler(TEXT("CreateEvent"));
return 1;
}
printf("Serial read thread started.\n");
while (threadRunning)
{
if (!ReadFile(hCom, buffer, BUFFER_SIZE - 1, &bytesRead, &ov))
{
if (GetLastError() != ERROR_IO_PENDING)
{
printf("Error reading from serial port\n");
break;
}
// 等待读取完成
WaitForSingleObject(ov.hEvent, INFINITE);
GetOverlappedResult(hCom, &ov, &bytesRead, FALSE);
}
if (bytesRead > 0)
{
buffer[bytesRead] = '\0'; // 确保字符串终止
printf("Received %d bytes: ", bytesRead);
// 打印十六进制格式
for (DWORD i = 0; i < bytesRead; i++)
{
printf("%02X ", (unsigned char)buffer[i]);
}
printf("\n");
// 也可以打印ASCII格式
// printf("Data: %s\n", buffer);
// 也可以解析数据并根据数类型分发给不同的队列到task中处理
}
}
CloseHandle(ov.hEvent);
printf("Serial read thread exiting.\n");
return 0;
}
// 主函数
int main() {
const char* port_name = "COM3"; // 串口号
char buffer[256];
// 初始化串口
if (initialize_serial_port(port_name) {
return 1;
}
// 发送数据
if (write_to_serial_port("Hello, Serial Port!")) {
close_serial_port();
return 1;
}
/*
// 接收数据
if (read_from_serial_port(buffer, sizeof(buffer))) {
close_serial_port();
return 1;
}
*/
// 创建并启动读取线程
threadRunning = TRUE;
hReadThread = CreateThread(
NULL, // 默认安全属性
0, // 默认堆栈大小
SerialReadThread, // 线程函数
NULL, // 无参数
0, // 默认创建标志
NULL); // 不需要线程ID
if (hReadThread == NULL)
{
close_serial_port();
return 1;
}
printf("Press Enter to exit...\n");
getchar(); // 等待用户输入以退出
// 清理
threadRunning = FALSE;
// 等待线程结束
WaitForSingleObject(hReadThread, 2000);
CloseHandle(hReadThread);
// 关闭串口
close_serial_port();
printf("Program exited.\n");
return 0;
}
2.代码说明
-
initialize_serial_port
函数:- 负责打开串口并配置串口参数(波特率、数据位、停止位、校验位等)。
- 参数
port_name
是串口号,例如"COM3"
。 - 返回
0
表示成功,1
表示失败。
-
close_serial_port
函数:- 负责关闭串口。
- 如果串口句柄有效,则调用
CloseHandle
关闭串口。
-
write_to_serial_port
函数:- 负责向串口发送数据。
- 参数
data
是要发送的字符串。 - 返回
0
表示成功,1
表示失败。
-
read_from_serial_port
函数:- 负责从串口读取数据。
- 参数
buffer
是用于存储读取数据的缓冲区,buffer_size
是缓冲区大小。 - 返回
0
表示成功,1
表示失败。
-
SerialReadThread
函数:- 用于处理串口读取的数据
- 可以根据不同类型的数据分发给不同的task
-
主函数:
- 调用上述函数完成串口初始化、发送数据、接收数据和关闭串口的操作。
3.使用方法
- 修改
port_name
为实际的串口号(例如"COM3"
)。 - 编译并运行程序。
- 程序会发送
"Hello, Serial Port!"
到串口,并尝试从串口读取数据。
4.其他参考案例
更多推荐
所有评论(0)