C语言writecom如何实现串口通信?

99ANYc3cd6
预计阅读时长 19 分钟
位置: 首页 C语言 正文

在标准的C语言库(如ANSI C)中,并没有一个叫做 WriteComm 的函数。

c语言writecom
(图片来源网络,侵删)

WriteComm 是一个在 Windows 平台下,用于串口通信的函数,它通常不是直接由Windows API提供,而是由许多第三方串口通信库(如C++的SerialPort类封装)或者是一些老旧的、特定框架中定义的函数名,其底层实现最终还是调用了Windows的API函数。

当你在C语言中看到 WriteComm 时,可以理解为它是一个自定义函数库函数,其目的是封装Windows的串口写入操作,使其使用起来更简单。


WriteComm 的核心功能

WriteComm 函数的核心功能是:向一个已经打开的串口设备发送数据。

它的原型通常类似于这样:

c语言writecom
(图片来源网络,侵删)
// 这是一个常见的自定义函数原型
int WriteComm(HANDLE hComm, const char* lpBuffer, DWORD dwNumberOfBytesToWrite);

参数解释:

  • hComm: 一个句柄,代表一个已经打开的串口,这个句柄通常由另一个打开串口的函数(比如自定义的 OpenComm 或直接调用Windows的 CreateFile)返回。
  • lpBuffer: 一个指向字符缓冲区的指针,缓冲区中包含了你想要发送的数据。
  • dwNumberOfBytesToWrite: 你想要发送的字节数。

返回值:

  • 成功时,通常返回实际写入的字节数
  • 失败时,通常会返回 -10,你可以通过调用 GetLastError() 获取具体的错误码。

如何在C语言中使用 WriteComm(模拟实现)

既然 WriteComm 不是标准函数,我们无法直接使用,要实现它,最直接的方法是调用Windows的底层API函数 WriteFileWriteFile 是Windows中用于向文件、设备(包括串口)写入数据的通用函数。

下面我们通过一个完整的例子来展示如何自定义一个 WriteComm 函数,并使用它来向串口发送 "Hello, Serial Port!" 字符串。

c语言writecom
(图片来源网络,侵删)

完整代码示例

#include <windows.h>   // Windows API头文件
#include <stdio.h>    // 标准输入输出
// 自定义的 WriteComm 函数
// 封装了 Windows API 的 WriteFile
int WriteComm(HANDLE hComm, const char* lpBuffer, DWORD dwNumberOfBytesToWrite) {
    if (hComm == INVALID_HANDLE_VALUE) {
        printf("错误:无效的串口句柄,\n");
        return -1;
    }
    DWORD dwBytesWritten; // 用于存储实际写入的字节数
    BOOL bResult = WriteFile(
        hComm,              // 串口句柄
        lpBuffer,           // 数据缓冲区
        dwNumberOfBytesToWrite, // 要写入的字节数
        &dwBytesWritten,    // 用于接收实际写入的字节数
        NULL                // 同步操作,不使用异步结构体
    );
    if (bResult && dwBytesWritten == dwNumberOfBytesToWrite) {
        // 成功写入所有字节
        return dwBytesWritten;
    } else {
        // 写入失败
        printf("写入失败!错误码: %lu\n", GetLastError());
        return -1;
    }
}
int main() {
    // 1. 打开串口
    // COM3 是一个常见的串口号,请根据你的实际情况修改
    HANDLE hSerial = CreateFile(
        "COM3",                      // 串口设备名
        GENERIC_WRITE,               // 指定写访问
        0,                           // 不共享设备
        NULL,                        // 默认安全属性
        OPEN_EXISTING,               // 打开已存在的设备
        0,                           // 默认属性
        NULL                         // 不使用模板文件
    );
    if (hSerial == INVALID_HANDLE_VALUE) {
        printf("无法打开串口 COM3,请检查串口号和设备管理器,\n");
        printf("错误码: %lu\n", GetLastError());
        return 1;
    }
    printf("串口 COM3 打开成功,\n");
    // 2. 配置串口参数(非常重要!)
    DCB dcbSerialParams = { 0 };
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams)) {
        printf("获取串口状态失败,\n");
        CloseHandle(hSerial);
        return 1;
    }
    // 配置波特率、数据位、停止位、校验位
    // 9600 bps, 8 data bits, no parity, 1 stop bit (8N1)
    dcbSerialParams.BaudRate = CBR_9600;
    dcbSerialParams.ByteSize = 8;
    dcbSerialParams.StopBits = ONESTOPBIT;
    dcbSerialParams.Parity = NOPARITY;
    if (!SetCommState(hSerial, &dcbSerialParams)) {
        printf("设置串口状态失败,\n");
        CloseHandle(hSerial);
        return 1;
    }
    printf("串口参数设置成功 (9600, 8, N, 1),\n");
    // 3. 使用自定义的 WriteComm 函数发送数据
    char dataToSend[] = "Hello, Serial Port!\r\n"; // \r\n 是回车换行,很多设备需要
    DWORD dataSize = strlen(dataToSend);
    int bytesWritten = WriteComm(hSerial, dataToSend, dataSize);
    if (bytesWritten > 0) {
        printf("成功发送了 %d 字节的数据: \"%s\"\n", bytesWritten, dataToSend);
    } else {
        printf("数据发送失败,\n");
    }
    // 4. 关闭串口
    CloseHandle(hSerial);
    printf("串口已关闭,\n");
    return 0;
}

代码步骤解析

  1. 包含头文件: #include <windows.h> 是必须的,它包含了所有Windows API的定义。
  2. 定义 WriteComm 函数:
    • 它接收串口句柄 hComm、数据缓冲区 lpBuffer 和要发送的字节数 dwNumberOfBytesToWrite
    • 内部调用 WriteFile 来执行实际的写入操作。
    • WriteFile 是一个同步函数,会阻塞程序直到数据被写入或发生错误。
    • 检查 WriteFile 的返回值和 dwBytesWritten,确保所有请求的字节都已成功发送。
  3. main 函数:
    • CreateFile: 打开串口,获取一个句柄 hSerialGENERIC_WRITE 表示我们只需要写入权限。
    • GetCommStateSetCommState: 这是串口通信的关键步骤,必须先获取当前的配置,然后修改为你需要的参数(如波特率9600、8位数据位等),再设置回去,如果参数不匹配,通信会失败。
    • 调用 WriteComm: 准备好要发送的数据字符串,然后调用我们自定义的函数发送。
    • CloseHandle: 操作完成后,必须关闭串口句柄,释放系统资源。

跨平台问题

WriteComm 的实现是平台相关的。

  • Windows: 使用 CreateFile, WriteFile, SetCommState 等 API。
  • Linux / macOS: 串口被当作普通的文件设备,操作方式与文件I/O完全相同。
    • 打开: open("/dev/ttyS0", O_WRONLY) (注意是 O_WRONLYO_RDWR)
    • 写入: write()
    • 配置: 使用 termios.h 库中的函数来设置波特率等参数(cfsetispeed, cfsetospeed, tcsetattr)。
    • 关闭: close()

如果你编写的程序需要跨平台,就不能依赖 WriteComm 这样的Windows特定函数,你需要使用跨平台的库,

  • Boost.Asio: C++的跨平台网络和串口库。
  • libserial: 一个专门为C++设计的跨平台串口库。
  • Poco Library: 另一个功能强大的C++跨平台库。
特性 说明
函数性质 非标准C函数,是Windows平台下的自定义或库函数。
核心功能 向已打开的串口发送数据。
底层实现 在Windows上,它通常是对 WriteFile API的封装。
使用前提 必须先成功打开串口并配置好参数(波特率、数据位等)。
关键API CreateFile, WriteFile, SetCommState, CloseHandle
跨平台 ,在Linux/macOS上需要使用 open, write, termios.h 等不同的API。

希望这个详细的解释能帮助你完全理解 WriteComm 在C语言中的作用和实现方式!

-- 展开阅读全文 --
头像
C语言elevator项目如何实现?
« 上一篇 04-15
织梦缩略图不加水印
下一篇 » 04-15

相关文章

取消
微信二维码
支付宝二维码

目录[+]