標籤:
源:NMEA協議 上位機 c#
前些時間寫做了兩款用NMEA協議的上位機,在這裡做一個總結和記錄。和大家分享,也為了以後不會忘記。
NMEA協議總體來說,相對簡單,是氣象上比較成熟的協議。
主要有以下幾個參數及其格式:
- 風速和風向;
- 空氣溫度;
- 土壤溫度;
- 濕度;
- 大氣壓;
註:
其中效驗部分主要採用的 異或效驗:即從$後第一個字元到’*’前一個字元進行異或。所得到的資料高4位,低4位的ASCII碼。
<CR>: ‘\r’
<LF>: ‘\n’
傳輸速率:4800
重新整理頻率:1Hz
在上位機的設計中,所有的接收方式都是被動的。所以處理上非常好做,只需要讀取特定的資料位元就可以,將其轉為資料即可。
由於每一段資料都是以’\n’結尾,所以串口中斷serialPortX_DataReceived()中直接採用serialPortX.ReadLine()讀取資料就可以了。讀取後根據協議分析其資料就可以了。以下是My Code:
using System;using System.Collections.Generic;using System.Linq;using System.Text;namespace 氣象監控_NMEA{ class NMEA { #region 變數 public float speed = 0f; public float direction = 0f; public float airTemp = 0f; public float soilTemp = 0f; public float humidity = 0f; public float barometer = 0f; public bool speedStatus = false; private const int MAX_LENGTH = 24; private readonly byte SUM_END = Convert.ToByte(‘*‘); private readonly byte SUM_START = Convert.ToByte(‘$‘); private readonly byte NUM_0_ASCII = Convert.ToByte(‘0‘); private readonly byte NUM_A_ASCII = Convert.ToByte(‘A‘ - 10); #endregion #region 屬性 public float GetSpeed { get { return speed; } set { speed = value; } } public float GetDirection { get { return direction; } set { direction = value; } } public bool GetStatus { get { return speedStatus; } set { speedStatus = value; } } public float GetAirTemp { get { return airTemp; } set { airTemp = value; } } public float GetSoilTemp { get { return soilTemp; } set { soilTemp = value; } } public float GetHumidity { get { return humidity; } set { humidity = value; } } public float GetBarometer { get { return barometer; } set { barometer = value; } } #endregion #region 子函數 /// <summary>/// 數字轉ASCII/// </summary>/// <param name="Integer">單個位整數</param>/// <returns>ASCII</returns> public byte Integer2Char(int Integer) { byte lcv_ch = 0; if (Integer <= 9) { lcv_ch = Convert.ToByte(Integer + NUM_0_ASCII); } else if ((Integer >= 0x0A) && (Integer <= 0x0F)) { lcv_ch = Convert.ToByte(Integer + NUM_A_ASCII); } return lcv_ch; } #endregion /// <summary>/// sum效驗/// </summary>/// <param name="array">效驗數組</param>/// <returns>效驗值,字元被拆分為兩個ASCII碼整和為一個Int,高位在int高8位,低後</returns> public int CheckSum(byte[] array) { byte sum = 0; int res = 0; int i; for (i = 1; (array[i] != SUM_END) && (i < MAX_LENGTH); i++ ) { sum ^= array[i]; } if (i != MAX_LENGTH) res = (Integer2Char((sum >> 4)) << 8) | Integer2Char(sum & 0xF); return res; } /// <summary>/// 從接收到的字串中,取出有用資料/// </summary>/// <param name="str">接收到的字串</param> public void DataProcess(string str) { char[] chSplit = {‘,‘,}; string[] strArray = str.Split(chSplit); switch (strArray[0]) { case "$WIMWV" : direction = float.Parse(strArray[1]); speed = float.Parse(strArray[3]); char[] chArray = strArray[5].ToCharArray(); speedStatus = (chArray[0] == ‘A‘ ? true : false); break; case "$WIMTA" : airTemp = float.Parse(strArray[1]); break; case "$WIMTS" : soilTemp = float.Parse(strArray[1]); break; case "$WIMHU" : humidity = float.Parse(strArray[1]); break; case "$WIMMB" : barometer = float.Parse(strArray[3]); break; default: break; } } /// <summary>/// 接收到的資料正確性判斷/// </summary>/// <param name="str">接收到的字串</param>/// <returns>效驗正常返回true</returns> public bool ReceiveCheck(string str) { bool res = false; char[] chSplit = {‘*‘,}; string[] strArray = str.Split(chSplit); if (strArray.Length == 2) { if (strArray[1].Length == 3) //長度正常 { byte[] array = Encoding.Default.GetBytes(strArray[1]); int check = CheckSum(Encoding.Default.GetBytes(str)); if (check != 0) { if (check == ((array[0] << 8) | array[1])) { res = true; } } } } return res; } }}
NMEA協議 上位機 C# (轉)