zoukankan      html  css  js  c++  java
  • 智能电表数据读写心得

    1、布线方面

        智能电表采用的是485通讯。如果单位的局域网布置得比较完整的话,建议使用串口转以太网模块,将数据接入以太网。这样做的好处是可以利用现有的网络布线,不用再重复布线。若是使用串口转以太网模块的话,那就需要在上位机上安装一个名为《虚拟VSPM虚拟串口服务器》的软件,它的功能是在将远端的TCP服务器虚拟成一个串口,这样一来,数据的读写跟使用485串口通讯是一样的。

        虚拟VSPM虚拟串口服务器的下载地地址:

         http://www.kinghwawin.com/DownloadShow.asp?ID=40

        串口转以太网络模块的地址:

         http://item.taobao.com/item.htm?spm=a1z09.2.9.66.LxUUjT&id=10248910782&_u=rlmt59h151e

    2、程序方面

        智能电表的数据读写需要遵循相应的通讯协议,这些通讯协议已经被列入了国家标准。目前比较常用的有两个标准:一是2007版本的,全称是《中华人民共和国电力行业标准 DLT645-2007多功能电能表通信协议》,一个是1997版本的。本文使用的是2007版本的通讯协议。   

        下面的代码的GetPowerConsumption()函数演示了如何读取总电量。

    using System;
    using System.Collections.Generic;
    
    using System.Text;
    using System.IO.Ports;
    using System.Windows.Forms;
    using System.Diagnostics;
    
    
    public class ElectricityMeter
    {
    
    
        //****************************************************** 字 段 ************************************************************************** 
        SerialPort _serialPort = new SerialPort();
        Form _frm;
    
        private static readonly ElectricityMeter _instance = new ElectricityMeter();
    
        //*****************************************************  事 件 ***************************************************************************
    
    
        //****************************************************** 属 性 *************************************************************************** 
    
    
        //****************************************************** 构造函数  ******************************************************************* 
    
        /// <summary>
        /// 私有构造函数,防止类被实例化
        /// </summary>
        private ElectricityMeter()
        {
    
        }
    
        //****************************************************** 方 法  ******************************************************************* 
    
    
    
        /// <summary>
        /// 只能通过CreateInstance方法来创建类的实例。单例模式
        /// </summary>
        public static ElectricityMeter CreateInstance()
        {
            return _instance;
        }
    
    
    
    
        /// <summary>
        /// 打开设备
        /// </summary>
        /// <param name="portName">串口号</param>
        /// <param name="frm">调用这个类的窗体。</param>
        public void Open( string portName, Form frm )
        {
            try
            {
                // 初始化窗体对象
                _frm = frm;
                _frm.FormClosing += new FormClosingEventHandler( _frm_FormClosing );
                //初始化SerialPort对象
                _serialPort.PortName = portName;
                _serialPort.BaudRate = 2400; // 请将设备的波特率设置为此。
                _serialPort.DataBits = 8;
                _serialPort.StopBits = StopBits.One;
                _serialPort.Parity = Parity.Even;
                _serialPort.Open();
            }
            catch( Exception e )
            {
                MessageBox.Show( e.Message );
            }
        }
    
    
    
    
    
        /// <summary>
        /// 关闭设备。
        /// </summary>
        public void Close()
        {
            if( _serialPort.IsOpen == true )
            {
                _serialPort.Close();
                _serialPort.Dispose();
            }
        }
    
    
        /// <summary>
        /// 获取耗电量
        /// </summary>
        public Decimal GetPowerConsumption()
        {
            if( _serialPort.IsOpen == true )
            {
                // 十六进制的命令字符串
                string strCmd = "68 AA AA AA AA AA AA 68 11 04 33 33 33 33 AD 16";
                // 转换为十六进制的字节数组
                string[] strs = strCmd.Split( new char[] { ' ' } ); // 空格分组
    
                byte[] cmdBytes = new byte[ strs.Length ];
    
                //  转换为十进制的字节数组
                for( int i = 0; i < cmdBytes.Length; i++ )
                {
                    cmdBytes[ i ] = Convert.ToByte( strs[ i ], 16 ); // 16进制转换为10进制
                }
    
                _serialPort.Write( cmdBytes, 0, cmdBytes.Length );
    
                System.Threading.Thread.Sleep( 500 );  // 500ms内应当有响应
    
                byte[] resultBytes = new byte[ 21 ]; // 容量为21的字节数组
                _serialPort.Read( resultBytes, 0, resultBytes.Length );
    
                string n1 = Convert.ToString( resultBytes[ 18 ] - 51, 16 ); // 将十进制转成16进制的字符串
                string n2 = Convert.ToString( resultBytes[ 17 ] - 51, 16 ); // 将十进制转成16进制的字符串
                string n3 = Convert.ToString( resultBytes[ 16 ] - 51, 16 ); // 将十进制转成16进制的字符串
                string n4 = Convert.ToString( resultBytes[ 15 ] - 51, 16 ); // 将十进制转成16进制的字符串
                string resultString = n1 + n2 + n3 + "." + n4;
    
                return Decimal.Parse( resultString );
            }
            else
            {
                throw new Exception( "串口没有打开" );
            }
        }
    
    
    
        /// <summary>
        /// 在窗体关闭的时候关闭串口连接。
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void _frm_FormClosing( object sender, FormClosingEventArgs e )
        {
            this.Close();
        }
    
    
    
    }
    View Code

        2007版标准的下载地址:

        http://wenku.baidu.com/view/b5e3e9d776a20029bd642d6d.html

  • 相关阅读:
    Redis系列-存储篇sorted set主要操作命令
    Redis系列-存储篇string主要操作命令
    Redis系列-存储篇list主要操作命令
    Redis系列-存储hash主要操作命令
    Jenkins-k8s-helm-eureka-harbor-githab-mysql-nfs微服务发布平台实战
    JAVA线上故障排查手册-(推荐)
    全网最详细的Linux命令系列-sed文本处理命令
    Shell水平测试-想学习Shell的童鞋必选必看文章
    区块链:新经济蓝图及导读
    希望下次 别人问我抽象 ,继承 ,密封 的时候 我不是背书 而是 在讲实实在在的实现
  • 原文地址:https://www.cnblogs.com/dehai/p/4303636.html
Copyright © 2011-2022 走看看