枚舉\位域\結構綜合實驗

1.枚舉項和數值,字符串如何互相轉換?2.結構和byte[]數組間如何互相轉換? 這在通信上廣泛使用!
3.位域在工控上DIO控制廣泛使用,如何借鑑.
OK,上代碼!html

using System;
using System.Runtime.InteropServices;
//http://www.cnblogs.com/pato/archive/2011/08/15/2139705.html
//https://msdn.microsoft.com/zh-cn/library/asx0thw2%28v=vs.110%29.aspx

namespace EnumStructDemo
{
    /// <summary>
    /// 測量類型:儀迪檢測設備測量的類型
    /// </summary>
    public enum MeasureType : byte
    {
        ITEM_NULL = 0,    //
        ITEM_NY = 1,      //耐壓
        ITEM_JD = 2,      //接地
        ITEM_JY = 3,      //絕緣
        ITEM_XL = 4,      //泄漏
        ITEM_GL = 5,      //功率
        ITEM_QD = 6,      //啓動
        ITEM_KD = 7       //開短
    }

    /// <summary>
    /// Binary flag, flag enum. 
    /// 二進制位標誌,一個枚舉實例包含多個枚舉值
    /// 輸入控制信號:到達位置,測量結束
    /// </summary>
    [System.Flags()]
    public enum DigitalIN : byte
    {
        PositionOK = 0x01,
        idiMeasureFinish = 0x02,
    }
    /// <summary>
    /// 輸出控制信號:儀迪設備開始測量,啓動傳動點擊,點亮報警燈
    /// </summary>
    [System.Flags()]
    public enum DigitalOut : byte
    {
        idiStart = 0x01,    //first bit is true, others is false
        chuandong = 0x02,   //second bit is true,...
        light = 0x04,       //third bit is true,....
    }

 
    /// <summary>
    /// 儀迪命令數據幀結構定義
    /// </summary>
    public struct Frame
    {
        public byte Head;       //0.幀頭 'I'
        public byte Protocal;   //1.協議編號 '1'
        public byte AddrHigh;   //2-3.通信地址高位在前,佔用2字節:0~16383
        public byte AddrLow;
        public byte bytCount;   //4.本幀總字節數
        public byte Reserve;    //5.保留,老是0
        public byte Command;    //6.主命令編號**
        public byte frameEnd;   //7.幀尾,老是'D'
        public byte chkSum;     //8.校驗和,全部字節和的低字節
        public void Display() { }
    }

    /// <summary>
    /// struct to byte
    /// </summary>
    /// <param name="obj">truct object</param>
    /// <returns>string array</returns>
    public class StructConvert
    {
        /// <summary>
        /// 根據傳入的結構對象,返回對應的字節數組的引用.
        /// </summary>
        /// <param name="obj">傳入對象</param>
        /// <returns>託管字節數組</returns>
        public static byte[] StructToBytes(object obj)
        {
            int size = Marshal.SizeOf(obj);
            byte[] bytes = new byte[size];//在託管堆上分配字節數組
            //Allocates memory from the unmanaged memory of the process by using the pointer to the specified number of bytes.
            IntPtr structPtr = Marshal.AllocHGlobal(size);
            //Marshals data from a managed object to an unmanaged block of memory.
            //從託管對象obj封裝數據到非託管內存塊
            Marshal.StructureToPtr(obj, structPtr, false);
            //Copies data from an unmanaged memory pointer to a managed 8-bit unsigned integer array.
            Marshal.Copy(structPtr, bytes, 0, size);
            Marshal.FreeHGlobal(structPtr);
            return bytes;
        }

        /// <summary>
        /// (StructName)convert.BytesToStruct(bytes, StructName.GetType());
        /// </summary>
        /// <param name="bytes">byte array</param>
        /// <param name="structType">struct type</param>
        /// <returns>the converted struct </returns>
        public static object BytesToStruct(byte[] bytes, Type structType, int indexFrom = 0)
        {
            //結構的大小老是>=字節數組, 拷貝字節數組到結構,取字節數組大小合適
            int sizeStruct = Marshal.SizeOf(structType);
            int sizeBytes = bytes.Length;

            //經過使用指定的字節數,從進程的非託管內存中分配內存。分配目標對象緩衝區
            IntPtr structPtr = Marshal.AllocHGlobal(sizeStruct);
            //將數據從一維託管 8 位無符號整數數組複製到非託管內存指針。拷貝bytes到緩衝區
            Marshal.Copy(bytes, indexFrom, structPtr, sizeBytes);
            //將數據從非託管內存塊封送到新分配的指定類型的託管對象,傳回託管對象的引用. 非託管內存塊可銷燬!
            //Marshals data from an unmanaged block of memory to a [newly allocated managed object] of the specified type.
            object objStruct = Marshal.PtrToStructure(structPtr, structType);
            //釋放之前從進程的非託管內存中分配的內存。
            //Frees memory previously allocated from the unmanaged memory of the process.
            Marshal.FreeHGlobal(structPtr);
            return objStruct;
        }


    }
    class Program
    {
        static void Main(string[] args)
        {
            //*************枚舉測試***
            foreach (var item in Enum.GetNames(typeof(MeasureType)))
                Console.WriteLine(item);
            //根據數值得到枚舉對象,接收儀器數據後,分析測試數據的類型
            MeasureType meas = (MeasureType)1;//1表明耐壓
            meas = (MeasureType)Enum.Parse(typeof(MeasureType), "ITEM_NY", ignoreCase: true);
            //獲取枚舉對象的[數值],串口發送指令時可用枚舉項表明命令類型
            byte jd = (byte)MeasureType.ITEM_JD;//接地是2
            //測試枚舉項是否爲指定標識,如是否爲耐壓測試
            bool ny = meas.HasFlag(MeasureType.ITEM_NY);
            Console.WriteLine("jd={0},ny={1}", jd, ny);//jd = 2,ny = True

            //*************位域測試***
            DigitalOut DI = DigitalOut.light | DigitalOut.chuandong;
            Console.WriteLine("{0}\tDI={1}", DI, (byte)DI);//chuandong, light DI = 6
            if ((DI & DigitalOut.idiStart) > 0)
                Console.WriteLine("啓動儀迪測試...");

            //*************結構測試***
            Frame frame = new Frame();//結構初始化,值類型爲0,引用類型爲null
            
            UInt16 a = 5;
            byte b = 0xf1;
            int c = 0xf1f2;
            Int64 d = c;
            int size = Marshal.SizeOf(frame);
            size = Marshal.SizeOf(a);//2
            //size = Marshal.SizeOf(DI);//Error!
            size = Marshal.SizeOf(b);//1
            size = Marshal.SizeOf(c);//4
            size = Marshal.SizeOf(d);//8

            byte[] bytMeasStart = { 0x49, 0x31, 0x00, 0x01, 0x08, 0x00, 0x00, 0x44, 0xC7 };
            frame = (Frame)StructConvert.BytesToStruct(bytMeasStart, frame.GetType());
            byte[] bytNew = StructConvert.StructToBytes(frame);
            //frame.chkSum = 199, bytNew[8] = 199
            Console.WriteLine("frame.chkSum={0}, bytNew[8]={1}", frame.chkSum, bytNew[8]);

            Console.ReadKey();
        }
    }
}
相關文章
相關標籤/搜索