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;
        }
    }
}
时间: 2024-08-25 13:42:01

NMEA协议 上位机 C# (转)的相关文章

C# MODBUS协议 上位机(转)

源:C# MODBUS协议 上位机 C#写了一款上位机监控软件,基于MODBUS_RTU协议. 软件的基本结构: 采用定时器(Timer控件)为时间片. 串口采用serialPort1_DataReceived中断接收,并进行MODBUS格式判断. 把正确接收的数据取出,转换为有特定的结构体中. 数据通过时间片实时刷新. MODBUS协议(这里不介绍了,网上有很多的权威资料). 串口接收问题 这里采用的是MODBUS_RTU协议,是没有回车等明显的结束符的哈.所以在C#也不可以用serialPo

c# MODBUS协议 上位机 (转载)

C#写了一款上位机监控软件,基于MODBUS_RTU协议. 软件的基本结构: 1.采用定时器(Timer控件)为时间片. 2.串口采用serialPort1_DataReceived中断接收,并进行MODBUS格式判断. 3.把正确接收的数据取出,转换为有特定的结构体中. 4.数据通过时间片实时刷新. 5.MODBUS协议(这里不介绍了,网上有很多的权威资料). 串口接收问题 这里采用的是MODBUS_RTU协议,是没有回车等明显的结束符的哈.所以在C#也不可以用serialPort1.Read

51采集PCF8591数据通过ESP8266上传C#上位机

效果    如果想用手机做可以参考这篇文章,自己的协议规定在文章中 android 之TCP客户端编程 ---恢复内容开始--- 请问一下博客为什么又不能直接复制粘贴图片了呢............ 先看8266的配置,8266我是用的Lua语言写的,,因为方便快捷....这次写的当然比以前完善...... 关于WIFI模块可以看这几篇 ESP8266使用详解 NodeMCU初探 ESP8266刷AT固件与nodemcu固件 (一)Lua脚本语言入门 (二)Lua脚本语言入门 (三)Lua脚本语

基于CAN总线的汽车诊断协议UDS(上位机开发驱动篇)

本篇作为UDS上位机的驱动开发篇,从市面上多见的CAN分析仪着手介绍UDS上位机驱动开发和移植的一般过程,目的是使UDS上位机软件能适应多家CAN分析仪,降低使用者的硬件成本. 一:广成CAN分析仪的驱动开发 首先创建ECANDLL类,从广成提供的二次开发包中获取ECANVCI.dll文件,将DLL文件放置与生成程序的目录中,如下类中创建了CAN常用的控制函数. public static class ECANDLL { [DllImport("ECANVCI.dll", EntryP

LPC1768IAP(详解,有上位机)

之前说了stm32的iap编程,今天天气真好,顺手就来说说lpc1788的iap编程(没看前面的请查看stm笔记下的内容) 首先是flash的算法,lpc1768并没有寄存器来让我们操作flash,他内置了iap的flash算法,在技术手册的525页有如下说明 其支持的iap命令有这些 这样我们就能够做出相关的flash读写借口呢(具体请查看lpc1768的技术手册) unsigned param_table[5];//传递参数列表 unsigned result_table[5];//返回结果

LabVIEW上位机与串口通信

渊源 大一的时候,学校开了门公共选修课,叫LabVIEW编程,当时的我当然还不知道LabVIEW是啥东东,但还是选了.上课的老师是机械学院的一个副教授,他给我们展示了好几个用LabVIEW做的项目,譬如油箱监控上位机等,已经不太记得了.后来随着学习单片机.ARM等的串口操作,有时候一个漂亮的上位机(尤其是能显示波形的上位机)在项目中给用户展示非常的有用.过了这么多年,虽然曾经也用LabVIEW写过简单的温度监控上位机,但这次再拿起LabVIEW又好像从头开始一样,语法几已忘记殆尽! 定义通信格式

STM32_IAP详解(有代码,有上位机)

Iap,全名为in applacation programming,即在应用编程,与之相对应的叫做isp,in system programming,在系统编程,两者的不同是isp需要依靠烧写器在单片机复位离线的情况下编程,需要人工的干预,而iap则是用户自己的程序在运行过程中对User Flash 的部分区域进行烧写,目的是为了在产品发布后可以方便地通过预留的通信口对产品中的固件程序进行更新升级.在工程应用中经常会出现我们的产品被安装在某个特定的机械结构中,更新程序的时候拆机很不方便,使用ia

C#学习与上位机开发之串口通信模块介绍

串口通信模块(SerialPort) (1)模块简介 使用此模块需要首先包含一些文件IO相关文件 using System.IO;using System.IO.Ports; 图标如下图1所示,将其拖拽到面板.会显示在最下方,其参数有如下: BaudRate 波特率 DataBits 数据位 Parity 奇偶校验位 PortName 端口号 StopBits 停止位 ByteToRead 获取输入缓冲区的 IsOpen 获取是否开启串口         以上是我们做串口通信上位机需要用到的(如

C#上位机串口控制12864显示

实现的效果 上面是用Proteus仿真的,,对了如果自己想用proteus仿真需要安装下面这个软件 再看一下实物显示效果 先做上位机部分........... 为了程序一启动就把电脑上能用的串口号显示在下拉框中 private void Form1_Load(object sender, EventArgs e) { string[] ComName = SerialPort.GetPortNames();//把可用的串口号存入comname comboBoxCom.Items.AddRange