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

摘要:
SerialMonitor不仅可以接受Arduino发送给计算机的数据,还可以将数据发送给Arduino进行双向通信。如果您需要通过计算机上的可视界面与Arduino交互,或处理Arduino发送到计算机的数据,则需要在计算机上编程。本文介绍了如何使用C#实现Arduino与计算机的串行通信。然后调用ChangeArduinoSendStatus方法向Arduino发送“serialstart”命令。
在给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)
【Arduino】使用C#实现Arduino与电脑进行串行通讯第1张
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,界面如下:

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

“串口列表”中自动加载电脑上的可用串口名称。
点击“开始读取”按钮,根据选择的串口名称实例化一个串口对象,指定串口的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>
privatevoid 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>
privatevoid 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>
privatevoid ChangeArduinoSendStatus(bool allowSend)
{
    if (port !=null&& port.IsOpen)
    {
        if (allowSend)
        {
            port.WriteLine("serial start");
        }
        else
        {
            port.WriteLine("serial stop");
        }
    }
}
 
/// <summary>
/// 从串口读取数据并转换为字符串形式
/// </summary>
/// <returns></returns>
privatestring 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>
privatevoid 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;
    }
    elseif(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;
    }
  }
}
 
 
 完整代码下载:http://files.cnblogs.com/files/conexpress/Arduino%E5%92%8CCSharp%E9%80%9A%E8%AE%AF.rar
 



来自为知笔记(Wiz)



免责声明:文章转载自《【Arduino】使用C#实现Arduino与电脑进行串行通讯》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇前端脚手架BigFishwinform DataGridView控件的打印下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

米家 + arduino + 自定义服务器

无聊突然想把米家的一些功能链接到我自己的服务器上,查了一下资料发现,木有开放的api。然后,我想到一个黑操作。 整体思路 通过米家app中的“智能”功能,可以触发开关米家台灯(这里我只有米家台灯感觉合适),然后通过硬件(光敏电阻),获取灯光是否打开,就可以通过自己的硬件,把指定的内容发送到服务器咯。我真棒! 购买硬件 最早想买一个树莓派来玩,不过价格让我...

macbookpro触摸板突然失灵按压无震动反馈和回弹感

小背景 今天下早班回来,打算看看视频放松一下,打开电脑后发现我的电脑触摸板按不动了,之前单击或点击触摸板的时候明显有一个一上一下的回弹感觉,现在却'按不下去了',其他的功能如滑动、缩放等操作都是正常的。 有问题先问一波百度,但是没有办法点击所以拿出了我压箱底用的鼠标,散发着红黄蓝绿光的鼠标将我指引到了apple的讨论区,发现有很多人遇到了和我一样的问题,这...

android 电容屏(一):电容屏基本原理篇

关键词:android 电容屏 tp ITO平台信息:内核:linux2.6/linux3.0系统:android/android4.0平台:S5PV310(samsung exynos 4210) 作者:xubin341719(欢迎转载,请注明作者) android 电容屏(一):电容屏基本原理篇 android 电容屏(二):驱动调试之基本概念篇 and...

出现 "System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本" 错误的解决办法

出现 "System.Data.OracleClient 需要 Oracle 客户端软件 8.1.7 或更高版本" 错误的解决办法 1.问题: 在Windows SP2 + VS2005 + Oracle 9i +IIS5.1环境中运行ASP.NET网页的时候出现如下错误: System.Data.OracleClient 需要 Oracle 客户端软...

C# 串口 已关闭 Safe handle

今天在使用我的通信框架,创建基于串口通信的客户端时,出现这样一个BUG: [csharp]view plaincopy 未处理System.ObjectDisposedException Message=已关闭Safehandle Source=mscorlib ObjectName="" StackTrace: 在System.Runtime....

Windows7里面怎么实现FTP服务功能

1.安装FTP服务 点击:计算机 ——>属性 ——> 控制面板主页 ——> 程序 ——> 打开或关闭Windows功能 2. 调出管理工具 操作: 鼠标点击工具栏,选择属性,选择【开始】菜单,选择自定义,选择系统管理工具里面的显示,操作如下。 3. 选择电脑左下角的Windows图标,选择管理工具,选择Internet信息服务(...