• 【Arduino】使用C#实现Arduino与电脑进行串行通讯


    在给Arduino编程的时候,因为没有调试工具,经常要通过使用串口通讯的方式调用Serial.print和Serial.println输出Arduino运行过程中的相关信息,然后在电脑上用Arduino IDE的Serial Monitor来查看print出来的信息。Serial Monitor不仅可以接受Arduino发送到电脑的数据,还可以向Arduino发送数据,进行双向通讯。但是这种通讯方式太过于简陋,是纯粹的手工方式,只适合调试。如果需要在电脑上通过可视化界面与Arduino进行交互,或者对Arduino发送到电脑上的数据进行处理,就需要在电脑上编程了。说的专业一点就是上位机与下位机的通讯。本文就介绍一下如何使用C#实现Arduino与电脑进行串行通讯。
    1、C#串口编程基础
    在C#中有一个串口类System.IO.Ports.SerialPort,这个类的实例就对应设备管理器中的串口。
    比如 SerialPort port = new SerialPort("COM4")
    这句代码就定义了一个串口实例,对应下图中的USB Serial Port(COM4)
    SerialPort常用方法包括Open, Close, Read, ReadLine, Write, WriteLine。这些方法通过名称就很容易理解它们的用法。
     
    2、Arduino串口编程基础
    Arduino中的Serial和C#的SerialPort用法类似,有available, begin, read, readBytes, write, print, println,从名称上也很容易理解。具体用法可以参考官方文档:http://arduino.cc/en/Reference/Serial
    一般我们会在Arduino代码的setup方法中添加Serial.begin(9600),然后在serialEvent方法中读取接收到的数据。
     
    3、实例
    实例的场景为:
    1、Arduino上接一个光线传感器,通过模拟口周期性读取亮度值。
    2、在电脑上向Arduino发送一个开始发送数据的命令后,点亮Arduino上13号数字口的LED,然后Arduino通过串口向电脑发送亮度值。
    3、在电脑上向Arduino发送一个停止发送数据的命令后,关闭Arduino上13号数字口的LED,然后Arduino停止通过串口向电脑发送亮度值。
    这个场景包含了Arduino和电脑的双向通讯。
    示例采用WinForm,界面如下:

    “串口列表”中自动加载电脑上的可用串口名称。
    点击“开始读取”按钮,根据选择的串口名称实例化一个串口对象,指定串口的DataReceived事件处理方法。然后调用ChangeArduinoSendStatus方法向Arduino发送“serial start”命令。
    点击“停止读取”按钮,向Arduino发送“serial stop”命令,关闭串口并销毁实例。
    点击“开始发送”或“停止发送”按钮,调用ChangeArduinoSendStatus方法向Arduino发送“serial start”或“serial stop”命令,让Arduino开始通过串口向电脑发送数据或停止向电脑发送数据。
    串口在接收到数据后出发DataReceived事件,在事件处理方法中调用RefreshInfoTextBox方法,读取串口的数据并追加到界面的文本框。注意:串口的DataReceived事件是由后台线程执行,要把读取到的数据显示在WinFrom界面,需要使用控件的Invoke方法才能刷新界面。
     
    C#核心代码如下:
    private SerialPort port = null;
    /// <summary>
    /// 初始化串口实例
    /// </summary>
    private void InitialSerialPort()
    {
        try
        {
            string portName = this.cmbSerials.SelectedItem.ToString();
            port = new SerialPort(portName, 9600);
            port.Encoding = Encoding.ASCII;
            port.DataReceived += port_DataReceived;
            port.Open();
            this.ChangeArduinoSendStatus(true);
        }
        catch (Exception ex)
        {
            MessageBox.Show("初始化串口发生错误:" + ex.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
    }
     
    /// <summary>
    /// 关闭并销毁串口实例
    /// </summary>
    private void DisposeSerialPort()
    {
        if (port != null)
        {
            try
            {
                this.ChangeArduinoSendStatus(false);
                if (port.IsOpen)
                {
                    port.Close();
                }
                port.Dispose();
            }
            catch (Exception ex)
            {
                MessageBox.Show("关闭串口发生错误:" + ex.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
    }
     
    /// <summary>
    /// 改变Arduino串口的发送状态
    /// </summary>
    /// <param name="allowSend">是否允许发送数据</param>
    private void ChangeArduinoSendStatus(bool allowSend)
    {
        if (port != null && port.IsOpen)
        {
            if (allowSend)
            {
                port.WriteLine("serial start");
            }
            else
            {
                port.WriteLine("serial stop");
            }
        }
    }
     
    /// <summary>
    /// 从串口读取数据并转换为字符串形式
    /// </summary>
    /// <returns></returns>
    private string ReadSerialData()
    {
        string value = "";
        try
        {
            if (port != null && port.BytesToRead > 0)
            {
                value = port.ReadExisting();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("读取串口数据发生错误:" + ex.Message, "提示信息", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
     
        return value;
    }
     
    /// <summary>
    /// 在读取到数据时刷新文本框的信息
    /// </summary>
    private void RefreshInfoTextBox()
    {
        string value = this.ReadSerialData();
        Action<string> setValueAction = text => this.txtInfo.Text += text;
     
        if (this.txtInfo.InvokeRequired)
        {
            this.txtInfo.Invoke(setValueAction, value);
        }
        else
        {
            setValueAction(value);
        }
    }
     
    Arduino代码
    代码注释很详细,就不再做解释。
    int pinLed = 13;//定义连接LED的数字口,当允许通过串口发送数据时,点亮LED,否则关闭LED
    boolean sendFlag = false;//指示是否允许通过串口发送数据
    boolean readCompleted = false;//指示是否完成读取串口数据
    String serialString = "";//串口数据缓存字符串
     
    //Author:Alex Leo, Email:conexpress@qq.com, Blog:http://conexpress.cnblogs.com/
    //参考:http://arduino.cc/en/Reference/Serial
    void setup()
    {
      pinMode(pinLed,OUTPUT);
      Serial.begin(9600);
      serialString.reserve(200);//初始化字符串
    }
     
    void loop()
    {
      int lightValue = analogRead(A0);//从A0口读取光线传感器的值
      if(readCompleted)//判断串口是否接收到数据并完成读取
      {
        Serial.print("read value:");
        Serial.println(serialString);//将读取到的信息发送给电脑
        if(serialString == "serial start")//当读取到的信息是"serial start"时,设置发送标志设置为true
        {
          sendFlag = true;
        }
        else if(serialString == "serial stop")//当读取到的信息是"serial stop"时,设置发送标志设置为false
        {
          sendFlag = false;
        }
        serialString = "";
        readCompleted = false;
      }
     
      if(sendFlag)//如果允许通过串口发送数据,则点亮LED并发送数据,否则关闭LED
      {
        digitalWrite(pinLed, HIGH);
        Serial.print("light value:");
        Serial.println(lightValue);
      }
      else
      {
        digitalWrite(pinLed, LOW);
      }
      delay(1000);//延时1000ms
    }
     
    void serialEvent()//串口事件处理方法,参考:http://arduino.cc/en/Tutorial/SerialEvent
    {
      while(Serial.available())//参考://arduino.cc/en/Serial/Available
      {
        char inChar = (char)Serial.read();
        if(inChar != ' ')//以换行符作为读取结束标志
        {
          serialString += inChar;
        }
        else
        {
          readCompleted = true;
        }
      }
    }
     
     
     





  • 相关阅读:
    Buffer lock
    union all合并记录
    欢迎您在新浪博客安家
    热点块引发的cache buffers cahins latch
    linux下能ping ip不能ping域名详解
    简易计算器页面
    学生管理系统报错(一)
    低效的SQL引发的cache buffers chains latch
    常用监控SQL
    C/C++ XMPP/Jabber 客户端类库对比/点评
  • 原文地址:https://www.cnblogs.com/conexpress/p/Arduino_Connecte_Compute_With_SerialPort.html
Copyright © 2020-2023  润新知