单片机源程序如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Threading.Tasks;
- using System.IO.Ports;
- using System.Windows;
- using System.Threading;
- namespace FX3GModbusAPI
- {
- public class FX3GModbusAPI
- {
- public struct Type
- {
- //FX3G
- public static string Y = "3300"; //Y元件的定义
- public static string X = "3400"; //X元件的定义
- public static string S = "2000"; //S元件的定义
- public static string M = "0000"; //M元件的定义
- public static string TS = "3000"; //TS位元件的定义
- public static string MR = "1E00"; //M8000~M8511字元件的定义
- public static string CS = "3200"; //CS位元件的定义
- public static string D = "0000"; //D0~D7999
- public static string WD = "1F40"; //D8000~D8511
- }
- public enum SoftElemType
- {
- //FX3G
- Y,
- X,
- S,
- M,
- TS,
- MR,
- CS,
- D,
- WD,
- }
-
- public struct FunctionName
- {
- public static string Read_线圈 = "01";//可多点
- public static string Read_输入 = "02";//可多点
- public static string Read_保持寄存器 = "03";//可多点
- public static string Read_输入寄存器 = "04";//可多点
- public static string Write_线圈写入 = "05";//仅一点
- public static string Write_寄存器写入 = "06";//仅一点
- public static string Write_批量线圈写入 = "0F";//多点线圈写入
- public static string Write_批量寄存器写入 = "10";//多点保持寄存器写入
- }
- public SerialPort port;
- // private StringBuilder myCompleteMessage = new StringBuilder();//避免在事件处理方法中反复的创建,定义到外面。
-
- public string STATE;
- public string myCompleteMessage;
-
- public int FX3G_Write_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
- {
-
- try
- {
- Addr = "";
- senddata = "";
- value = "";
-
- //num = 0;
- switch (eType)
- {
- case (SoftElemType.Y):
- for (int i = 0; i < pValue.Length; i++)
- value += string.Format("{0:x2}", pValue[i]);
- Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.Y.ToString(), 16), 16);
- if (nCount == 1)
- senddata = string.Format("{0:x2}{1}{2}", FunctionName.Write_线圈写入, Addr.PadLeft(4, '0'), value.PadLeft(4, '0'));
- else senddata = string.Format("{0:x2}{1}{2}{3}{4}", FunctionName.Write_批量线圈写入, Addr.PadLeft(4, '0'), Convert.ToString(nCount, 16).PadLeft(4, '0'), Convert.ToString((nCount - 1) / 8 + 1, 16).PadLeft(4, '0'), value);
- Write_port(senddata);
- myCompleteMessage = myCompleteMessage.Replace(" ", "");
- if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x05 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x0F) return -1;
- break;
- case (SoftElemType.M):
- for (int i = 0; i < pValue.Length; i++)
- value += string.Format("{0:x2}", pValue[i]);
- Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16);
- int len = nCount / 8;
- if (nCount % 8 != 0)
- {
- len += 1;
- }
- if (nCount == 1) senddata = string.Format("{0:x2}{1}{2}", FunctionName.Write_线圈写入, Addr.PadLeft(4, '0'), value.PadLeft(4, '0'));
- else senddata = string.Format("{0:x2}{1}{2}{3}{4}", FunctionName.Write_批量线圈写入, Addr.PadLeft(4, '0'), Convert.ToString(nCount, 16).PadLeft(4, '0'), Convert.ToString(len, 16).PadLeft(2, '0'), value);
-
- Write_port(senddata);
-
-
- myCompleteMessage = myCompleteMessage.Replace(" ", "");
- if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x05 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x0F) return -1;
-
- break;
- case (SoftElemType.D):
- for (int i = 0; i < pValue.Length; i++)
- value += string.Format("{0:x2}", pValue[i]);
- Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16);
- if (nCount == 1) senddata = string.Format("{0:x2}{1}{2}", FunctionName.Write_寄存器写入, Addr.PadLeft(4, '0'), value.PadLeft(4, '0'));
- else senddata = string.Format("{0:x2}{1}{2}{3}{4}", FunctionName.Write_批量寄存器写入, Addr.PadLeft(4, '0'), Convert.ToString(nCount, 16).PadLeft(4, '0'), Convert.ToString(2 * nCount, 16).PadLeft(2, '0'), value);
- Write_port(senddata);
- myCompleteMessage = myCompleteMessage.Replace(" ", "");
- if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x06 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x10) return -1;
- break;
- case (SoftElemType.WD):
- for (int i = 0; i < pValue.Length; i++)
- value += string.Format("{0:x2}", pValue[i]);
- Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16);
- senddata = string.Format("{0:x2}{1}{2}{3}{4}", FunctionName.Write_批量寄存器写入, Addr.PadLeft(4, '0'), Convert.ToString(nCount, 16).PadLeft(4, '0'), Convert.ToString(2 * nCount, 16).PadLeft(2, '0'), value);
- Write_port(senddata);
- myCompleteMessage = myCompleteMessage.Replace(" ", "");
- if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x06 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x10) return -1;
- break;
- default:
- return -1;
- }
- }
- catch
- {
- return -1;
- }
- return 1;
-
- }
- string Addr = "";
- string senddata = "";
- string value = "";
- // int num = 0;
- object locker1 = new object();
- public int FX3G_Read_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
- {
- Addr = "";
- senddata = "";
- value = "";
-
-
- // num = 0;
- try
- {
- switch (eType)
- {
- case (SoftElemType.Y):
- Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.Y.ToString(), 16), 16).PadLeft(4, '0');
- senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_线圈, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
- Write_port(senddata);
- myCompleteMessage = myCompleteMessage.Replace(" ", "");
- int leny = nCount / 8;
- if (nCount % 8 != 0)
- {
- leny += 1;
- }
- StringBuilder resulty = new StringBuilder(leny * 8);
- byte[] bvaluey = new byte[leny];
- if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x01) return -1;
- for (int i = 0; i < leny; i++)
- {
- bvaluey[i] = Convert.ToByte((myCompleteMessage.Substring(6 + 2 * i, 2)), 16);
- }
- foreach (byte b in bvaluey)
- {
- resulty.Append(Convert.ToString(b, 2).PadLeft(8, '0'));
- }
- for (int i = 0; i < leny * 8; i++)
- {
- int len1 = (i + 1) / 8;
- if ((i + 1) % 8 != 0)
- {
- len1 += 1;
- }
- pValue[i] = Convert.ToByte(resulty[8 * (2 * len1 - 1) - 1 - i].ToString(), 2);
- }
- break;
- case (SoftElemType.X):
- Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.X.ToString(), 16), 16).PadLeft(4, '0'); ;
- senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_输入, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
- Write_port(senddata);
-
- myCompleteMessage = myCompleteMessage.Replace(" ", "");
- int lenx = nCount / 8;
- if (nCount % 8 != 0)
- {
- lenx += 1;
- }
- StringBuilder resultx = new StringBuilder(lenx * 8);
- byte[] bvaluex = new byte[lenx];
- if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x02) return -1;
- for (int i = 0; i < lenx; i++)
- {
- bvaluex[i] = Convert.ToByte((myCompleteMessage.Substring(6 + 2 * i, 2)), 16);
- }
- foreach (byte b in bvaluex)
- {
- resultx.Append(Convert.ToString(b, 2).PadLeft(8, '0'));
- }
- for (int i = 0; i < lenx * 8; i++)
- {
- int len1 = (i + 1) / 8;
- if ((i + 1) % 8 != 0)
- {
- len1 += 1;
- }
- pValue[i] = Convert.ToByte(resultx[8 * (2 * len1 - 1) - 1 - i].ToString(), 2);
- }
- break;
-
-
- case (SoftElemType.M):
- Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16).PadLeft(4, '0'); ;
- senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_线圈, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
- Write_port(senddata);
- //if (myCompleteMessage.Length < 8) return -1;
- myCompleteMessage = myCompleteMessage.Replace(" ", "");
- int len = nCount / 8;
- if (nCount % 8 != 0)
- {
- len += 1;
- }
- StringBuilder result = new StringBuilder(len * 8);
- byte[] bvalue = new byte[len];
- if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x01) return -1;
- for (int i = 0; i < len; i++)
- {
- bvalue[i] = Convert.ToByte((myCompleteMessage.Substring(6 + 2 * i, 2)), 16);
- }
- foreach (byte b in bvalue)
- {
- result.Append(Convert.ToString(b, 2).PadLeft(8, '0'));
- }
- for (int i = 0; i < len * 8; i++)
- {
- int len1 = (i + 1) / 8;
- if ((i + 1) % 8 != 0)
- {
- len1 += 1;
- }
- pValue[i] = Convert.ToByte(result[8 * (2 * len1 - 1) - 1 - i].ToString(), 2);
- }
- break;
- case (SoftElemType.D):
- Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.D.ToString(), 16), 16).PadLeft(4, '0');
- senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_输入寄存器, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
- Write_port(senddata);
- myCompleteMessage = myCompleteMessage.Replace(" ", "");
- if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x04) return -1;
- for (int i = 0; i < 2 * nCount; i = i + 2)
- {
- pValue[i] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i, 2), 16);//高8位
- pValue[i + 1] = Convert.ToByte(myCompleteMessage.ToString().Substring(8 + 2 * i, 2), 16);//低8位
- }
- break;
- case (SoftElemType.WD):
- Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.D.ToString(), 16), 16).PadLeft(4, '0');
- senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_输入寄存器, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
- Write_port(senddata);
- myCompleteMessage = myCompleteMessage.Replace(" ", "");
- if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x04) return -1;
- for (int i = 0; i < 2 * nCount; i = i + 4)
- {
- pValue[i] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 2, 2), 16);//低8位
- pValue[i + 1] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i, 2), 16);//高8位
- pValue[i + 2] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 6, 2), 16);//低8位
- pValue[i + 3] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 4, 2), 16);//高8位
- }
- break;
- default:
- return -1;
- }
- return 1;
- }
- catch
- {
- return -1;
- }
-
- }
- object locker = new object();
- public void Write_port(string Date)
- {
-
- Date = Date.Insert(0, STATE);
- List<string> sendData16 = new List<string>();
- byte[] sendBuffer = null;
- for (int i = 0; i < Date.Length; i += 2)
- {
- sendData16.Add(Date.Substring(i, 2));
- }
- sendBuffer = new byte[sendData16.Count];
- for (int i = 0; i < sendData16.Count; i++)
- {
- sendBuffer[i] = (byte)(Convert.ToInt32(sendData16[i], 16));
- }
- byte[] star = bcrc16(sendBuffer);
- StringBuilder recBuffer16 = new StringBuilder();
- List<byte> tmp = new List<byte>(sendBuffer.Length + star.Length);
- tmp.AddRange(sendBuffer);
- tmp.AddRange(star);
- byte[] merged = tmp.ToArray();
- port.Write(merged, 0, merged.Length);
- //DateTime TF_timeh, TS_timeh;
- //TF_timeh = DateTime.Now;
- //bool cc = true;
- //while (cc)
- //{
- // TS_timeh = DateTime.Now;
- // double TDelta_t = (TS_timeh - TF_timeh).TotalMilliseconds;
- // if (TDelta_t > 1000) cc = false;
- //}
- System.Threading.Thread.Sleep(200);
-
- }
- public static byte[] bcrc16(byte[] data)
- {
- if (data.Length == 0)
- throw new Exception("调用CRC16校验算法,(低字节在前,高字节在后)时发生异常,异常信息:被校验的数组长度为0。");
- byte[] temdata = new byte[data.Length + 2];
- int xda, xdapoly;
- byte i, j, xdabit;
- xda = 0xFFFF;
- xdapoly = 0xA001;
- for (i = 0; i < data.Length; i++)
- {
- xda ^= data[i];
- for (j = 0; j < 8; j++)
- {
- xdabit = (byte)(xda & 0x01);
- xda >>= 1;
- if (xdabit == 1)
- xda ^= xdapoly;
- }
- }
- temdata = new byte[2] { (byte)(xda & 0xFF), (byte)(xda >> 8) };
- return temdata;
- }//crc校验
- public void serialport_DataReceived(object sender, SerialDataReceivedEventArgs e)
- {
- lock(locker)
- {
- try
- {
- System.Threading.Thread.Sleep(50);
- int n = port.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致
- if (n < 2)
- return;
- // myCompleteMessage = ""; //清除字符串构造器的内容
- ////因为要访问ui资源,所以需要使用invoke方式同步ui。
- byte[] myReadBuffer = new byte[n];
- int numberOfBytesRead = 0;
- // Incoming message may be larger than the buffer size.
- numberOfBytesRead = port.Read(myReadBuffer, 0, myReadBuffer.Length);//读取缓冲数据
- string[] recData = new string[myReadBuffer.Length];
- StringBuilder recBuffer16 = new StringBuilder();
- for (int i = 0; i < myReadBuffer.Length; i++)
- {
- recBuffer16.AppendFormat("{0:X2}" + " ", myReadBuffer[i]);
- recData[i] = myReadBuffer[i].ToString("X2");
- }
- myCompleteMessage = recBuffer16.ToString();
- // myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
-
- }
- catch
- {
- return ;
- }
- }
- }
-
- public int FX3G_Read_Soft_Elem_Float(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
- {
-
- try
- {
- if (eType != SoftElemType.WD)
- return -1;
- Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.D.ToString(), 16), 16).PadLeft(4, '0');
- senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_输入寄存器, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
- Write_port(senddata);
- lock (locker)
- {
- myCompleteMessage = myCompleteMessage.Replace(" ", "");
-
- if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x04)
- return -1;
- for (int i = 0; i < 2 * nCount; i = i + 4)
- {
- pValue[i] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 2, 2), 16);//低8位
- pValue[i + 1] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i, 2), 16);//高8位
- pValue[i + 2] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 6, 2), 16);//低8位
- pValue[i + 3] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 4, 2), 16);//高8位
- }
- return 1;
- }
- }
- catch
- {
- return -1;
- }
-
- }
- public int FX3G_Write_Soft_Elem_Float(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
- {
-
- try
- {
- if (eType != SoftElemType.WD)
- return -1;
- for (int i = 0; i < pValue.Length; i++)
- value += string.Format("{0:x2}", pValue[i]);
- Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16);
- senddata = string.Format("{0:x2}{1}{2}{3}{4}", FunctionName.Write_批量寄存器写入, Addr.PadLeft(4, '0'), Convert.ToString(nCount, 16).PadLeft(4, '0'), Convert.ToString(2 * nCount, 16).PadLeft(2, '0'), value);
- Write_port(senddata);
- myCompleteMessage = myCompleteMessage.Replace(" ", "");
- if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x06 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x10) return -1;
- return 1;
- }
- catch
- {
- return -1;
- }
- }
-
- }
- }
复制代码
所有资料51hei提供下载:
FX3GModbusAPI.rar
(27.5 KB, 下载次数: 237)
|