博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【Arduino】使用C#实现Arduino与电脑进行串行通讯
阅读量:6718 次
发布时间:2019-06-25

本文共 4654 字,大约阅读时间需要 15 分钟。

在给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:
 
2、Arduino串口编程基础
Arduino中的Serial和C#的SerialPort用法类似,有available, begin, read, readBytes, write, print, println,从名称上也很容易理解。具体用法可以参考官方文档:
一般我们会在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;
    }
  }
}
 
 
 完整代码下载:
 

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

你可能感兴趣的文章
如何从Spotify Music中删除DRM?
查看>>
VR开发者为Labo VR辩护 预计这可能是任天堂进军VR的开始
查看>>
全面解析大数据框架Hadoop主要模块
查看>>
手写调用门
查看>>
海恩法则与墨菲定律
查看>>
linux RHEL 解决中文网页乱码和界面英文
查看>>
linux中oracle的日常维护命令
查看>>
Linux 修改IP地址和网关
查看>>
linux查看硬件信息
查看>>
apache http的源码编译
查看>>
find命令的参数
查看>>
H3C交换机配置镜像端口
查看>>
ESXI6.0(6.7)实践——惠普A6 7310主板,APU,Realtek网卡的安装之路
查看>>
我的友情链接
查看>>
26期学员参观森华易腾移动IDC机房有感
查看>>
三、一个简单的BDB JE例子
查看>>
在Windows Server2008R2安装Oracle Database 11g Release 2
查看>>
借助mysql和DNS view实现智能DNS(centos6.3 x64环境)
查看>>
维纳-辛钦 (Wiener–Khinchin) 定理
查看>>
修改mysql的数据库密码
查看>>