zoukankan      html  css  js  c++  java
  • 串行通讯之.NET SerialPort异步写数据

    1说明    2

    1 为什么需要异步写数据?    2

    2 异步写数据的代码    2

    3 源代码    4

    1说明

    1 为什么需要异步写数据?

    如下图所示,以波特率300打开一个串口。

    图1

    单击"同步发送"按钮,则数据未发送完之前写数据的函数不会返回。波特率300,每秒大概能发送25个字符,发送500个字符就需要20秒。这20秒之内,整个程序将处于假死状态。

    单击"异步发送"按钮,就不会出现假死状态。

    2 异步写数据的代码

    异步写数据的代码如下:

    private void btnWriteAsync_Click(object sender, EventArgs e)

    {//异步写

    byte[] byt = System.Text.Encoding.Default.GetBytes(txtSend.Text);

    if(byt!=null && byt.Length > 0)

    {

    IntPtr hComm = GetCommHandle(m_sp);

    UInt32 w = 0;

    m_ov.hEvent = IntPtr.Zero;

    m_ov.Internal = IntPtr.Zero;

    m_ov.InternalHigh = IntPtr.Zero;

    m_ov.Offset = 0;

    m_ov.OffsetHigh = 0;

    WriteFile(hComm, byt, (UInt32)byt.Length, ref w, ref m_ov);

    }

    }

    要点为:

    1GetCommHandle函数获取.NET SerialPort对象的串口句柄hComm

    2)调用WriteFile函数,异步写数据。

    以下是结构OVERLAPPED的声明、函数WriteFile的声明、函数GetCommHandle的实现:

    [StructLayout(LayoutKind.Sequential,Pack=4)]

    public struct OVERLAPPED

    {

    public IntPtr Internal;

    public IntPtr InternalHigh;

    public UInt32 Offset;

    public UInt32 OffsetHigh;

    public IntPtr hEvent;

    }

    [DllImport("kernel32.dll", SetLastError = true

    , CallingConvention = CallingConvention.Winapi)]

    private static extern UInt32 WriteFile(IntPtr hFile, byte[] lpBuffer

    , UInt32 nNumberOfBytesToWrite

    , ref UInt32 lpNumberOfBytesWritten

    , ref OVERLAPPED lpOverlapped);

     

    protected System.IO.Ports.SerialPort m_sp =

    new System.IO.Ports.SerialPort();

    protected OVERLAPPED m_ov;

     

    static IntPtr GetCommHandle(System.IO.Ports.SerialPort sp)

    {//获得串口句柄,供 Win32 API 使用

    IntPtr hComm = IntPtr.Zero;

    if (sp != null)

    {

    object stream = typeof(System.IO.Ports.SerialPort).GetField("internalSerialStream", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(sp);

    var handle = (Microsoft.Win32.SafeHandles.SafeFileHandle)stream.GetType().GetField("_handle", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance).GetValue(stream);

    hComm = handle.DangerousGetHandle();

    }

    return hComm;

    }

    3 源代码

    本文的代码已上传至git服务器:

    https://github.com/hanford77/Exercise

    https://git.oschina.net/hanford/Exercise

    在目录 SerialPortc# 目录内。

  • 相关阅读:
    PostgreSQL 数据库备份与恢复 pd_dump pg_restore
    给数据库减负的7个技巧
    添加二级域名 配置多站点 阿里云
    PHP 循环输出多重数组元素
    CentOS 7 yum Loaded plugins: fastestmirror, langpacks Loading mirror speeds from cached hostfile
    CentOS 7 配置 nginx php-fpm 详细教程
    Centos7 卸载 Nginx 并重新安装 Nginx
    centos7 取消自动锁屏
    composer 安装以及使用教程
    MacBook Pro设置外接显示器竖屏显示 切换主显示器
  • 原文地址:https://www.cnblogs.com/hanford/p/6135470.html
Copyright © 2011-2022 走看看