【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.pswp.cn/news/448512.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/448512.shtml
英文地址,請注明出處:http://en.pswp.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;主要由建…