NMEA协议 上位机 C# (转)

源:NMEA协议 上位机 c#

前些时间写做了两款用NMEA协议的上位机,在这里做一个总结和记录。和大家分享,也为了以后不会忘记。

NMEA协议总体来说,相对简单,是气象上比较成熟的协议。

主要有以下几个参数及其格式:

  1. 风速和风向;

  2. 空气温度;

  3. 土壤温度;

  4. 湿度;

  5. 大气压;

注:

其中效验部分主要采用的 异或效验:即从$后第一个字符到’*’前一个字符进行异或。所得到的数据高4位,低4位的ASCII码。

<CR>: ‘\r’

<LF>: ‘\n’

波特率:4800

刷新频率:1Hz

 

在上位机的设计中,所有的接收方式都是被动的。所以处理上非常好做,只需要读取特定的数据位就可以,将其转为数据即可。

由于每一段数据都是以’\n’结尾,所以串口中断serialPortX_DataReceived()中直接采用serialPortX.ReadLine()读取数据就可以了。读取后根据协议分析其数据就可以了。以下是我的代码:

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;
        }
    }
}

 

posted @ 2015-04-15 18:57  酒醉的Tiger  阅读(470)  评论(0编辑  收藏  举报