久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费

 找回密碼
 立即注冊

QQ登錄

只需一步,快速開始

搜索
查看: 7825|回復: 4
打印 上一主題 下一主題
收起左側

燒寫Flash小工具C#上位機源碼

[復制鏈接]
跳轉到指定樓層
樓主
燒寫Flash小工具資料包:


燒寫Flash小工具上位機運行界面:


全部資料51hei下載地址:
燒寫Flash小工具.rar (5.09 MB, 下載次數: 116)


C#源碼:
  1. /*
  2.   * MODBUS協議
  3.   *
  4.   * 介紹:
  5.   * 此modbus上位機 協議類 具有較強的通用性
  6.   * 本協議類最主要的思想是 把所有向下位機發送的指令 先存放在緩沖區中(命名為管道)
  7.   * 再將管道中的指令逐個發送出去。
  8.   * 管道遵守FIFO的模式。管道中所存放指令的個數 在全局變量中定義。
  9.   * 管道內主要分為兩部分:1,定時循環發送指令。2,一次性發送指令。
  10.   * 定時循環發送指令:周期性間隔時間發送指令,一般針對“輸入寄存器”或“輸入線圈”等實時更新的變量。
  11.   * 這兩部分的長度由用戶所添加指令個數決定(所以自由性強)。
  12.   * 指令的最大發送次數,及管道中最大存放指令的個數在常量定義中 可進行設定。
  13.   *
  14.   * 使用說明:
  15.   * 1,首先對所定義的寄存器或線圈進行分組定義,并定義首地址。
  16.   * 2,在MBDataTable數組中添加寄存器或線圈所對應的地址。 注意 寄存器:ob = new UInt16()。線圈:ob = new byte()。
  17.   * 3,對所定義的地址 用屬性進行定義 以方便在類外進行訪問及了解所對應地址的含義。
  18.   * 4,GetAddressValueLength函數中 對使用說明的"第一步"分組 的元素個數進行指定。
  19.   * 5,在主程序中調用MBConfig進行協議初始化(初始化內容參考函數)。
  20.   * 6,在串口中斷函數中調用MBDataReceive()。
  21.   * 7,定時器調用MBRefresh()。(10ms以下)
  22.   *    指令發送間隔時間等于實時器乘以10。 例:定時器5ms調用一次  指令發送間隔為50ms。
  23.   * 8,在主程序初始化中添加固定實時發送的指令操作 用MBAddRepeatCmd函數。
  24.   * 9,在主程序運行過程中 根據需要添加 單個的指令操作(非固定重復發送的指令)用MBAddCmd函數。
  25.   *
  26.   *
  27.   * 作者:王宏強
  28.   * 時間:2012.7.2
  29.   *
  30.   *
  31.   *
  32.   * 修正2012.1.1 修正只有一次性指令,發送最大次數不正常問題
  33.   *
  34.   *
  35. */

  36. using System;
  37. using System.Collections.Generic;
  38. using System.ComponentModel;
  39. using System.Data;
  40. using System.Drawing;
  41. using System.Text;
  42. using System.Windows.Forms;
  43. using System.IO.Ports;

  44. namespace 上位機
  45. {

  46.     public class Modbus : Form
  47.      {
  48.          #region 所用結構體
  49.          /// <summary>
  50.          /// 地址對應表元素單元
  51.          /// </summary>
  52.          public struct OPTable{
  53.              public volatile int addr;
  54.              public volatile byte type;
  55.              public volatile object ob;
  56.          };
  57.          /// <summary>
  58.          /// 當前的指令
  59.          /// </summary>
  60.          public struct MBCmd
  61.          {
  62.              public volatile int addr;           //指令首地址
  63.              public volatile int stat;           //功能碼
  64.              public volatile int len;            //所操作的寄存器或線圈的個數
  65.              public volatile int res;            //返回碼的狀態, 0:無返回,1:正確返回
  66.          };
  67.          /// <summary>
  68.          /// 當前操作的指令管道
  69.          /// </summary>
  70.          public struct MBSci
  71.          {
  72.              public volatile MBCmd[] cmd;             //指令結構體
  73.              public volatile int index;               //當前索引
  74.              public volatile int count;               //當前功能碼執行的次數
  75.              public volatile int maxRepeatCount;      //最大發送次數
  76.              public volatile int rtCount;             //實時讀取的指令各數(無限間隔時間讀取)
  77.          };
  78.          #endregion

  79.          #region 常量定義
  80.          public const byte MB_READ_COILS = 0x01;             //讀線圈寄存器
  81.          public const byte MB_READ_DISCRETE = 0x02;          //讀離散輸入寄存器
  82.          public const byte MB_READ_HOLD_REG = 0x03;          //讀保持寄存器
  83.          public const byte MB_READ_INPUT_REG = 0x04;         //讀輸入寄存器
  84.          public const byte MB_WRITE_SINGLE_COIL = 0x05;      //寫單個線圈
  85.          public const byte MB_WRITE_SINGLE_REG = 0x06;       //寫單寄存器
  86.          public const byte MB_WRITE_MULTIPLE_COILS = 0x0f;   //寫多線圈
  87.          public const byte MB_WRITE_MULTIPLE_REGS = 0x10;    //寫多寄存器

  88.          private const int MB_MAX_LENGTH = 1200;               //最大數據長度
  89.          private const int MB_SCI_MAX_COUNT = 15;             //指令管道最大存放的指令各數
  90.          private const int MB_MAX_REPEAT_COUNT = 3;           //指令最多發送次數
  91.          #endregion

  92.          #region 全局變量
  93.          private static volatile bool sciLock = false;                       //調度器鎖 true:加鎖  false:解鎖
  94.          private static volatile byte[] buff = new byte[MB_MAX_LENGTH];      //接收緩沖器
  95.          private static volatile int buffLen = 0;
  96.          private static volatile byte[] rBuff = null;                  //正確接收緩沖器
  97.          private static volatile byte[] wBuff = null;                     //正確發送緩沖器
  98.          public static MBSci gMBSci = new MBSci() { cmd = new MBCmd[MB_SCI_MAX_COUNT], index = 0, maxRepeatCount = MB_MAX_REPEAT_COUNT, rtCount = 0, count = 0 };
  99.          private static SerialPort comm = null;
  100.          private static int mbRefreshTime = 0;
  101.          #endregion

  102.          #region MODBUS 地址對應表
  103.          //modbus寄存器和線圈分組 首地址定義
  104.          public const int D_DIO = 0x0000;


  105.          /// <summary>
  106.          /// 變量所對應的地址 在此位置
  107.          /// </summary>
  108.          public static volatile OPTable[] MBDataTable = new OPTable[1028];

  109.          public static OPTable[] gDio { get { return MBDataTable; } set { MBDataTable = value; } }

  110.          public static UInt16 gNode = 100;
  111.          public static int gBaud = 38400;
  112.          /// <summary>
  113.          /// 獲取寄存器或線圈 分組后的成員各數
  114.          /// </summary>
  115.          /// <param name="addr">首地址</param>
  116.          /// <returns>成員各數</returns>
  117.          private static int GetAddressValueLength(int addr)
  118.          {
  119.              int res = 0;
  120.              switch (addr)
  121.              {
  122.                  case D_DIO: res = 514; break;
  123.                  default: break;
  124.              }
  125.              return res;
  126.          }
  127.          /// <summary>
  128.          /// 獲取地址所對應的數據
  129.          /// </summary>
  130.          /// <param name="addr">地址</param>
  131.          /// <param name="type">類型</param>
  132.          /// <returns>獲取到的數據</returns>
  133.          private static object GetAddressValue(int addr, byte type)
  134.          {
  135.              switch (type)       //功能碼類型判斷
  136.              {
  137.                  case MB_READ_COILS:
  138.                  case MB_READ_DISCRETE:
  139.                  case MB_READ_HOLD_REG:
  140.                  case MB_READ_INPUT_REG: break;
  141.                  case MB_WRITE_SINGLE_COIL:
  142.                  case MB_WRITE_MULTIPLE_COILS: type = MB_READ_DISCRETE; break;
  143.                  case MB_WRITE_SINGLE_REG:
  144.                  case MB_WRITE_MULTIPLE_REGS: type = MB_READ_HOLD_REG; break;
  145.                  default: return null;
  146.              }

  147.              for (int i = 0; i < MBDataTable.Length; i++)
  148.              {
  149.                  if (MBDataTable[i].addr == addr)
  150.                  {
  151.                      if (MBDataTable[i].type == type)
  152.                      {
  153.                          return MBDataTable[i].ob;
  154.                      }
  155.                  }
  156.              }
  157.              return null;
  158.          }
  159.          /// <summary>
  160.          /// 設置地址所對應的數據
  161.          /// </summary>
  162.          /// <param name="addr">地址</param>
  163.          /// <param name="type">類型</param>
  164.          /// <param name="data">數據</param>
  165.          /// <returns>是否成功</returns>
  166.          private static object SetAddressValue(int addr, byte type, object data)
  167.          {
  168.              for (int i = 0; i < MBDataTable.Length; i++)
  169.              {
  170.                  if (MBDataTable[i].addr == addr)
  171.                  {
  172.                      if (MBDataTable[i].type == type)
  173.                      {
  174.                          MBDataTable[i].ob = data;
  175.                          return true;
  176.                      }
  177.                  }
  178.              }
  179.              return null;
  180.          }
  181.          /// <summary>
  182.          /// 獲取一連串數據
  183.          /// </summary>
  184.          /// <param name="addr">首地址</param>
  185.          /// <param name="type">功能碼</param>
  186.          /// <param name="len">長度</param>
  187.          /// <returns>轉換后的字節數組</returns>
  188.          private static byte[] GetAddressValues(int addr, byte type, int len)
  189.          {
  190.              byte[] arr = null;
  191.              object obj;
  192.              byte temp;
  193.              int temp2;

  194.              switch (type)
  195.              {
  196.                  case MB_WRITE_MULTIPLE_COILS:
  197.                      arr = new byte[(len % 8 == 0) ? (len / 8) : (len / 8 + 1)];
  198.                      for (int i = 0; i < arr.Length; i++)
  199.                      {
  200.                          for (int j = 0; j < 8; j++)
  201.                          {   //獲取地址所對應的數據 并判斷所讀數據 是否被指定,有沒被指定的數據 直接返回null
  202.                              obj = GetAddressValue(addr + i * 8 + j, MB_READ_COILS);
  203.                              if (obj == null)
  204.                                  return null;
  205.                              else
  206.                                  temp = Convert.ToByte(obj);
  207.                              arr[i] |=  (byte)((temp == 0? 0 : 1) << j);
  208.                          }
  209.                      }
  210.                      break;
  211.                  case MB_WRITE_MULTIPLE_REGS:
  212.                      arr = new byte[len * 2];
  213.                      for (int i = 0; i < len; i++)
  214.                      {
  215.                          obj = GetAddressValue(addr + i, MB_READ_HOLD_REG);
  216.                          if (obj == null)
  217.                              return null;
  218.                          else
  219.                              temp2 = Convert.ToInt32(obj);
  220.                          arr[i * 2] = (byte)(temp2 >> 8);
  221.                          arr[i * 2 + 1] = (byte)(temp2 & 0xFF);
  222.                      }
  223.                      break;
  224.                  default: break;
  225.              }
  226.              return arr;
  227.          }
  228.          #endregion

  229.          #region 校驗
  230.          private static readonly byte[] aucCRCHi = {
  231.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  232.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  233.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  234.              0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  235.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  236.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  237.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  238.              0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  239.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  240.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  241.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  242.              0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  243.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  244.              0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  245.              0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  246.              0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  247.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  248.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40,
  249.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  250.              0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41,
  251.              0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41,
  252.              0x00, 0xC1, 0x81, 0x40
  253.          };
  254.          private static readonly byte[] aucCRCLo = {
  255.              0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7,
  256.              0x05, 0xC5, 0xC4, 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E,
  257.              0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9,
  258.              0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, 0x1D, 0x1C, 0xDC,
  259.              0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3,
  260.              0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32,
  261.              0x36, 0xF6, 0xF7, 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D,
  262.              0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38,
  263.              0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, 0x2E, 0x2F, 0xEF,
  264.              0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26,
  265.              0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1,
  266.              0x63, 0xA3, 0xA2, 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4,
  267.              0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB,
  268.              0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, 0x7B, 0x7A, 0xBA,
  269.              0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5,
  270.              0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0,
  271.              0x50, 0x90, 0x91, 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97,
  272.              0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E,
  273.              0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, 0x48, 0x49, 0x89,
  274.              0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C,
  275.              0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83,
  276.              0x41, 0x81, 0x80, 0x40
  277.          };
  278.          /// <summary>
  279.          /// CRC效驗
  280.          /// </summary>
  281.          /// <param name="pucFrame">效驗數據</param>
  282.          /// <param name="usLen">數據長度</param>
  283.          /// <returns>效驗結果</returns>
  284.          public static int Crc16(byte[] pucFrame, int usLen)
  285.          {
  286.              int i = 0;
  287.              byte ucCRCHi = 0xFF;
  288.              byte ucCRCLo = 0xFF;
  289.              UInt16 iIndex = 0x0000;

  290.              while (usLen-- > 0)
  291.              {
  292.                  iIndex = (UInt16)(ucCRCLo ^ pucFrame[i++]);
  293.                  ucCRCLo = (byte)(ucCRCHi ^ aucCRCHi[iIndex]);
  294.                  ucCRCHi = aucCRCLo[iIndex];
  295.              }
  296.              return (ucCRCHi << 8 | ucCRCLo);
  297.          }

  298.          #endregion

  299.          #region 發送指命操作
  300.          /// <summary>
  301.          /// 首部分數據 node:節點
  302.          /// </summary>
  303.          /// <param name="addr">寄存器地址</param>
  304.          /// <param name="len">數據長度,或單個數據</param>
  305.          /// <param name="stat"></param>
  306.          /// <returns></returns>
  307.          private static byte[] SendTrainHead(int node, int addr, int len, byte stat)
  308.          {
  309.              byte[] head = new byte[6];

  310.              head[0] = Convert.ToByte(node);
  311.              head[1] = stat;
  312.              head[2] = (byte)(addr >> 8);
  313.              head[3] = (byte)(addr & 0xFF);
  314.              head[4] = (byte)(len >> 8);
  315.              head[5] = (byte)(len & 0xFF);

  316.              return head;
  317.          }
  318.          /// <summary>
  319.          /// 計算數據長度 并在0x0f,0x10功能下 加載字節數
  320.          /// </summary>
  321.          /// <param name="arr"></param>
  322.          /// <param name="len"></param>
  323.          /// <param name="stat"></param>
  324.          /// <returns></returns>
  325.          private static byte[] SendTrainBytes(byte[] arr, ref int len, byte stat)
  326.          {
  327.              byte[] res;
  328.              switch (stat)
  329.              {
  330.                  default: len = 0; break;

  331.                  case MB_READ_COILS:
  332.                  case MB_READ_DISCRETE:
  333.                  case MB_READ_HOLD_REG:
  334.                  case MB_READ_INPUT_REG:
  335.                  case MB_WRITE_SINGLE_COIL:
  336.                  case MB_WRITE_SINGLE_REG:
  337.                      len = 0;
  338.                      break;

  339.                  case MB_WRITE_MULTIPLE_COILS:
  340.                      len = (len % 8 == 0) ? (len / 8) : (len / 8 + 1);
  341.                      res = new byte[arr.Length + 1];
  342.                      arr.CopyTo(res, 0);
  343.                      res[arr.Length] = (byte)(len);
  344.                      arr = res;
  345.                      break;

  346.                  case MB_WRITE_MULTIPLE_REGS:
  347.                      len *= 2;
  348.                      res = new byte[arr.Length + 1];
  349.                      arr.CopyTo(res, 0);
  350.                      res[arr.Length] = (byte)len;      //把字節寫入數據最后位置
  351.                      arr = res;
  352.                      break;

  353.              }
  354.              return arr;
  355.          }
  356.          /// <summary>
  357.          /// 主控方式  發送指令模板
  358.          /// </summary>
  359.          /// <param name="node">節點</param>
  360.          /// <param name="data">數據</param>
  361.          /// <param name="addr">地址</param>
  362.          /// <param name="con">變量各數</param>
  363.          /// <param name="stat">功能碼</param>
  364.          /// <returns></returns>
  365.          private static byte[] SendTrainCyclostyle(int node, byte[] data, int addr, int con, byte stat)
  366.          {
  367.              int crcVal = 0;
  368.              byte[] headData = SendTrainHead(node, addr, con, stat);                   //寫首部分數據
  369.              byte[] headDataLen = SendTrainBytes(headData, ref con, stat);       //計算數據的長度,有字節則寫入。
  370.              byte[] res = new byte[headDataLen.Length + con + 2];

  371.              headDataLen.CopyTo(res, 0);

  372.              if ((stat == MB_WRITE_MULTIPLE_REGS) || (stat == MB_WRITE_MULTIPLE_COILS))
  373.                  Array.Copy(data, 0, res, headDataLen.Length, con);                   //把數據復制到數據中

  374.              crcVal = Crc16(res, res.Length - 2);
  375.              res[res.Length - 2] = (byte)(crcVal & 0xFF);
  376.              res[res.Length - 1] = (byte)(crcVal >> 8);

  377.              return res;
  378.          }
  379.          /// <summary>
  380.          /// 封裝發送數據幀
  381.          /// </summary>
  382.          /// <param name="node">從機地址</param>
  383.          /// <param name="cmd">指令信息</param>
  384.          /// <returns></returns>
  385.          private static byte[] SendPduPack(int node, MBCmd cmd)
  386.          {
  387.              byte[] res = null;
  388.              switch (cmd.stat)
  389.              {
  390.                  case MB_READ_COILS:
  391.                  case MB_READ_DISCRETE:
  392.                  case MB_READ_HOLD_REG:
  393.                  case MB_READ_INPUT_REG:
  394.                  case MB_WRITE_SINGLE_COIL:
  395.                  case MB_WRITE_SINGLE_REG:
  396.                      res = SendTrainCyclostyle(node, null, cmd.addr, cmd.len, (byte)cmd.stat); break;

  397.                  case MB_WRITE_MULTIPLE_COILS:
  398.                  case MB_WRITE_MULTIPLE_REGS:
  399.                      byte[] data = GetAddressValues(cmd.addr, (byte)cmd.stat, cmd.len);
  400.                      res = SendTrainCyclostyle(node, data, cmd.addr, cmd.len, (byte)cmd.stat); break;
  401.              }
  402.              return res;
  403.          }
  404.          #endregion

  405.          #region 回傳數據操作
  406.          /// <summary>
  407.          /// 存儲回傳的線圈
  408.          /// </summary>
  409.          /// <param name="data">回傳的數組</param>
  410.          /// <param name="addr">首地址</param>
  411.          /// <returns>存儲是否正確</returns>
  412.          private static bool ReadDiscrete(byte[] data, int addr)
  413.          {
  414.              bool res = true;
  415.              int len = data[2];

  416.              if (len != (data.Length - 5))  //數據長度不正確 直接退出
  417.                  return false;

  418.              for (int i = 0; i < len; i++)
  419.              {
  420.                  for (int j = 0; j < 8; j++)
  421.                  {
  422.                      if (SetAddressValue(addr + i * 8 + j, data[1], data[i + 3] & (0x01 << j)) == null)
  423.                      {
  424.                          return false;
  425.                      }
  426.                  }
  427.              }
  428.              return res;
  429.          }
  430.          /// <summary>
  431.          /// 讀回傳的寄存器
  432.          /// </summary>
  433.          /// <param name="data">回傳的數組</param>
  434.          /// <param name="addr">首地址</param>
  435.          /// <returns>存儲是否正確</returns>
  436.          private static bool ReadReg(byte[] data, int addr)
  437.          {
  438.              bool res = true;
  439.              int len = data[2];

  440.              if (len != (data.Length - 5))  //數據長度不正確 直接退出
  441.                  return false;

  442.              for (int i = 0; i < len; i += 2)
  443.              {
  444.                  if (SetAddressValue(addr + i / 2, data[1], (data[i + 3] << 8) | data[i + 4]) == null)
  445.                  {
  446.                      res = false;
  447.                      break;
  448.                  }
  449.              }
  450.              return res;
  451.          }
  452.          /// <summary>
  453.          /// 回傳的數據處理
  454.          /// </summary>
  455.          /// <param name="buff">回傳的整幀數據</param>
  456.          /// <param name="addr">當前所操作的首地址</param>
  457.          /// <returns></returns>
  458.          private static bool ReceiveDataProcess(byte[] buff, int addr)
  459.          {
  460.              if (buff == null)
  461.                  return false;
  462.              if (buff.Length < 5)    //回傳的數據 地址+功能碼+長度+2效驗 = 5字節
  463.                  return false;

  464.              bool res = true;
  465.              switch (buff[1])
  466.              {
  467.                  case MB_READ_COILS: ReadDiscrete(buff, addr); break;
  468.                  case MB_READ_DISCRETE: ReadDiscrete(buff, addr); break;
  469.                  case MB_READ_HOLD_REG: ReadReg(buff, addr); break;
  470.                  case MB_READ_INPUT_REG: ReadReg(buff, addr); break;
  471.                  case MB_WRITE_SINGLE_COIL:
  472.                  case MB_WRITE_SINGLE_REG:
  473.                  case MB_WRITE_MULTIPLE_COILS:
  474.                  case MB_WRITE_MULTIPLE_REGS: break;
  475.                  default: res = false; break;
  476.              }
  477.              return res;
  478.          }
  479.          #endregion

  480.          #region 收發調度
  481.          /// <summary>
  482.          /// 添加重復操作指令
  483.          /// </summary>
  484.          /// <param name="sci">待發送的指命管道</param>
  485.          /// <param name="addr">所添加指令的首地址</param>
  486.          /// <param name="len">所添加指令的寄存器或線圈個數</param>
  487.          /// <param name="stat">所添加指令的功能碼</param>
  488.          private static void SciAddRepeatCmd(ref MBSci sci, int addr, int len, int stat)
  489.          {
  490.              if (sci.rtCount >= MB_SCI_MAX_COUNT - 1)  //超出指令管道最大長度 直接退出
  491.                  return;
  492.              if (len == 0)                               //地址的數據長度為空 直接退出
  493.                  return;

  494.              sci.cmd[sci.rtCount].addr = addr;
  495.              sci.cmd[sci.rtCount].len = len;
  496.              sci.cmd[sci.rtCount].stat = stat;
  497.              sci.cmd[sci.rtCount].res = 0;
  498.              sci.rtCount++;
  499.          }
  500.          /// <summary>
  501.          /// 添加一次性操作指令
  502.          /// </summary>
  503.          /// <param name="sci">待發送的指命管道</param>
  504.          /// <param name="addr">所添加指令的首地址</param>
  505.          /// <param name="len">所添加指令的寄存器或線圈個數</param>
  506.          /// <param name="stat">所添加指令的功能碼</param>
  507.          private static void SciAddCmd(ref MBSci sci, int addr, int len, int stat)
  508.          {
  509.              if (len == 0)                               //地址的數據長度為空 直接退出
  510.                  return;

  511.              for (int i = sci.rtCount; i < MB_SCI_MAX_COUNT; i++)
  512.              {
  513.                  if (sci.cmd[i].addr == -1)      //把指令載入到空的管道指令上
  514.                  {
  515.                      sci.cmd[i].addr = addr;
  516.                      sci.cmd[i].len = len;
  517.                      sci.cmd[i].stat = stat;
  518.                      sci.cmd[i].res = 0;
  519.                      break;
  520.                  }
  521.              }
  522.          }
  523.          /// <summary>
  524.          /// 清空重復讀取指令集
  525.          /// </summary>
  526.          /// <param name="sci">待發送的指命管道</param>
  527.          private static void SciClearRepeatCmd(ref MBSci sci)
  528.          {
  529.              sci.rtCount = 0;
  530.          }
  531.          /// <summary>
  532.          /// 清空一次性讀取指令集
  533.          /// </summary>
  534.          /// <param name="sci">待發送的指命管道</param>
  535.          private static void SciClearCmd(ref MBSci sci)
  536.          {
  537.              for (int i = sci.rtCount; i < MB_SCI_MAX_COUNT; i++)
  538.              {
  539.                  sci.cmd[i].addr = -1;
  540.                  sci.cmd[i].len = 0;
  541.                  sci.cmd[i].res = 0;
  542.              }
  543.          }
  544.          /// <summary>
  545.          /// 跳到下一個操作指令
  546.          /// </summary>
  547.          /// <param name="sci">待發送的指命管道</param>
  548.          private static void SciJumbNext(ref MBSci sci)
  549.          {
  550.              if (sci.index >= sci.rtCount)           //非實時讀取地址會被清除
  551.              {
  552.                  sci.cmd[sci.index].addr = -1;
  553.                  sci.cmd[sci.index].len = 0;
  554.                  sci.cmd[sci.index].stat = 0;
  555.              }

  556.              do{
  557.                  sci.index++;
  558.                  if (sci.index >= MB_SCI_MAX_COUNT)    //超出指令最大范圍
  559.                  {
  560.                      sci.index = 0;
  561.                      if (sci.rtCount == 0)               //如果固定實時讀取 為空 直接跳出
  562.                          break;
  563.                  }

  564.              } while (sci.cmd[sci.index].addr == -1);
  565.              sci.cmd[sci.index].res = 0;             //本次返回狀態清零
  566.          }
  567.          /// <summary>
  568.          /// 發送指令調度鎖定
  569.          /// </summary>
  570.          public static void SciSchedulingLock()
  571.          {
  572.              sciLock = true;
  573.          }
  574.          /// <summary>
  575.          /// 發送指令調度解鎖
  576.          /// </summary>
  577.          public static void SciSchedulingUnlock()
  578.          {
  579.              sciLock = false;
  580.          }
  581.          /// <summary>
  582.          /// 待發送的指令管道調度
  583.          /// </summary>
  584.          /// <param name="sci">待發送的指命管道</param>
  585.          /// <param name="rBuf">收到正確的回傳數據</param>
  586.          /// <param name="wBuf">準備發送的指令數據</param>
  587.          private static void SciScheduling(ref MBSci sci, ref byte[] rBuf, ref byte[] wBuf)
  588.          {
  589.              if (sciLock)   //如果被加鎖 直接退出
  590.                  return;

  591.              if (sci.cmd[0].addr == -1)
  592.                  return;

  593.              if ((sci.cmd[sci.index].res != 0) || (sci.count >= sci.maxRepeatCount))
  594.              {
  595.                  sci.count = 0;       //發送次數清零
  596.                  if (sci.cmd[sci.index].res != 0)    //如果收到了正常返回
  597.                  {
  598.                      ReceiveDataProcess(rBuf, sci.cmd[sci.index].addr);     //保存數據
  599.                      rBuf = null;        //清空當前接收緩沖區的內容, 以防下次重復讀取
  600.                  }
  601.                  else
  602.                  {
  603.                      //參數操作失敗
  604.                  }

  605.                  SciJumbNext(ref sci);
  606.              }
  607.              wBuf = SendPduPack((int)gNode, sci.cmd[sci.index]);     //發送指令操作
  608.              sci.count++;                            //發送次數加1
  609.          }
  610.          /// <summary>
  611.          /// 快速刷新 處理接收到的數據   建議:10ms以下
  612.          /// </summary>
  613.          /// <returns>所正確回傳數據的功能碼, null:回傳不正確</returns>
  614.          private static int MBQuickRefresh()
  615.          {
  616.              int res = -1;
  617.              if (rBuff != null)
  618.              {
  619.                  SciSchedulingLock();
  620.                  if (ReceiveDataProcess(rBuff, gMBSci.cmd[gMBSci.index].addr) == true)
  621.                  {
  622.                      gMBSci.cmd[gMBSci.index].res = 1;   //標記 所接收到的數據正確
  623.                      res = gMBSci.cmd[gMBSci.index].stat;
  624.                  }
  625.                  rBuff = null;
  626.                  SciSchedulingUnlock();
  627.              }
  628.              return res;
  629.          }
  630.          /// <summary>
  631.          /// 調度間隔時間刷新        建議:50ms以上
  632.          /// </summary>
  633.          /// <returns>封裝好的協議幀</returns>
  634.          private static void MBSchedRefresh()
  635.          {
  636.              SciScheduling(ref gMBSci, ref rBuff, ref wBuff);
  637.              if (wBuff != null)
  638.                  comm.Write(wBuff, 0, wBuff.Length);
  639.          }

  640.          #endregion

  641.          #region 接口函數
  642.          /// <summary>
  643.          /// 清空存放一次性的指令空間
  644.          /// </summary>
  645.          public static void MBClearCmd()
  646.          {
  647.              SciClearCmd(ref gMBSci);
  648.          }
  649.          /// <summary>
  650.          /// 添加固定刷新(重復) 操作指令
  651.          /// </summary>
  652.          /// <param name="addr">地址</param>
  653.          /// <param name="stat">功能碼</param>
  654.          public static void MBAddRepeatCmd(int addr, byte stat)
  655.          {
  656.              for (int i = 0; i < GetAddressValueLength(addr); i++ )
  657.                  if (GetAddressValue(addr, stat) == null)        //如果所添加的指令沒有在MODBUS對應表中定義 直接退出
  658.                      return;
  659.              SciAddRepeatCmd(ref gMBSci, addr, GetAddressValueLength(addr), stat);
  660.          }
  661.          /// <summary>
  662.          /// 添加一次性 操作指令
  663.          /// </summary>
  664.          /// <param name="addr"></param>
  665.          /// <param name="stat"></param>
  666.          public static void MBAddCmd(int addr, byte stat)
  667.          {
  668.              for (int i = 0; i < GetAddressValueLength(addr); i++)
  669.                  if (GetAddressValue(addr, stat) == null)        //如果所添加的指令沒有在MODBUS對應表中定義 直接退出
  670.                      return;
  671.              SciAddCmd(ref gMBSci, addr, GetAddressValueLength(addr), stat);
  672.          }
  673.          /// <summary>
  674.          /// 串口參數配置
  675.          /// </summary>
  676.          /// <param name="commx">所用到的串口</param>
  677.          /// <param name="node"></param>
  678.          /// <param name="baud"></param>
  679.          public static void MBConfig(SerialPort commx, UInt16 node, int baud)
  680.          {
  681.              gBaud = baud;
  682.              gNode = node;
  683.              comm = commx;
  684.              SciClearRepeatCmd(ref gMBSci);
  685.              SciClearCmd(ref gMBSci);
  686.          }
  687.          /// <summary>
  688.          /// 讀取串口中接收到的數據
  689.          /// </summary>
  690.          /// <param name="comm">所用到的串口</param>
  691.          public static void MBDataReceive()
  692.          {
  693.              if (comm == null)                       //如果串口沒有被初始化直接退出
  694.                  return;
  695.              SciSchedulingLock();
  696.              System.Threading.Thread.Sleep(10);      //等待緩沖器滿
  697.              if (!comm.IsOpen)
  698.                  return;

  699.              buffLen = comm.BytesToRead;          //獲取緩沖區字節長度
  700.              if (buffLen > MB_MAX_LENGTH)            //如果長度超出范圍 直接退出
  701.              {
  702.                  SciSchedulingUnlock();
  703.                  return;
  704.              }
  705.              comm.Read(buff, 0, buffLen);            //讀取數據
  706.              if (gMBSci.cmd[gMBSci.index].stat == buff[1])
  707.              {
  708.                  if (Crc16(buff, buffLen) == 0)
  709.                  {
  710.                      rBuff = new byte[buffLen];
  711.                      Array.Copy(buff, rBuff, buffLen);
  712.                  }
  713.              }
  714.              SciSchedulingUnlock();
  715.          }
  716.          /// <summary>
  717.          /// MODBUS的實時刷新任務,在定時器在實時調用此函數
  718.          /// 指令發送間隔時間等于實時器乘以10。 例:定時器5ms調用一次  指令發送間隔為50ms。
  719.          /// </summary>
  720.          /// <returns>返回當前功能讀取指令回傳 的功能碼</returns>
  721.          public static int MBRefresh()
  722.          {
  723.              if (sciLock)   //如果被加鎖 直接退出
  724.                  return 0;

  725.              mbRefreshTime++;
  726.              if (mbRefreshTime > 10)
  727.              {
  728.                  mbRefreshTime = 0;
  729.                  MBSchedRefresh();
  730.              }
  731.              return MBQuickRefresh();
  732.          }
  733.          #endregion


  734.      }

  735. }
復制代碼


分享到:  QQ好友和群QQ好友和群 QQ空間QQ空間 騰訊微博騰訊微博 騰訊朋友騰訊朋友
收藏收藏4 分享淘帖 頂 踩
回復

使用道具 舉報

沙發
ID:625650 發表于 2019-10-17 15:19 | 只看該作者
學習學習哈,這個什么燒寫器都適用嗎
回復

使用道具 舉報

板凳
ID:779899 發表于 2020-10-21 18:10 | 只看該作者

學習學習哈,這個什么燒寫器都適用嗎
回復

使用道具 舉報

地板
ID:654797 發表于 2022-3-1 22:04 | 只看該作者
這是燒寫什么芯片的呀
回復

使用道具 舉報

5#
ID:87000 發表于 2022-7-28 09:20 | 只看該作者
vscos 發表于 2022-3-1 22:04
這是燒寫什么芯片的呀

這只是上位機串口工具,還需你自己去實現下位機來執行燒寫過程
回復

使用道具 舉報

您需要登錄后才可以回帖 登錄 | 立即注冊

本版積分規則

手機版|小黑屋|51黑電子論壇 |51黑電子論壇6群 QQ 管理員QQ:125739409;技術交流QQ群281945664

Powered by 單片機教程網

快速回復 返回頂部 返回列表
主站蜘蛛池模板: 国产精品视频一二三区 | 黑人巨大精品欧美黑白配亚洲 | 国产一区二区在线观看视频 | 黄色a视频 | 亚洲综合精品 | 毛片免费看的 | 一区二区三区在线观看免费视频 | 欧美黄色小视频 | 中文字幕精品一区二区三区精品 | 一区二区三区四区免费在线观看 | 国产大片一区 | 爱爱小视频 | 成人免费视频播放 | 欧美日韩综合精品 | 欧美日韩一区在线 | 国产在线精品一区二区 | 在线观看第一区 | av中文字幕在线播放 | 操久久| 日本不卡视频在线播放 | 日本福利视频免费观看 | 成人黄色在线视频 | 日韩另类| 久久亚洲天堂 | 国产精品免费观看 | 自拍偷拍视频网 | 中文字幕 国产 | 精品国产乱码久久久 | av中文字幕在线播放 | 久久久久国产一区二区三区 | 国产激情精品视频 | 中文字幕黄色大片 | 欧美中文视频 | 天堂亚洲 | 亚洲a视频| 日韩在线精品视频 | 精品亚洲一区二区三区 | 久色视频在线观看 | 国产精品久久久久久久免费大片 | 日韩在线精品视频 | 在线观看免费av网站 |