• 串口通讯:


    一、

    1.在用ReadFile和WriteFile读写串口时,既可以同步执行,也可以重叠执行
        在同步执行时,函数直到操作完成后才返回。这意味着同步执行时线程会被阻塞,从而导致效率下降。
        在重叠执行时,即使操作还未完成,这两个函数也会立即返回,费时的I/O操作在后台进行。
    2.ReadFile和WriteFile函数是同步还是异步由CreateFile函数决定:
        如果在调用CreateFile创建句柄时<指定了FILE_FLAG_OVERLAPPED标志>,那么调用ReadFile和WriteFile对该句柄进行的操作就应该是重叠的;
        如果未指定重叠标志,则读写操作应该是同步的。
    ReadFile和WriteFile函数的同步或者异步应该和CreateFile函数相一致。

    3.ReadFile函数只要在串口 <输入缓冲区> 中读入指定数量的字符,就算完成操作。
      WriteFile函数不但要把指定数量的字符拷入到 <输出缓冲区>,而且要 <等> 这些字符从串行口 <送出去>后才算完成操作。
    如果操作成功,这两个函数都返回TRUE。
          需要注意的是,当ReadFile和WriteFile <返回FALSE时,不一定就是操作失败>,线程应该调用GetLastError函数分析返回的结果。
            例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING:这说明重叠操作还未完成,正在后台运行。

    3.重叠I/O非常灵活,它也可以实现阻塞(例如我们可以设置一定要读取到一个数据才能进行到下一步操作)。
    两种方法可以 <等待> 操作完成:
        一种方法是用像WaitForSingleObject这样的等待函数来等待OVERLAPPED结构的hEvent成员;
        另一种方法是调用GetOverlappedResult函数等待

    二、串口通讯大致步骤:

    (一)、open()打开串口“读”

    1 打开串口函数(以异步(重叠)IO打开串口)m_hCommHandle标识通讯端口的句柄

        m_hCommHandle = CreateFile(szComm,          //COM

                        GENERIC_READ | GENERIC_WRITE,   //允许读和写

                        0,                              //独占方式

                        NULL,

                        OPEN_EXISTING,                  //打开而不是创建

                        FILE_FLAG_OVERLAPPED,           //重叠方式

                        NULL);

    2获取串口当前配置函数

        GetCommState(m_hCommHandle, &dcb);

            dcb.BaudRate = dwBaudRate;//当前波特率

            dcb.ByteSize = byByteSize;//数据位数

            dcb.Parity = byParity;//奇偶校验

            dcb.StopBits = byStopBits;//停止位

    3配置串口函数(设置COM口的设备控制块)

        SetCommState(m_hCommHandle, &dcb))

    4将串口DTR线路升成高电位

        EscapeCommFunction(m_hCommHandle, SETDTR);

        要实现自己的流控制时。此时应用必须负责RTSDTR信号线的状态改变。

    5设置串行口的输入和输出缓冲区的大小

        SetupComm(m_hCommHandle, 4096, 4096))

    6在读写串口之前,要用PurgeComm()函数清空缓冲区,终止正在进行的读写操作

        PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR))//清空缓冲区

    7创建一个线程用于接收串口的数据

    8、线程函数中“实时读串口”

    8.1 设置要监控的事件

    SetCommMask(m_hCommHandle, EV_RXCHAR | EV_ERR);

        EV_RXCHAR输入缓冲区中已收到数据

    8.2 等待串口通信事件的发生;

    WaitCommEvent(m_hCommHandle, &dwMask, &m_eventOverlapped))

        GetOverlappedResult该函数返回重叠操作的结果:用来判断异步操作是否完成;

    8.3 读串口 ReadFile()数据:

        GetOverlappedResult该函数返回重叠操作的结果:用来判断异步操作是否完成;

    8.4 接收完成后,进入RecvDataEvent响应函数(注册过SerialPort的类会实现RecvDataEvent函数)

    ()Send()发送数据,写串口

    9、写串口

    9.1 立即终止异步发送+清空发送缓存区

        PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);

    9.2 写串口

        WriteFile(m_hCommHandle, vpData, dwDataLen, &dwWriteLen, &m_writeOverlapped)

        GetOverlappedResult该函数返回重叠操作的结果:用来判断异步操作是否完成;

    9.3 调用子类的回调函数SendDataEvent函数,实现发送

    ()close()关闭串口

    10. 关闭串口

        WaitForSingleObject(m_hThread, INFINITE);//等线程结束后关闭

        CloseHandle(m_hThread);//关闭线程句柄

        EscapeCommFunction(m_hCommHandle, CLRDTR);//DTR线路降成低电位

        PurgeComm(m_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); //终止读写/清空缓冲区函数

        CloseHandle(m_hCommHandle);//关闭串口

  • 相关阅读:
    【C语言】函数的定义、传参与调用(二)
    每日一题(LeetCode)----数组--螺旋矩阵(一)
    LuatOS-SOC接口文档(air780E)-- i2s - 数字音频
    写论文工具:LaTex在线网站
    洛谷刷题C语言:USPON、ZBROJ、KARTE、最急救助、可持久化动态仙人掌的直径问题
    SOA和微服务是一回事吗
    什么是期权撮合成交?了解期权撮合成交规则。
    【Elasticsearch专栏 02】深入探索:Elasticsearch为什么使用倒排索引而不是正排索引
    e.target 原生js 没有 $event的 自定义属性值 传参
    springboot基于web的在线问答社区系统设计与实现毕业设计源码061628
  • 原文地址:https://blog.csdn.net/zxf347085420/article/details/134422066