• NMEA协议 上位机 C# (转)


    源:NMEA协议 上位机 c#

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

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

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

    1. 风速和风向;

    2. 空气温度;

    3. 土壤温度;

    4. 湿度;

    5. 大气压;

    注:

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

    <CR>: ‘ ’

    <LF>: ‘ ’

    波特率:4800

    刷新频率:1Hz

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

    由于每一段数据都是以’ ’结尾,所以串口中断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;
            }
        }
    }
  • 相关阅读:
    springboot入门系列(一):简单搭建springboot项目
    springboot入门系列(二):SpringBoot整合Swagger
    springboot入门系列(三):SpringBoot教程之RabbitMQ示例
    springboot入门系列(四):SpringBoot和Mybatis配置多数据源连接多个数据库
    Linux下安装RabbitMQ
    Mybatis原理之数据源和连接池
    springboot入门系列(五):SpringBoot连接多RabbitMQ源
    jsp中<c:foreach>分页标签的序号问题
    Java中删除一个文件夹下的所有文件(包括子目录内的文件)
    接口的幂等性
  • 原文地址:https://www.cnblogs.com/LittleTiger/p/4429679.html
Copyright © 2020-2023  润新知