【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: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 != '\n')//以换行符作为读取结束标志
    {
      serialString += inChar;
    }
    else
    {
      readCompleted = true;
    }
  }
}
完整代码下载:http://files.cnblogs.com/files/conexpress/Arduino%E5%92%8CCSharp%E9%80%9A%E8%AE%AF.rar



来自为知笔记(Wiz)



转载于:https://www.cnblogs.com/conexpress/p/Arduino_Connecte_Compute_With_SerialPort.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/448512.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

虚拟机NAT模式联网

阿里开源镜像软件&#xff1a;https://opsx.alibaba.com/mirror 如何使VMware ip与本机ip处于同一网段 https://blog.csdn.net/kakuma_chen/article/details/71425620 转载于:https://www.cnblogs.com/cdy0626/p/11131440.html

VS2008下最新X264(svn 2009.9)编译不过的解决办法

总有人说最新的版本 编译不过&#xff0c;搞的群、 论坛里到处都是这种求助贴。建议斑竹把这个解决办法放到醒目的位置&#xff0c;以减少噪音。科普开始1、编译问题由于MS的VS编译器对C99标准支持不好&#xff0c;不支持函数当中混合定义、声明变量。解决办法&#xff1a;在函…

node、npm、vue安装 -- VUE 项目 demo 实例

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1. 安装node&#xff1a; sudo yum install epel-release sudo yum install nodejs node --version // 安装好后查看版本2. 安装 npm …

用C语言实现简单的停车场管理

这个程序是利用栈和循环队列实现的&#xff0c;自己得先处理好逻辑关系就好了。由于题目没有要求&#xff0c;这个程序就没加重复判断&#xff0c;比如一辆车已经停在车位上或者便道上&#xff0c;再来一辆就判断不了了。关于栈&#xff0c;就是先进后出的思想&#xff0c;队列…

推荐一个配置linux服务的网站

该网站的各种linux服务的配置都是基于CentOS系统的 基本上各种linux服务都有了 http://www.server-world.info/en/转载于:https://www.cnblogs.com/Skyar/p/3582389.html

mariadb数据库增删改查

1.常用数据类型 1&#xff09;整数:int, bit 2&#xff09;小数:decimal    #decimal(5,2)表示共有五位数&#xff0c;保留两位小数 3&#xff09;字符串:varchar, char   4&#xff09;日期时间:date, time, datetime 5&#xff09;枚举类型(enu…

为什么你工作努力却没有起色?

成为职场达人&#xff0c;未必要经常挑灯夜战。相反&#xff0c;注意到下面几条&#xff0c;会让你少走弯路。 1&#xff09;成长的机会永远比眼前的待遇重要——做重要的事比多拿钱重要。 我知道在水木bbs上的worklife版本&#xff0c;每天都在上演的就是比较自己的第一个o…

《 Spring 实战 》(第4版) 读书笔记 (未完结,更新中...)

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 Pxx 表示在书的第 xx 页。 Spring 框架的核心是 Spring 容器。 1. (P7.) 构造器注入是依赖注入的方式之一。 紧耦合&#xff1a;在 …

数据结构排序法之希尔排序法(Shell Sort)

希尔排序&#xff0c;也叫递减增量排序&#xff0c;是插入排序的一种更高效的改进版本。希尔排序是不稳定的排序算法。 希尔排序是基于插入排序的以下两点性质而提出改进方法的&#xff1a; 1、插入排序在对几乎已经排好序的数据操作时&#xff0c;效率高&#xff0c;即可以达…

Windows To Ghost系统封装之必备软件集 - 好压

好压压缩软件&#xff08;HaoZip&#xff09;是强大的压缩文件管理器&#xff0c;是完全免费的新一代压缩软件&#xff0c;相比其它压缩软件系统资源占用更少&#xff0c;有更好的兼容性&#xff0c;压缩率比较高。 它提供了对ZIP、7Z和TAR文件的完整支持&#xff0c;能解压RAR…

js 弹窗并定时关闭

1. $(input).click(function() {prompt(点击成功, 2000) })function prompt(newName, time, fn) {var $div $(<div></div>);$div.css({position: fixed,top: 0,left: 0,width: 100%,height: 100%,z-index: 200,background-color: rgba(0,0,0,0.4),// background-c…

数据结构排序法之插入法

插入排序是一种简单直观的排序算法。它的工作原理非常类似于我们抓扑克牌。 对于未排序数据(右手抓到的牌)&#xff0c;在已排序序列(左手已经排好序的手牌)中从后向前扫描&#xff0c;找到相应位置并插入。 插入排序在实现上&#xff0c;通常采用in-place排序&#xff08;即…

XSLT学习笔记

1. 样式声明&#xff1a;<xsl:stylesheet>或<xsl:transform> 2. XSLT常用元素&#xff1a; 2.1 <xsl:template>&#xff1a;创建模板 Match属性的作用是使模板和XML元素相关联 e.g.:<xsl:template match"\">......</xsl:template&g…

职场:人生从没有最佳时机!一个离职客服人员的领悟

每个人都有感到失落迷惘的时候。 人生用专制又霸道的方式运行着&#xff0c;每当我们心想一切尘埃落定、生活稳固的时候&#xff0c;生活总爱给我们惊喜&#xff0c;粉碎我们短暂的安逸&#xff0c;让我们不得不重新思考。 「我走对路了吗?」 「我能够赚更多钱、爬到更高的地位…

VS Code 的常用快捷键

VS Code 的常用快捷键和插件 一、vs code 的常用快捷键 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1、注释&#xff1a; a) 单行注释&#xff1a;[ctrlk,ctrlc] 或 ctrl/ b) 取消…

vue-axios interceptors

import axios from axios import cookie from js-cookie const options {baseURL: window.location.protocol process.env.BASE_API,headers: {},timeout: 20000 } const fetch axios.create(options)// request拦截器 fetch.interceptors.request.use(config > {if (coo…

数据结构排序法之鸡尾酒排序法he快速排序法

鸡尾酒排序&#xff0c;也叫定向冒泡排序&#xff0c;是冒泡排序的一种改进。此算法与冒泡排序的不同处在于从低到高然后从高到低&#xff0c;而冒泡排序则仅从低到高去比较序列里的每个元素。他可以得到比冒泡排序稍微好一点的效能。 // 两两互换 void swap (int* a, int i, …

VSCode 多开、环境对比

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 多开&#xff1a; 第一种&#xff1a;win10的开始菜单&#xff0c;在vscode图标右键选择“新开窗口”&#xff0c;这样就多了一个vscode…

前言_工作两年自我感触

17年大学毕业&#xff0c;到今天整整工作两年&#xff0c;从前端到数据分析&#xff0c;从上家公司&#xff08;简称A&#xff09;到现公司&#xff0c;想趁着今天是参加工作两年的纪念日&#xff0c;回忆过往&#xff0c;结合现状有感而发。 刚毕业的时候&#xff0c;啥都学&a…

数据结构排序法之堆排序he归并排序

堆排序&#xff08;Heapsort&#xff09;是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构&#xff0c;并同时满足堆性质&#xff1a;即子结点的键值或索引总是小于&#xff08;或者大于&#xff09;它的父节点。 堆排序的时间&#xff0c;主要由建…