【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。这些方法通过名称就很容易理解它们的用法。

具体类信息可以参考MSDN:http://msdn.microsoft.com/zh-cn/library/vstudio/System.IO.Ports.SerialPort(v=vs.100).aspx

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:[email protected], 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 != ‘\n‘)//以换行符作为读取结束标志
    {
      serialString += inChar;
    }
    else
    {
      readCompleted = true;
    }
  }
}

完整代码下载:http://files.cnblogs.com/files/conexpress/Arduino%E5%92%8CCSharp%E9%80%9A%E8%AE%AF.rar

原文地址:https://www.cnblogs.com/endv/p/8644480.html

时间: 2024-10-04 00:55:04

【Arduino】使用C#实现Arduino与电脑进行串行通讯的相关文章

Arduino 串行外设接口(SPI)

时间有限有其他项目工作在忙,感觉作者写的不错,就先记录下来了. 这几天用SPI——Arduino 在供应商的电子原件上游离游走,重要的是可以读写了, 下面是在查资料看到的一篇不错的文章关于用Arduino 自带的SPI方式通信的,(虽然没用这种方法但感觉不错有时间可以学学.... 这几天我都是用什么SPI最底层的编程bit移位,什么汇编语言似的,惨! 所以说在学校的时候一定要好好学啊,别像我现学现用....新项目又来了,继续奋斗....) 参考:https://www.w3cschool.cn/

Arduino 串行外设接口——W3Cschool

来源:https://www.w3cschool.cn/arduino/arduino_serial_peripheral_interface.html Arduino 串行外设接口 由 drbear 创建,youj 最后一次修改 2016-12-26 串行外设接口(SPI)总线是用于串行通信的系统,最多可使用四个导体,通常为三个.一个导体用于数据接收,一个导体用于数据发送,一个导体用于同步,另一个导体用于选择与之通信的设备.它是一个全双工连接,这意味着数据是同时发送和接收的.最大波特率高于I2

11.Arduino基础入门— 8.Arduino通过MQTT客户端推送信息

两个库的引用, 其中,PubSubClient可以在Arduino IDE的库管理器中找到: #include <WiFi.h> 本来是#include <ESP8266WiFi.h> 改成Wifi.h即可. #include <WiFi.h> #include <PubSubClient.h> //设置设备ID const String deviceID = "tempDevice1"; // 设置wifi连接用户密码 const ch

使用python在远程电脑执行多行shell脚本

#!/usr/bin/env python import paramiko hostname='was1' port=22 username='mqm' password='redhat' cmd=''' function printline {                 echo "-------------------------------$1-------------------------------"         }  if [ -d /tmp/test ] th

指示灯组与3个复位按钮的介绍Arduino Yun快速入门教程

指示灯组与3个复位按钮的介绍Arduino Yun快速入门教程 1.4.2  指示灯组 指示灯组的放大图如图1.5所示. 图1.5  指示灯组 各个指示灯对应的功能如下: q  RX:对应于0号端口,串行通讯的接收指示,在接收数据时闪烁: q  TX:对应于1号端口,串行通讯的发送提示,在发送数据时闪烁: q  L13:连接在13号端口,当13号端口为高电平时被点亮: q  WAN:有线网络连接指示,在网线有数据交换的时候点亮: q  ON:电源指示: q  WLAN:WIFI指示,同时也可以用

Arduino Yun的主要部件介绍选自Arduino Yun快速入门教程

Arduino Yun的主要部件介绍 1.4.1  主要部件 Yun的主要部件如图1.4所示. 图1.4  Arduino Yun的主要部件 在Yun小小的板子上集成了两颗处理器.一个是ATmega32u4(标号6),它是Arduino端的控制器,与连接的是MicorUSB(标号8)和两排数据插座以及ICSP头(标号4).另一个处理器在标号3部分,与它相连的是网络接口(标号1).USB host(标号7)以及WIFI(标号2).下面依次介绍各个标号部分的作用:本文选自Arduino Yun快速入

理解电脑上的串口对应的端口号(com口)

每次看到台式电脑上的com1.com2都会迷惑不解,只知道它们是串口的端口号. 其实,串口至少分为RS232串口.RS422串口.RS485串口(还有没有其它我就不知道了), 其中RS232串口即为com口.而COM口( cluster communication port )即串行通讯端口, 也就是我们所说的串口的端口. 那么电脑上的com1.com2有什么区别呢? 1.com1和com2分别对应不同的I/O口,对应电脑上不同的接口(插口) 2.com1和com2的优先级不同,COM2优先级高

单片机(simple chip microcomputer)概论、51单片机、MCS-51单片机、STM32、ARM

catalogue 1. 单片机概论 2. 51单片机 3. MCS-51单片机 4. QX-MINI51开发板(STC89C52芯片) 5. STM32单片机 6. stm32f103zet6开发板实验 1. 单片机概论 0x1: 仿真器 单片机应用系统的软硬件调试需要专门的开发工具,称为"单片机开发系统"或"仿真机".常用的开发方式是把开发系统(例如PC)中的CPU和RAM暂时出借给用户系统,利用开发系统对用户系统的软硬件进行调试(又称仿真),然后将调试好的程序

USB Keyboard Recorder

catalogue 0. 引言 1. Device Class Definition for Human Interface Devices (HID) 2. USB HID Report Descriptors 3. arduino USB Keyboard definition 4. USB Host Shield for Arduino分类 5. USB Host Shield for Arduino datasheet 6. USB Host Library Rev.2.0 7. USB