当前位置: 首页 > article >正文

windows 驱动实例分析系列-COM驱动的I/O处理

在文章 COM驱动讲解 中,我们讲解了virtualSerial驱动几乎所有代码,但是唯独没有讲解I/O操作,这是因为I/O操作往往关乎驱动的功能,由于那个驱动仅仅作为案例,故我们不打算在上面讲解太多,但实际开发中,serial一般都具有实际的功能,故大部分情况下我们都需要改造之前的umdfserial驱动,让它实际具有一定的功能。

在umdfserial中,写入数据是正确的,但是怎么读取数据是一个问题,实际上作为最经常使用的接口,serial的经典应用是它会源源不断主动上报数据,这个数据往往是调试信息、日志输出、传感器信息等。

所以我们先研究用户层是如何读取数据的,驱动层又是如何上报数据的。

数据上报方式

在windows api中,可以使用ReadFile、ReadFileEx、DeviceIoControl这样的消息来完成从串口读取数据的操作,但这需要解决的问题就是我们如何知道什么时候需要读取数据。

初学者最容易想到的就是使用一个线程持续的读取数据,代码看起来像下面一样:

...

ret = ReadFile(hFile,
        lpBuffer,
        nNumberOfBytesToRead,
        lpNumberOfBytesRead,
        lpOverlapped
    );
...

注意,无论使用同步或者异步,结果都没什么变化,尤其是对于我们的 umdfserial 代码来说。

更机智的做法是深入了解UART的硬件机制,serial本身存在流控的说法,就是当数据到达的时候,它有某种方案通知上层,就是RTS和CTS信号,当然,对于我们来说,我们并没有实际上的信号线,但上层不知道这一点,所以我们只需要装作有RTS和CTS信号的样子就可以了。

不过在那之前,我们先来看一般的串口程序会怎么做,一般的串口读写工具(sscom之类的)往往会使用WaitCommEvent和ClearCommError函数,下面是代码:

#include <windows.h>
#include <tchar.h>
#include <stdio.h>

int main()
{
    HANDLE hCom;
    BOOL fSuccess;
    DWORD dwEvtMask;
    DWORD dwError;
    COMSTAT ComState = { 0 };
    CHAR    buffer[256] = { 0 };

    hCom = CreateFile(COM_NAME,
        GENERIC_READ | GENERIC_WRITE,
        0,    // exclusive access 
        NULL, // default security attributes 
        OPEN_EXISTING,
        FILE_FLAG_OVERLAPPED,
        NULL
    );

    if (hCom == INVALID_HANDLE_VALUE)
    {
        printf("CreateFile failed with error %d.\n", GetLastError());
        return;
    }

    // 设置事件掩码
    fSuccess = SetCommMask(hCom, EV_CTS | EV_DSR | EV_RXCHAR);
    if (!fSuccess)
    {
        printf("SetCommMask failed with error %d.\n", GetLastError());
        return;
    }

    // 等待事件 WaitCommEvent函数会在SetCommMask设定的监听时间发生前返回
    if (WaitCommEvent(hCom, &dwEvtMask, NULL))
    {
        // 这个函数可以获取数据缓冲区的长度
        if (ClearCommError(hCom, &dwError, &ComState))
        {
            DWORD Size = 0;
            DWORD Length = 0;
            while (ComState.cbOutQue != Length)
            {
                if (!ReadFile(hCom, buffer + Length, ComState.cbOutQue, &Size, NULL))
                {
                    break;
                }
                Length

http://www.kler.cn/a/320041.html

相关文章:

  • C语言中的一些小知识(三)
  • uni-app vue3封装websocket,支持微信小程序
  • 《AI设计类工具系列之一——FigJam AI》
  • 深入理解及如何使用main函数参数
  • C++ VECTOR容器
  • 基于大数据可视化的化妆品推荐及数据分析系统
  • 招联金融2025校招内推喇
  • python制表符 \t
  • WebGIS开发四大开源框架对比
  • 微服务配置管理——动态路由
  • SpringBoot开发——整合P6Spy详细记录SQL执行耗时情况
  • Java面试经验总结之MySQL
  • 利士策分享,动摇时刻的自我救赎
  • 一文入门生成式AI(理解ChatGPT的原理)
  • kubernetes K8S 结合 Istio 实现流量治理
  • 探索JMeterTools:一个Python驱动的JMeter脚本生成器
  • llama_deploy
  • Python知识点:如何使用Python与R进行互操作(rpy2)
  • 两种调用智谱AI API的方式
  • 数据结构 ——— C语言实现动态顺序表