NMEA協議 上位機 c#


前些時間寫做了兩款用NMEA協議的上位機,在這里做一個總結和記錄。和大家分享,也為了以后不會忘記。

NMEA協議總體來說,相對簡單,是氣象上比較成熟的協議。

主要有以下幾個參數及其格式:

  1. 風速和風向;

  2. 空氣溫度;

  3. 土壤溫度;

  4. 濕度;

  5. 大氣壓;

注:

其中效驗部分主要采用的 異或效驗:即從$后第一個字符到’*’前一個字符進行異或。所得到的數據高4位,低4位的ASCII碼。

<CR>: ‘\r’

<LF>: ‘\n’

波特率:4800

刷新頻率:1Hz

 

在上位機的設計中,所有的接收方式都是被動的。所以處理上非常好做,只需要讀取特定的數據位就可以,將其轉為數據即可。

由於每一段數據都是以’\n’結尾,所以串口中斷serialPortX_DataReceived()中直接采用serialPortX.ReadLine()讀取數據就可以了。讀取后根據協議分析其數據就可以了。以下是我的代碼:

  1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5
6 namespace 氣象監控_NMEA
7 {
8 class NMEA
9 {
10 #region 變量
11 public float speed = 0f;
12 public float direction = 0f;
13 public float airTemp = 0f;
14 public float soilTemp = 0f;
15 public float humidity = 0f;
16 public float barometer = 0f;
17 public bool speedStatus = false;
18
19 private const int MAX_LENGTH = 24;
20 private readonly byte SUM_END = Convert.ToByte('*');
21 private readonly byte SUM_START = Convert.ToByte('$');
22 private readonly byte NUM_0_ASCII = Convert.ToByte('0');
23 private readonly byte NUM_A_ASCII = Convert.ToByte('A' - 10);
24 #endregion
25
26 #region 屬性
27 public float GetSpeed
28 {
29 get
30 {
31 return speed;
32 }
33 set
34 {
35 speed = value;
36 }
37 }
38
39 public float GetDirection
40 {
41 get
42 {
43 return direction;
44 }
45 set
46 {
47 direction = value;
48 }
49 }
50
51 public bool GetStatus
52 {
53 get
54 {
55 return speedStatus;
56 }
57 set
58 {
59 speedStatus = value;
60 }
61 }
62
63 public float GetAirTemp
64 {
65 get
66 {
67 return airTemp;
68 }
69 set
70 {
71 airTemp = value;
72 }
73 }
74
75 public float GetSoilTemp
76 {
77 get
78 {
79 return soilTemp;
80 }
81 set
82 {
83 soilTemp = value;
84 }
85 }
86
87 public float GetHumidity
88 {
89 get
90 {
91 return humidity;
92 }
93 set
94 {
95 humidity = value;
96 }
97 }
98
99 public float GetBarometer
100 {
101 get
102 {
103 return barometer;
104 }
105 set
106 {
107 barometer = value;
108 }
109 }
110 #endregion
111
112 #region 子函數
113 /// <summary>
114 /// 數字轉ASCII
115 /// </summary>
116 /// <param name="Integer">單個位整數</param>
117 /// <returns>ASCII</returns>
118 public byte Integer2Char(int Integer)
119 {
120 byte lcv_ch = 0;
121 if (Integer <= 9)
122 {
123 lcv_ch = Convert.ToByte(Integer + NUM_0_ASCII);
124 }
125 else if ((Integer >= 0x0A) && (Integer <= 0x0F))
126 {
127 lcv_ch = Convert.ToByte(Integer + NUM_A_ASCII);
128 }
129 return lcv_ch;
130 }
131
132 #endregion
133
134 /// <summary>
135 /// sum效驗
136 /// </summary>
137 /// <param name="array">效驗數組</param>
138 /// <returns>效驗值,字符被拆分為兩個ASCII碼整和為一個Int,高位在int高8位,低后</returns>
139 public int CheckSum(byte[] array)
140 {
141 byte sum = 0;
142 int res = 0;
143 int i;
144 for (i = 1; (array[i] != SUM_END) && (i < MAX_LENGTH); i++ )
145 {
146 sum ^= array[i];
147 }
148
149 if (i != MAX_LENGTH)
150 res = (Integer2Char((sum >> 4)) << 8) | Integer2Char(sum & 0xF);
151 return res;
152 }
153
154 /// <summary>
155 /// 從接收到的字符串中,取出有用數據
156 /// </summary>
157 /// <param name="str">接收到的字符串</param>
158 public void DataProcess(string str)
159 {
160 char[] chSplit = {',',};
161 string[] strArray = str.Split(chSplit);
162 switch (strArray[0])
163 {
164 case "$WIMWV" :
165 direction = float.Parse(strArray[1]);
166 speed = float.Parse(strArray[3]);
167 char[] chArray = strArray[5].ToCharArray();
168 speedStatus = (chArray[0] == 'A' ? true : false);
169 break;
170
171 case "$WIMTA" :
172 airTemp = float.Parse(strArray[1]);
173 break;
174
175 case "$WIMTS" :
176 soilTemp = float.Parse(strArray[1]);
177 break;
178
179 case "$WIMHU" :
180 humidity = float.Parse(strArray[1]);
181 break;
182
183 case "$WIMMB" :
184 barometer = float.Parse(strArray[3]);
185 break;
186
187 default: break;
188 }
189 }
190
191 /// <summary>
192 /// 接收到的數據正確性判斷
193 /// </summary>
194 /// <param name="str">接收到的字符串</param>
195 /// <returns>效驗正常返回true</returns>
196 public bool ReceiveCheck(string str)
197 {
198 bool res = false;
199 char[] chSplit = {'*',};
200 string[] strArray = str.Split(chSplit);
201 if (strArray.Length == 2)
202 {
203 if (strArray[1].Length == 3) //長度正常
204 {
205 byte[] array = Encoding.Default.GetBytes(strArray[1]);
206 int check = CheckSum(Encoding.Default.GetBytes(str));
207 if (check != 0)
208 {
209 if (check == ((array[0] << 8) | array[1]))
210 {
211 res = true;
212 }
213 }
214 }
215 }
216 return res;
217 }
218 }
219 }




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM