找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 9506|回复: 11
收起左侧

三菱PLC与上位机的Modbus通讯 附C#源代码

  [复制链接]
ID:590315 发表于 2019-7-25 15:31 | 显示全部楼层 |阅读模式
0.png

单片机源程序如下:
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using System.IO.Ports;
  7. using System.Windows;
  8. using System.Threading;
  9. namespace FX3GModbusAPI
  10. {
  11.     public class FX3GModbusAPI
  12.     {
  13.         public struct Type
  14.         {
  15.             //FX3G
  16.             public static string Y = "3300";      //Y元件的定义        
  17.             public static string X = "3400";                //X元件的定义                                                        
  18.             public static string S = "2000";        //S元件的定义                                
  19.             public static string M = "0000";                //M元件的定义                                                        
  20.             public static string TS = "3000";                //TS位元件的定义                                
  21.             public static string MR = "1E00";        //M8000~M8511字元件的定义                                
  22.             public static string CS = "3200";                //CS位元件的定义                                
  23.             public static string D = "0000";          //D0~D7999
  24.             public static string WD = "1F40";     //D8000~D8511
  25.         }
  26.         public enum SoftElemType
  27.         {
  28.             //FX3G   

  29.             Y,
  30.             X,
  31.             S,
  32.             M,
  33.             TS,
  34.             MR,
  35.             CS,
  36.             D,
  37.             WD,

  38.         }
  39.    
  40.         public struct FunctionName
  41.         {
  42.            public static string   Read_线圈 = "01";//可多点
  43.            public static string Read_输入 = "02";//可多点
  44.            public static string Read_保持寄存器 = "03";//可多点
  45.            public static string Read_输入寄存器 = "04";//可多点
  46.            public static string Write_线圈写入 = "05";//仅一点
  47.            public static string Write_寄存器写入 = "06";//仅一点
  48.            public static string Write_批量线圈写入 = "0F";//多点线圈写入
  49.            public static string Write_批量寄存器写入 = "10";//多点保持寄存器写入
  50.         }
  51.         public  SerialPort port;
  52.      //   private StringBuilder myCompleteMessage = new StringBuilder();//避免在事件处理方法中反复的创建,定义到外面。  
  53.    
  54.         public string STATE;

  55.         public string myCompleteMessage;
  56.    
  57.         public int FX3G_Write_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
  58.         {
  59.             
  60.             try
  61.             {
  62.                 Addr = "";
  63.                 senddata = "";
  64.                 value = "";
  65.          
  66.                 //num = 0;
  67.                 switch (eType)
  68.                 {
  69.                     case (SoftElemType.Y):
  70.                         for (int i = 0; i < pValue.Length; i++)
  71.                             value += string.Format("{0:x2}", pValue[i]);

  72.                         Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.Y.ToString(), 16), 16);

  73.                         if (nCount == 1)
  74.                             senddata = string.Format("{0:x2}{1}{2}", FunctionName.Write_线圈写入, Addr.PadLeft(4, '0'), value.PadLeft(4, '0'));

  75.                         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);


  76.                         Write_port(senddata);
  77.                         myCompleteMessage = myCompleteMessage.Replace(" ", "");
  78.                         if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x05 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x0F) return -1;

  79.                         break;
  80.                     case (SoftElemType.M):
  81.                         for (int i = 0; i < pValue.Length; i++)

  82.                             value += string.Format("{0:x2}", pValue[i]);

  83.                         Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16);
  84.                         int len = nCount / 8;
  85.                         if (nCount % 8 != 0)
  86.                         {
  87.                             len += 1;
  88.                         }

  89.                         if (nCount == 1) senddata = string.Format("{0:x2}{1}{2}", FunctionName.Write_线圈写入, Addr.PadLeft(4, '0'), value.PadLeft(4, '0'));

  90.                         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);
  91.                                                                      
  92.                            Write_port(senddata);
  93.                     
  94.                         
  95.                                 myCompleteMessage = myCompleteMessage.Replace(" ", "");
  96.                                 if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x05 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x0F) return -1;
  97.                                 
  98.                         break;
  99.                     case (SoftElemType.D):
  100.                         for (int i = 0; i < pValue.Length; i++)

  101.                             value += string.Format("{0:x2}", pValue[i]);

  102.                         Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16);

  103.                         if (nCount == 1) senddata = string.Format("{0:x2}{1}{2}", FunctionName.Write_寄存器写入, Addr.PadLeft(4, '0'), value.PadLeft(4, '0'));

  104.                         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);


  105.                         Write_port(senddata);
  106.                         myCompleteMessage = myCompleteMessage.Replace(" ", "");
  107.                         if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x06 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x10) return -1;

  108.                         break;
  109.                     case (SoftElemType.WD):
  110.                         for (int i = 0; i < pValue.Length; i++)

  111.                             value += string.Format("{0:x2}", pValue[i]);

  112.                         Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16);

  113.                         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);

  114.                         Write_port(senddata);
  115.                         myCompleteMessage = myCompleteMessage.Replace(" ", "");
  116.                         if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x06 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x10) return -1;

  117.                         break;
  118.                     default:
  119.                         return -1;
  120.                 }

  121.             }
  122.             catch
  123.             {
  124.                 return -1;
  125.             }
  126.             return 1;
  127.             
  128.         }
  129.         string Addr = "";
  130.         string senddata = "";
  131.         string value = "";
  132.        // int num = 0;
  133.         object locker1 = new object();
  134.         public int FX3G_Read_Soft_Elem(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
  135.         {
  136.             Addr = "";
  137.             senddata = "";
  138.             value = "";
  139.    
  140.            
  141.           //  num = 0;
  142.             try
  143.             {
  144.                 switch (eType)
  145.                 {
  146.                     case (SoftElemType.Y):
  147.                         Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.Y.ToString(), 16), 16).PadLeft(4, '0');
  148.                         senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_线圈, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
  149.                         Write_port(senddata);
  150.                         myCompleteMessage = myCompleteMessage.Replace(" ", "");
  151.                         int leny = nCount / 8;
  152.                         if (nCount % 8 != 0)
  153.                         {
  154.                             leny += 1;
  155.                         }
  156.                         StringBuilder resulty = new StringBuilder(leny * 8);
  157.                         byte[] bvaluey = new byte[leny];
  158.                         if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x01) return -1;
  159.                         for (int i = 0; i < leny; i++)
  160.                         {
  161.                             bvaluey[i] = Convert.ToByte((myCompleteMessage.Substring(6 + 2 * i, 2)), 16);

  162.                         }
  163.                         foreach (byte b in bvaluey)
  164.                         {
  165.                             resulty.Append(Convert.ToString(b, 2).PadLeft(8, '0'));
  166.                         }
  167.                         for (int i = 0; i < leny * 8; i++)
  168.                         {
  169.                             int len1 = (i + 1) / 8;
  170.                             if ((i + 1) % 8 != 0)
  171.                             {
  172.                                 len1 += 1;
  173.                             }
  174.                             pValue[i] = Convert.ToByte(resulty[8 * (2 * len1 - 1) - 1 - i].ToString(), 2);

  175.                         }
  176.                         break;
  177.                     case (SoftElemType.X):
  178.                         Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.X.ToString(), 16), 16).PadLeft(4, '0'); ;
  179.                         senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_输入, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));

  180.                         Write_port(senddata);

  181.                   
  182.                               myCompleteMessage = myCompleteMessage.Replace(" ", "");
  183.                               int lenx = nCount / 8;
  184.                               if (nCount % 8 != 0)
  185.                               {
  186.                                   lenx += 1;
  187.                               }
  188.                               StringBuilder resultx = new StringBuilder(lenx * 8);
  189.                               byte[] bvaluex = new byte[lenx];
  190.                               if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x02) return -1;
  191.                               for (int i = 0; i < lenx; i++)
  192.                               {
  193.                                   bvaluex[i] = Convert.ToByte((myCompleteMessage.Substring(6 + 2 * i, 2)), 16);

  194.                               }
  195.                               foreach (byte b in bvaluex)
  196.                               {
  197.                                   resultx.Append(Convert.ToString(b, 2).PadLeft(8, '0'));
  198.                               }
  199.                               for (int i = 0; i < lenx * 8; i++)
  200.                               {
  201.                                   int len1 = (i + 1) / 8;
  202.                                   if ((i + 1) % 8 != 0)
  203.                                   {
  204.                                       len1 += 1;
  205.                                   }
  206.                                   pValue[i] = Convert.ToByte(resultx[8 * (2 * len1 - 1) - 1 - i].ToString(), 2);

  207.                               }
  208.                               break;
  209.                        
  210.                        
  211.                     case (SoftElemType.M):
  212.                         Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16).PadLeft(4, '0'); ;
  213.                         senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_线圈, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
  214.                         Write_port(senddata);
  215.                         //if (myCompleteMessage.Length < 8) return -1;
  216.                         myCompleteMessage = myCompleteMessage.Replace(" ", "");
  217.                         int len = nCount / 8;
  218.                         if (nCount % 8 != 0)
  219.                         {
  220.                             len += 1;
  221.                         }
  222.                         StringBuilder result = new StringBuilder(len * 8);
  223.                         byte[] bvalue = new byte[len];

  224.                         if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x01) return -1;
  225.                         for (int i = 0; i < len; i++)
  226.                         {
  227.                             bvalue[i] = Convert.ToByte((myCompleteMessage.Substring(6 + 2 * i, 2)), 16);

  228.                         }
  229.                         foreach (byte b in bvalue)
  230.                         {
  231.                             result.Append(Convert.ToString(b, 2).PadLeft(8, '0'));
  232.                         }
  233.                         for (int i = 0; i < len * 8; i++)
  234.                         {
  235.                             int len1 = (i + 1) / 8;
  236.                             if ((i + 1) % 8 != 0)
  237.                             {
  238.                                 len1 += 1;
  239.                             }
  240.                             pValue[i] = Convert.ToByte(result[8 * (2 * len1 - 1) - 1 - i].ToString(), 2);

  241.                         }
  242.                         break;
  243.                     case (SoftElemType.D):
  244.                         Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.D.ToString(), 16), 16).PadLeft(4, '0');
  245.                         senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_输入寄存器, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
  246.                         Write_port(senddata);
  247.                         myCompleteMessage = myCompleteMessage.Replace(" ", "");
  248.                         if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x04) return -1;
  249.                         for (int i = 0; i < 2 * nCount; i = i + 2)
  250.                         {
  251.                             pValue[i] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i, 2), 16);//高8位
  252.                             pValue[i + 1] = Convert.ToByte(myCompleteMessage.ToString().Substring(8 + 2 * i, 2), 16);//低8位
  253.                         }
  254.                         break;

  255.                     case (SoftElemType.WD):
  256.                         Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.D.ToString(), 16), 16).PadLeft(4, '0');
  257.                         senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_输入寄存器, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
  258.                         Write_port(senddata);
  259.                         myCompleteMessage = myCompleteMessage.Replace(" ", "");
  260.                         if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x04) return -1;
  261.                         for (int i = 0; i < 2 * nCount; i = i + 4)
  262.                         {
  263.                             pValue[i] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 2, 2), 16);//低8位
  264.                             pValue[i + 1] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i, 2), 16);//高8位
  265.                             pValue[i + 2] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 6, 2), 16);//低8位
  266.                             pValue[i + 3] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 4, 2), 16);//高8位
  267.                         }
  268.                         break;
  269.                     default:
  270.                         return -1;
  271.                 }
  272.                 return 1;
  273.             }
  274.             catch
  275.             {
  276.                 return -1;
  277.             }
  278.       
  279.         }
  280.         object locker = new object();
  281.         public void Write_port(string Date)
  282.         {
  283.            
  284.             Date = Date.Insert(0, STATE);
  285.             List<string> sendData16 = new List<string>();
  286.             byte[] sendBuffer = null;
  287.             for (int i = 0; i < Date.Length; i += 2)
  288.             {
  289.                 sendData16.Add(Date.Substring(i, 2));
  290.             }
  291.             sendBuffer = new byte[sendData16.Count];
  292.             for (int i = 0; i < sendData16.Count; i++)
  293.             {
  294.                 sendBuffer[i] = (byte)(Convert.ToInt32(sendData16[i], 16));
  295.             }



  296.             byte[] star = bcrc16(sendBuffer);
  297.             StringBuilder recBuffer16 = new StringBuilder();
  298.             List<byte> tmp = new List<byte>(sendBuffer.Length + star.Length);
  299.             tmp.AddRange(sendBuffer);
  300.             tmp.AddRange(star);
  301.             byte[] merged = tmp.ToArray();


  302.             port.Write(merged, 0, merged.Length);
  303.             //DateTime TF_timeh, TS_timeh;
  304.             //TF_timeh = DateTime.Now;
  305.             //bool cc = true;
  306.             //while (cc)
  307.             //{
  308.             //    TS_timeh = DateTime.Now;
  309.             //    double TDelta_t = (TS_timeh - TF_timeh).TotalMilliseconds;
  310.             //    if (TDelta_t > 1000) cc = false;
  311.             //}

  312.             System.Threading.Thread.Sleep(200);
  313.             
  314.         }
  315.         public static byte[] bcrc16(byte[] data)
  316.         {
  317.             if (data.Length == 0)
  318.                 throw new Exception("调用CRC16校验算法,(低字节在前,高字节在后)时发生异常,异常信息:被校验的数组长度为0。");
  319.             byte[] temdata = new byte[data.Length + 2];
  320.             int xda, xdapoly;
  321.             byte i, j, xdabit;
  322.             xda = 0xFFFF;
  323.             xdapoly = 0xA001;
  324.             for (i = 0; i < data.Length; i++)
  325.             {
  326.                 xda ^= data[i];
  327.                 for (j = 0; j < 8; j++)
  328.                 {
  329.                     xdabit = (byte)(xda & 0x01);
  330.                     xda >>= 1;
  331.                     if (xdabit == 1)
  332.                         xda ^= xdapoly;
  333.                 }
  334.             }
  335.             temdata = new byte[2] { (byte)(xda & 0xFF), (byte)(xda >> 8) };
  336.             return temdata;
  337.         }//crc校验
  338.         public void serialport_DataReceived(object sender, SerialDataReceivedEventArgs e)
  339.         {
  340.             lock(locker)
  341.             {
  342.             try
  343.             {
  344.                 System.Threading.Thread.Sleep(50);
  345.                 int n = port.BytesToRead;//先记录下来,避免某种原因,人为的原因,操作几次之间时间长,缓存不一致  

  346.                 if (n < 2)
  347.                     return;
  348.               //  myCompleteMessage = ""; //清除字符串构造器的内容  
  349.                 ////因为要访问ui资源,所以需要使用invoke方式同步ui。  
  350.                 byte[] myReadBuffer = new byte[n];

  351.                 int numberOfBytesRead = 0;

  352.                 // Incoming message may be larger than the buffer size.

  353.                 numberOfBytesRead = port.Read(myReadBuffer, 0, myReadBuffer.Length);//读取缓冲数据  
  354.                 string[] recData = new string[myReadBuffer.Length];
  355.                 StringBuilder recBuffer16 = new StringBuilder();
  356.                 for (int i = 0; i < myReadBuffer.Length; i++)
  357.                 {
  358.                     recBuffer16.AppendFormat("{0:X2}" + " ", myReadBuffer[i]);
  359.                     recData[i] = myReadBuffer[i].ToString("X2");
  360.                 }
  361.                 myCompleteMessage = recBuffer16.ToString();

  362.                 //  myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead));
  363.                
  364.             }
  365.             catch
  366.             {
  367.                 return ;
  368.             }
  369.             }
  370.            }
  371.                   

  372.         public int FX3G_Read_Soft_Elem_Float(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
  373.         {
  374.             
  375.             try
  376.             {
  377.                 if (eType != SoftElemType.WD)
  378.                     return -1;
  379.                 Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.D.ToString(), 16), 16).PadLeft(4, '0');
  380.                 senddata = string.Format("{0:x2}{1}{2}", FunctionName.Read_输入寄存器, Addr, Convert.ToString(nCount, 16).PadLeft(4, '0'));
  381.                 Write_port(senddata);

  382.                 lock (locker)
  383.                 {
  384.                     myCompleteMessage = myCompleteMessage.Replace(" ", "");
  385.                  
  386.                     if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x04)
  387.                         return -1;
  388.                     for (int i = 0; i < 2 * nCount; i = i + 4)
  389.                     {
  390.                         pValue[i] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 2, 2), 16);//低8位
  391.                         pValue[i + 1] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i, 2), 16);//高8位
  392.                         pValue[i + 2] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 6, 2), 16);//低8位
  393.                         pValue[i + 3] = Convert.ToByte(myCompleteMessage.ToString().Substring(6 + 2 * i + 4, 2), 16);//高8位
  394.                     }
  395.                     return 1;
  396.                 }
  397.             }
  398.             catch
  399.             {
  400.                 return -1;
  401.             }
  402.             
  403.         }

  404.         public int FX3G_Write_Soft_Elem_Float(SoftElemType eType, int nStartAddr, int nCount, byte[] pValue, int nNetId = 0)
  405.         {
  406.            
  407.             try
  408.             {
  409.                 if (eType != SoftElemType.WD)
  410.                     return -1;
  411.                 for (int i = 0; i < pValue.Length; i++)

  412.                     value += string.Format("{0:x2}", pValue[i]);

  413.                 Addr = Convert.ToString(nStartAddr + Convert.ToInt16(Type.M.ToString(), 16), 16);

  414.                 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);

  415.                 Write_port(senddata);
  416.                 myCompleteMessage = myCompleteMessage.Replace(" ", "");
  417.                 if (Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x06 && Convert.ToByte((myCompleteMessage.Substring(2, 2)), 16) != 0x10) return -1;
  418.                 return 1;
  419.             }
  420.             catch
  421.             {
  422.                 return -1;
  423.             }
  424.         }
  425.         

  426.     }
  427. }
复制代码

所有资料51hei提供下载:
FX3GModbusAPI.rar (27.5 KB, 下载次数: 231)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:585878 发表于 2019-7-31 19:25 | 显示全部楼层
实在是太有帮助了 ,赞赞赞!
回复

使用道具 举报

ID:27254 发表于 2020-2-19 09:41 | 显示全部楼层
还没试验,不够要感谢发帖。
回复

使用道具 举报

ID:46331 发表于 2020-6-8 17:44 | 显示全部楼层
源码能打开,不知道为什么在VS里面打不开
回复

使用道具 举报

ID:684781 发表于 2020-6-18 22:49 | 显示全部楼层
完全看不懂
回复

使用道具 举报

ID:307512 发表于 2020-7-20 10:17 | 显示全部楼层
好帖子,就是为啥代码有几个报错呢
回复

使用道具 举报

ID:940560 发表于 2021-6-19 18:04 | 显示全部楼层
实在是太有帮助了 ,赞赞赞!
回复

使用道具 举报

ID:948487 发表于 2021-7-2 20:56 | 显示全部楼层
实在是太有帮助了 ,赞赞赞
回复

使用道具 举报

ID:952377 发表于 2021-7-13 01:32 | 显示全部楼层
正在学plc,谢谢
回复

使用道具 举报

ID:382728 发表于 2021-11-20 11:17 | 显示全部楼层

完全看不懂
回复

使用道具 举报

ID:65369 发表于 2023-8-13 20:13 | 显示全部楼层
实在是太有帮助了,谢谢楼主!
回复

使用道具 举报

ID:600309 发表于 2023-10-3 08:28 | 显示全部楼层
实在是太有帮助了 ,赞赞赞!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表