總網頁瀏覽量

2020年3月18日 星期三

【C# 應用程式】透過WMI API偵測COM Port裝置插拔狀態及取得裝置名稱的重點程式筆記(參考國外網路上網友分享的程式碼)


以下C# WMI範例程式code為參考自下方網路論壇資料並進行相關實作實驗,並加上自己的備忘註解: 
(1) https://hant-kb.kutu66.com/windows/post_650386 
(2) https://stackoverflow.com/questions/17563969/wmi-usb-monitor-multiple-events-fired?rq=1
(3) https://social.msdn.microsoft.com/Forums/zh-TW/c236cac4-a954-4a70-882d-bc20e2cc6e81/getting-more-information-about-a-serial-port-in-c?forum=winformsdesigner
(4) https://stackoverflow.com/questions/2837985/getting-serial-port-information/59508646#59508646
(5) https://cyfangnotepad.blogspot.com/2015/01/cnet-usb.html


個人本身不是什麼純軟體物件導向語言高手,只是過去有一些短暫的相關開發經驗,分享出來讓大家作個參考

程式執行(實驗)環境為Visual Studio IDE, 平台為.NET Framework
.

- 第一部分:主要是記錄如何用C#語言撰寫偵測USB裝置的insert/remove狀態事件

using System.Management;
//...
ManagementEventWatcher watcher = new ManagementEventWatcher();
WqlEventQuery query = new WqlEventQuery("SELECT * FROM Win32_DeviceChangeEvent WHERE EventType = 1");
//EventType = 1是對insert和remove都有反應; 
//EventType = 2是只有對insert有反應; 
//EventType = 3是只有對remove有反應
//以上可以視情況宣告為全域instances 方便一些應用

watcher.EventArrived += new EventArrivedEventHandler(watcher_EventArrived);
watcher.Query = query;
watcher.Start(); 
//如果要停掉watcher就呼叫watcher.Stop(); 不用時可以dispose()掉
//注意上述這些初始動作要在serial port init之前

static void watcher_EventArrived(object sender, EventArrivedEventArgs e)

{ 
  ... //看你想在EventHandler函式裡面做什麼應用
}



------------------------------------


- 第二部分:主要是記錄如何用C#語言撰寫取得裝置管理員內的COM PORT裝置名稱,這邊以Prolific的PL2303 UART轉USB晶片的裝置為例合基本邏輯撰寫(這是許多人玩Raspberry pi或Arduino常會用到的UART/USB轉換的線材內的常見晶片,另外幾款這類用途的常見晶片就是CP210x、CH340、FT232R,不清楚這方面的朋友可參考小弟過去寫的這兩篇文章: USB_to_Serial轉換器或轉換線或轉換板  和  安裝PL2303 USB to Serial轉換線之驅動程式)

using System.Management;

//...

public string GetFullComputerDevices()

  ManagementClass processClass = new ManagementClass("Win32_PnPEntity");
  ManagementObjectCollection Ports = processClass.GetInstances();
  string ComPort_number = "No COM Port device recognized";

  foreach(ManagementObject property in Ports)
  {
       if (property.GetPropertyValue("Name").ToString().Contains("Prolific USB-to-Serial Comm Port");  //以顯示名稱為Prolific USB-to-Serial Comm Port的UART轉USB晶片PL2303為基底的裝置為例
   {
     ComPort_number = property.GetPropertyValue("Name").ToString(); 
     ComPort_number = ComPort_number.Substring(ComPort_number.IndexOf("COM")).TrimEnd(')'); //取得COMx的字串並將其放置到ComPort_number這個string變數
     
//微軟的String.Substring方法教學
//微軟的String.TrimEnd方法教學:
 
   }
  }    
  
  return ComPort_number; //回傳字串,如果都沒有就會回傳預設的"No COM Port device recognized"字串
}
   
注意! 除了在程式裡面using System.Management之外,還有一個步驟要做,否則會有錯誤: 專案 -> 加入參考參考管理員 -> 組件 -> 右上角搜尋: management -> 勾選System.Management -> 按下確定
(如果Visual Studio是英文版: project ->  Add Reference -> Reference Manager -> Assemblies -> search: System.Management -> choose(tick): System.Management -> press Enter)


最後,簡單利用上述重點,並搭配C#的一些基礎

整合實作一個簡單的PL2303的USB轉UART線裝置的插拔偵測與取得裝置名稱的應用程式

Demo影片如下:
(註解: GUI視窗程式下方淺藍色圖案只是一個測試效果)
程式背景圖片就用張西子灣照吧!



【若需要家教模式之技術輔導 可來信洽談合作方式: iws6645@gmail.com】
 

2020年3月11日 星期三

【UART應用】國外STM32臉書facebok社團討論小PO文之記錄整理:用UART傳送浮點數的方式



無意間在臉書上看到外國人的臉書社團STM32 ARM Cortex-M上面的這則老外們在討論的討論PO文(可能要加入該臉書社團才能看到)有點意思,是針對用UART傳送浮點數的方式的這個簡單但實用的議題,幾分鐘就能看完下面的留言討論,但是因為是簡單實用的討論所以就想說在此記錄一下。對於此層面的軟體程式邏輯來說,UART只是以byte為單位(Data framing中主要的資料部分)將資料送出的單元(當然如果要針對UART硬體更精確地來說,其實是將資料一個一個位元的進行串列傳送),所以這裡跟UART的關係並不算很直接,其實這議題算是有點偏向C語言的基礎

如果有嵌入式系統的C語言韌體開發背景的讀者,可以簡單看出該PO文的下面留言者(很多都是外國工程師)提出的留言建議的方式多數屬於下列兩種(也都是很直覺的方式),這邊將其整理並作一些解說:


1. 直接傳送浮點數值:使用union,讓浮點數值與uint8型態的資料作對應(casting/mapping), 然後一個一個byte透過UART送出

/* 將浮點數值與uint8型態的資料透過union在其內宣告,使它們共用一塊記憶體空間 */
typedef union{
float f_val;
uint8_t  uint_val[4];
} float_u; 

float_u value;
value.f_val =6.66; //6.66只是隨便舉個小數值的例子

/* Send Data via UART*/
UART_Transmit(value.uint_val);  /*此處的UART_Transmit函式也是類似pseudo code的簡單示意的範例,實際上就看你的嵌入式系統軟韌體開發環境的UART API函式是怎樣的狀況(實際形式),而此處的目的簡單來說就是用UART將浮點數值一個byte一個byte的方式送出去*/



2. 將浮點數值轉成字串並傳送這個字串:透過sprintf函式將浮點數值轉為字串,例如:
char buffer[4];
sprintf(buffer, "%.2f", 3.14);
然後再透過UART將資料傳送出去。接收端如果需要此值去做後續的運算,當然就需要再把字串轉變回數值之後再作運算
(如果相應的嵌入式系統軟韌體開發環境的printf若已直接串通UART, 就可直接用printf函式就好。這邊的討論應該是針對STM32的HAL_UART_Transmit函式來說,用sprintf將浮點數值轉換為字串並放置到某一段連續的buffer(或陣列),然後再透過此位址搭配HAL_UART_Transmit函式將該字串一個一個byte傳送出去)

【若需要家教模式之嵌入式系統技術輔導 可來信洽談合作方式: iws6645@gmail.com,亦可先點擊參考這篇介紹文章