C#实现三菱FX-3U SerialOverTcp

news2024/9/29 9:30:20

设备信息

测试结果

D值测试

 Y值写入后读取测试

 协议解析

三菱FX 3U系列PLC的通信协议

1. 每次给PLC发送指令后,必须等待PLC的应答完成才能发送下一条指令;
2. 报文都是十六进制ASCII码的形式
3. 相关指令

指令 命令码(ASCII码) 操作原件
读 0(30H) X,Y,M,S,T,C,D
写 1(31H) X,Y,M,S,T,C,D
置位 7(37H) X,Y,M,S,T,C
复位 8(38H) X,Y,M,S,T,C

地址换算:D123这个地址写入数据,那么地址为: address = 123*2 + 4096 = 4342 = 10F6
==================================================================================
读指令

上位机请求:STX(1) + CMD(1) + Address(4) + Length(2) + ETX(1) + SUM(2,从cmd到etx)

PLC响应:STX(1) + 值(n字节) + ETX(1) + SUM(2)

**********************************************************************************
例子:
X,Y,D通过相应的地址换算成新的地址

读取Y005 / Y006 bool

02 30 30 30 41 30 30 31 03 36 35 :范围(0-7 地址) 地址: A0 160
02 30 30 30 41 31 30 31 03 36 36 :范围(10-17 地址) 地址: A1 161
02 30 30 30 41 32 30 31 03 36 37 :范围(20-27 地址) 地址: A2 162

02 30 30 30 41 30 30 31 03 36 35

02 32 30 03 36 35:5亮 32 30 -> 20H -> 转二进制 0010 0000

02 36 30 03 36 39:5,6亮 36 30 -> 60H -> 转二进制 0110 0000


D123读取2个字节,short类型
新版:指令45
老版:
02 30 31 30 46 36 30 32 03 37 32
02 30 30 30 30 03 43 33 -- 值为0
02 30 31 30 30 03 43 34 -- 值为1

==================================================================================
写指令

上位机请求:STX(1) + CMD(1) + Address(4) + Length(2) + Data(4*n)+ ETX(1) + SUM(2,从cmd到etx)

PLC响应:STX(1) + 值(1字节 正确:06H;错误:15H) + ETX(1) + SUM(2)

例子:

Y006设置true
02 37 30 36 30 35 03 30 35
06

D123写入2个字节,short类型,值1

新版
0245313034304636303230313030034143
06

老版:写入值:1
02 31 31 30 46 36 30 34 30 31 30 30 30 30 30 30 03 46 36
06

================================================

核心代码

复制代码

using MelsecFxOverTcp;
using System;
using System.Net.Sockets;
using System.Text;

namespace MelsecFxSerialOverTcp.Util
{
    class MelsecFx
    {
        string ip = string.Empty;
        int port = 0;
        int SendTimeout = 2000;
        int ReceiveTimeout = 2000;

        public MelsecFx(string ip, int port)
        {
            this.ip = ip;
            this.port = port;
        }

        static string NotSupportedDataType => "输入的类型不支持,请重新输入";

        /// <summary>
        /// 地址解析
        /// </summary>
        static void FxAnalysisAddress(string address, ref MelsecMcDataType Content1, ref ushort Content2)
        {
            switch (address[0])
            {
                case 'M':
                case 'm':
                    Content1 = MelsecMcDataType.M;
                    Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.M.FromBase);
                    break;
                case 'X':
                case 'x':
                    Content1 = MelsecMcDataType.X;
                    Content2 = Convert.ToUInt16(address.Substring(1), 8);
                    break;
                case 'Y':
                case 'y':
                    Content1 = MelsecMcDataType.Y;
                    Content2 = Convert.ToUInt16(address.Substring(1), 8);
                    break;
                case 'D':
                case 'd':
                    Content1 = MelsecMcDataType.D;
                    Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.D.FromBase);
                    break;
                case 'S':
                case 's':
                    Content1 = MelsecMcDataType.S;
                    Content2 = Convert.ToUInt16(address.Substring(1), MelsecMcDataType.S.FromBase);
                    break;
                case 'T':
                case 't':
                    if (address[1] == 'N' || address[1] == 'n')
                    {
                        Content1 = MelsecMcDataType.TN;
                        Content2 = Convert.ToUInt16(address.Substring(2), MelsecMcDataType.TN.FromBase);
                        break;
                    }

                    if (address[1] == 'S' || address[1] == 's')
                    {
                        Content1 = MelsecMcDataType.TS;
                        Content2 = Convert.ToUInt16(address.Substring(2), MelsecMcDataType.TS.FromBase);
                        break;
                    }

                    if (address[1] == 'C' || address[1] == 'c')
                    {
                        Content1 = MelsecMcDataType.TC;
                        Content2 = Convert.ToUInt16(address.Substring(2), MelsecMcDataType.TC.FromBase);
                        break;
                    }

                    throw new Exception(NotSupportedDataType);
                case 'C':
                case 'c':
                    if (address[1] == 'N' || address[1] == 'n')
                    {
                        Content1 = MelsecMcDataType.CN;
                        Content2 = Convert.ToUInt16(address.Substring(2), MelsecMcDataType.CN.FromBase);
                        break;
                    }

                    if (address[1] == 'S' || address[1] == 's')
                    {
                        Content1 = MelsecMcDataType.CS;
                        Content2 = Convert.ToUInt16(address.Substring(2), MelsecMcDataType.CS.FromBase);
                        break;
                    }

                    if (address[1] == 'C' || address[1] == 'c')
                    {
                        Content1 = MelsecMcDataType.CC;
                        Content2 = Convert.ToUInt16(address.Substring(2), MelsecMcDataType.CC.FromBase);
                        break;
                    }

                    throw new Exception(NotSupportedDataType);
                default:
                    throw new Exception(NotSupportedDataType);
            }
        }

        public bool ConnectServer()
        {
            bool ret = false;

            TcpClient client = null;

            try
            {
                using (client = new TcpClient(ip, port))
                {
                    ret = client.Connected;
                    client.Close();
                }
            }
            catch (Exception ex)
            {

            }
            finally
            {
                if (null != client) client.Close();
            }

            return ret;
        }

        /// <summary>
        /// // 串口或者网口发送数据
        /// </summary>
        /// <exception cref="Exception"></exception>
        byte[] SendWaitResponse(byte[] data)
        {
            var requestStr = DataHelper.ToHexString(data, data.Length, true);
            DataMgr.MainUI.AddMessage("C -> S: " + requestStr);

            byte[] ret = null;

            using (var client = new TcpClient(ip, port))
            {
                client.SendTimeout = SendTimeout;
                client.ReceiveTimeout = ReceiveTimeout;
                var netstream = client.GetStream();
                //
                netstream.Write(data, 0, data.Length);
                //
                byte[] temp = new byte[2048];
                int recvnum = netstream.Read(temp, 0, temp.Length);
                if (recvnum == 0)
                {
                    throw new Exception("数据接收超时");
                }
                ret = new byte[recvnum];
                Array.Copy(temp, 0, ret, 0, recvnum);
            }

            var responseStr = DataHelper.ToHexString(ret, ret.Length, true);
            DataMgr.MainUI.AddMessage("S -> C: " + responseStr);

            return ret;
        }

        public bool[] ReadBool(string address, int length)
        {
            Console.WriteLine($"ReadBool,address={address},length={length}");

            MelsecMcDataType Content1 = MelsecMcDataType.M;
            ushort Content2 = 0;

            FxAnalysisAddress(address, ref Content1, ref Content2);

            // 地址转换
            ushort content = Content2;

            if (Content1 == MelsecMcDataType.M)
            {
                content = ((content < 8000) ? ((ushort)((int)content / 8 + 256)) : ((ushort)((content - 8000) / 8 + 480)));
            }
            else if (Content1 == MelsecMcDataType.X)
            {
                content = (ushort)((int)content / 8 + 128);
            }
            else if (Content1 == MelsecMcDataType.Y)
            {
                content = (ushort)((int)content / 8 + 160);
            }
            else if (Content1 == MelsecMcDataType.S)
            {
                content = (ushort)((int)content / 8);
            }
            else if (Content1 == MelsecMcDataType.CS)
            {
                content = (ushort)((int)content / 8 + 448);
            }
            else if (Content1 == MelsecMcDataType.CC)
            {
                content = (ushort)((int)content / 8 + 960);
            }
            else if (Content1 == MelsecMcDataType.TS)
            {
                content = (ushort)((int)content / 8 + 192);
            }
            else
            {
                if (Content1 != MelsecMcDataType.TC)
                { 
                    throw new Exception("当前的类型不支持位读写");
                }

                content = (ushort)((int)content / 8 + 704);
            }

            var Content3 = (ushort)((int)Content2 % 8);

            ushort num = (ushort)((Content2 + length - 1) / 8 - (int)Content2 / 8 + 1);
           
            byte[] array = new byte[11]
            {
                2,
                48,
                SoftBasic.BuildAsciiBytesFrom(content)[0],
                SoftBasic.BuildAsciiBytesFrom(content)[1],
                SoftBasic.BuildAsciiBytesFrom(content)[2],
                SoftBasic.BuildAsciiBytesFrom(content)[3],
                SoftBasic.BuildAsciiBytesFrom((byte)num)[0],
                SoftBasic.BuildAsciiBytesFrom((byte)num)[1],
                3,
                0,
                0
            };
            DataHelper.FxCalculateSum(array).CopyTo(array, 9); 
            
            byte[] response = SendWaitResponse(array);

            // **********************
            // Y005 or Y006 读取测试
            //string responseStr = "02 36 30 03 36 39";// 5亮:02 32 30 03 36 35 // 5和6亮:02 36 30 03 36 39

            //var response = DataHelper.ToHexByte(responseStr); 

            var results = ExtractActualBoolData(response, Content3, length); 

            return results;
        }

        public byte[] ReadWord(string address, ushort length, bool isNewVersion = false)
        {
            Console.WriteLine($"ReadWord,address={address},length={length}");

            MelsecMcDataType Content1 = MelsecMcDataType.M;
            ushort Content2 = 0;

            FxAnalysisAddress(address, ref Content1, ref Content2);

            ushort content = Content2;

            if (Content1 == MelsecMcDataType.D)
            {
                content = ((content < 8000) ? (isNewVersion ? ((ushort)(content * 2 + 16384)) : ((ushort)(content * 2 + 4096))) : ((ushort)((content - 8000) * 2 + 3584)));
            }
            else if (Content1 == MelsecMcDataType.CN)
            {
                content = ((content < 200) ? ((ushort)(content * 2 + 2560)) : ((ushort)((content - 200) * 4 + 3072)));
            }
            else
            {
                if (Content1 != MelsecMcDataType.TN)
                { 
                    throw new Exception("当前的类型不支持字读写");
                }

                content = (ushort)(content * 2 + 2048);
            }

            length = (ushort)(length * 2);
             
            byte[] array;

            if (isNewVersion)
            {
                array = new byte[13]
                {
                    2,
                    69,
                    48,
                    48,
                    SoftBasic.BuildAsciiBytesFrom(content)[0],
                    SoftBasic.BuildAsciiBytesFrom(content)[1],
                    SoftBasic.BuildAsciiBytesFrom(content)[2],
                    SoftBasic.BuildAsciiBytesFrom(content)[3],
                    SoftBasic.BuildAsciiBytesFrom((byte)length)[0],
                    SoftBasic.BuildAsciiBytesFrom((byte)length)[1],
                    3,
                    0,
                    0
                };
                DataHelper.FxCalculateSum(array).CopyTo(array, 11);

            }
            else
            {
                array = new byte[11]
                {
                2,
                48,
                SoftBasic.BuildAsciiBytesFrom(content)[0],
                SoftBasic.BuildAsciiBytesFrom(content)[1],
                SoftBasic.BuildAsciiBytesFrom(content)[2],
                SoftBasic.BuildAsciiBytesFrom(content)[3],
                SoftBasic.BuildAsciiBytesFrom((byte)length)[0],
                SoftBasic.BuildAsciiBytesFrom((byte)length)[1],
                3,
                0,
                0
                };
                DataHelper.FxCalculateSum(array).CopyTo(array, 9);
            }

            //var request = DataHelper.ToHexString(array, array.Length, true);
            //DataMgr.MainUI.AddMessage("request:" + request);

            // 串口或者网口发送数据
            // .....
            // 

            // **********************
            // D123 读取测试
            //string responseStr = "02 30 31 30 30 03 43 34";// 值为0:02 30 30 30 30 03 43 33 // 值为1:02 30 31 30 30 03 43 34

            //var response = DataHelper.ToHexByte(responseStr);

            //DataMgr.MainUI.AddMessage(responseStr);

            var response = SendWaitResponse(array);

            var results = ExtractActualData(response);

            return results;
        }

        public void WriteBool(string address, bool value)
        {
            Console.WriteLine($"WriteBool,address={address},value={value}");

            MelsecMcDataType Content1 = MelsecMcDataType.M;
            ushort Content2 = 0;

            FxAnalysisAddress(address, ref Content1, ref Content2);  

            ushort content = Content2;
            if (Content1 == MelsecMcDataType.M)
            {
                content = ((content < 8000) ? ((ushort)(content + 2048)) : ((ushort)(content - 8000 + 3840)));
            }
            else if (Content1 == MelsecMcDataType.S)
            {
                content = content;
            }
            else if (Content1 == MelsecMcDataType.X)
            {
                content = (ushort)(content + 1024);
            }
            else if (Content1 == MelsecMcDataType.Y)
            {
                content = (ushort)(content + 1280);
            }
            else if (Content1 == MelsecMcDataType.CS)
            {
                content = (ushort)(content + 448);
            }
            else if (Content1 == MelsecMcDataType.CC)
            {
                content = (ushort)(content + 960);
            }
            else if (Content1 == MelsecMcDataType.CN)
            {
                content = (ushort)(content + 3584);
            }
            else if (Content1 == MelsecMcDataType.TS)
            {
                content = (ushort)(content + 192);
            }
            else if (Content1 == MelsecMcDataType.TC)
            {
                content = (ushort)(content + 704);
            }
            else
            {
                if (Content1 != MelsecMcDataType.TN)
                {
                    // "当前的类型不支持位读写"
                    return ;
                }

                content = (ushort)(content + 1536);
            }

            byte[] array = new byte[9]
            {
                2,
                (byte)(value ? 55 : 56),
                SoftBasic.BuildAsciiBytesFrom(content)[2],
                SoftBasic.BuildAsciiBytesFrom(content)[3],
                SoftBasic.BuildAsciiBytesFrom(content)[0],
                SoftBasic.BuildAsciiBytesFrom(content)[1],
                3,
                0,
                0
            };
            DataHelper.FxCalculateSum(array).CopyTo(array, 7);

            SendWaitResponse(array);
        }

        //public static void Write(string address, int value)
        //{
        //    Write(address, new int[1] { value });
        //}

        //public static void Write(string address, int[] values)
        //{
        //    Write(address, ByteTransformBase.TransByte(values));
        //}

        public void WriteWord(string address, byte[] value, bool isNewVersion = false)
        {
            Console.WriteLine($"WriteBytes,address={address},value={value}");

            MelsecMcDataType Content1 = MelsecMcDataType.M;
            ushort Content2 = 0;

            FxAnalysisAddress(address, ref Content1, ref Content2);

            ushort content = Content2;

            if (Content1 == MelsecMcDataType.D)
            {
                content = ((content < 8000) ? (isNewVersion ? ((ushort)(content * 2 + 16384)) : ((ushort)(content * 2 + 4096))) : ((ushort)((content - 8000) * 2 + 3584)));
            }
            else if (Content1 == MelsecMcDataType.CN)
            {
                content = ((content < 200) ? ((ushort)(content * 2 + 2560)) : ((ushort)((content - 200) * 4 + 3072)));
            }
            else
            {
                if (Content1 != MelsecMcDataType.TN)
                {
                    return;// 当前的类型不支持字读写
                }

                content = (ushort)(content * 2 + 2048);
            }

            if (value != null)
            {
                value = SoftBasic.BuildAsciiBytesFrom(value);
            }
             
            byte[] array = null;

            if (isNewVersion)
            {
                array = new byte[13 + value.Length];
                array[0] = 2;
                array[1] = 69;
                array[2] = 49;
                array[3] = 48;
                array[4] = SoftBasic.BuildAsciiBytesFrom(content)[0];
                array[5] = SoftBasic.BuildAsciiBytesFrom(content)[1];
                array[6] = SoftBasic.BuildAsciiBytesFrom(content)[2];
                array[7] = SoftBasic.BuildAsciiBytesFrom(content)[3];
                array[8] = SoftBasic.BuildAsciiBytesFrom((byte)(value.Length / 2))[0];
                array[9] = SoftBasic.BuildAsciiBytesFrom((byte)(value.Length / 2))[1];
                Array.Copy(value, 0, array, 10, value.Length);
                array[array.Length - 3] = 3; 
            }
            else
            {
                array = new byte[11 + value.Length];
                array[0] = 2;
                array[1] = 49;
                array[2] = SoftBasic.BuildAsciiBytesFrom(content)[0];
                array[3] = SoftBasic.BuildAsciiBytesFrom(content)[1];
                array[4] = SoftBasic.BuildAsciiBytesFrom(content)[2];
                array[5] = SoftBasic.BuildAsciiBytesFrom(content)[3];
                array[6] = SoftBasic.BuildAsciiBytesFrom((byte)(value.Length / 2))[0];
                array[7] = SoftBasic.BuildAsciiBytesFrom((byte)(value.Length / 2))[1];
                Array.Copy(value, 0, array, 8, value.Length);
                array[array.Length - 3] = 3;
            }
            DataHelper.FxCalculateSum(array).CopyTo(array, array.Length - 2);

            SendWaitResponse(array); 
        }

        public static string CheckPlcReadResponse(byte[] ack)
        {
            if (ack.Length == 0)
            {
                return "接收的数据长度为0";
            }

            if (ack[0] == 21)
            {
                return "PLC反馈的数据无效,Actual: " + SoftBasic.ByteToHexString(ack, ' ');
            }

            if (ack[0] != 2)
            {
                return "PLC反馈信号错误:" + ack[0] + " Actual: " + SoftBasic.ByteToHexString(ack, ' ');
            }

            if (!DataHelper.CheckSum(ack))
            {
                return "PLC反馈报文的和校验失败!";
            }

            return string.Empty;
        }

        public static byte[] ExtractActualData(byte[] response)
        {
            byte[] array = new byte[(response.Length - 4) / 2];
            for (int i = 0; i < array.Length; i++)
            {
                byte[] bytes = new byte[2]
                {
                    response[i * 2 + 1],
                    response[i * 2 + 2]
                };
                array[i] = Convert.ToByte(Encoding.ASCII.GetString(bytes), 16);
            }

            return array;
        }

        public static bool[] ExtractActualBoolData(byte[] response, int start, int length)
        {
            // 02 32 30 03 36 35 Data:20H -> 十进制32 -> 0010 0000
            // 02 36 30 03 36 39 Data:60H -> 十进制96 -> 0110 0000
            byte[] Content = ExtractActualData(response);
            bool[] arraybool = new bool[length];
            bool[] array2 = SoftBasic.ByteToBoolArray(Content, Content.Length * 8);// false false false false true false false

            for (int i = 0; i < length; i++)
            {
                arraybool[i] = array2[i + start];
            }

            return arraybool;
        }
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/852950.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

七牛云获取qn(url、bucket、access-key、secret-key)

1.注册账号 2.access-key和secret-key&#xff1a; 点击“密钥管理” 复制AK和SK即可 域名&#xff1a; bucket&#xff1a; 这个就是对象存储空间名字 先新建一个空间&#xff08;没买需要先购买&#xff09;&#xff0c;步骤如下&#xff1a; 填写存储空间名字&#xff0…

“OSError: [WinError 1455]页面文件太小,无法完成操作。”解决方案

按照下面步骤, 会发现电脑默认情况下是没有给D盘分配虚拟内存的, 所以将Python装在D盘的朋友, 在跑程序时, 没有分配虚拟内存, 自然就遇到了上面的问题, 所以根本操作只要给D盘分配虚拟内存即可 第一步&#xff1a;鼠标右击我的电脑 (此电脑)&#xff0c;点击属性进入以下界面 …

PostMessage/SendMessage在不同线程的调用探究

PostMessage和SendMessage是我们比较常用的windows API&#xff0c;最近也探究这两个api在调用之后&#xff0c;执行的线程问题&#xff0c;发现如下结论&#xff1a; 仅仅是RegisterClass注册类之后&#xff0c;调用createwindow第一个参数通过&#xff1a;(const TCHAR*)base…

three.js 地球与卫星绕地飞行【真实三维数据】

&#xff08;真实经纬度运行轨迹&#xff09; 完整代码 <template><div class"home3dMap" id"home3dMap" v-loading"loading"></div> </template><script> import * as THREE from three import { OrbitControl…

【K8S 的二进制搭建】

目录 一、二进制搭建 Kubernetes v1.201、准备环境 二、操作系统初始化配置三、部署 etcd 集群1、准备签发证书环境2、在 master01 节点上操作1、生成Etcd证书 3、在 node01 节点上操作4、在 node02 节点上操作 四、部署 Master 组件五、部署 docker引擎六、部署 Worker Node 组…

【算法|数组】手撕经典二分法

算法|数组——二分查找 文章目录 算法|数组——二分查找引言二分查找左闭右闭写法左闭右开写法 总结 引言 首先学习这个算法之前需要了解数组知识&#xff1a;数组。 大概介绍以下&#xff1a; 数组是存储在连续内存空间上的相同类型数据的集合。数组下标都是从0开始。数组在…

【SpringCloud】Gateway服务网关

Spring Cloud Gateway 是 Spring Cloud 的一个全新项目&#xff0c;该项目是基于 Spring 5.0&#xff0c;Spring Boot 2.0 和 Project Reactor 等响应式编程和事件流技术开发的网关&#xff0c;它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。 1.为什么需要网关…

“实现数字化转型:探索会议OA项目的高级技术与创新应用“

文章目录 引言&#xff1a;1.项目背景和需求分析&#xff1a;2.技术选型和架构设计&#xff1a;3.项目实现和功能亮点&#xff1a;3.0 layui实现登录及注册3.1 会议管理模块3.1.1 会议发布3.1.2 我的会议3.1.3 我的审批3.1.4 会议通知3.1.5 待开会议3.1.6 历史会议3.1.7 所有会…

【Leetcode】层次遍历||树深度||队列

step by step. 题目&#xff1a; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 示例 1&#xff1a; 输入&#xff1a;root [3,9,20,null,null,15,7] 输出&#xff1a;3示例 2&#xff1a; 输入&am…

【LeetCode】数据结构题解(13)[设计循环链表]

设计循环链表 &#x1f609; 1.题目来源&#x1f440;2.题目描述&#x1f914;3.解题思路&#x1f973;4.代码展示 所属专栏&#xff1a;玩转数据结构题型❤️ &#x1f680; >博主首页&#xff1a;初阳785❤️ &#x1f680; >代码托管&#xff1a;chuyang785❤️ &…

WordPress使用【前端投稿】功能时为用户怎么添加插入文章标签

在使用Wordpress做前端投稿功能的时候&#xff0c;可能需要用户填写文章标签&#xff0c;在插入文章的时候很多人不知道怎么把这些标签插入进去&#xff0c;下面这篇文章来为大家带来WordPress使用前端投稿功能时插入文章标签方法。 在Wordpress里 wp_insert_post 此函数的作…

Vue3核心笔记

文章目录 1.Vue3简介2.Vue3带来了什么1.性能的提升2.源码的升级3.拥抱TypeScript4.新的特性 一、创建Vue3.0工程1.使用 vue-cli 创建2.使用 vite 创建 二、常用 Composition API1.拉开序幕的setup2.ref函数3.reactive函数4.Vue3.0中的响应式原理vue2.x的响应式Vue3.0的响应式 5…

冠达管理:夜盘是什么意思?

跟着现代社会的快节奏开展&#xff0c;股票商场的运营也因而发生了相应的改变。夜盘是指在正常的买卖时刻外特别敞开的买卖商场&#xff0c;为出资者供给更多的买卖时刻和机会。夜盘的概念在我国自2002年引入以来逐渐被越来越多的出资者所熟知。那么夜盘究竟是什么&#xff1f;…

Collection 中的简单命令

一、list 集合常用的方法 LIst&#xff1a;元素存取有序、可以保存重复元素、有下标。可以存储 null 值。 ArrayList&#xff1a;底层数组结构&#xff0c;有 index&#xff0c;查询快 LinkList&#xff1a; 底层链表结构&#xff0c;增删快 添加 //确保此集合包含指定的元素…

操作系统—进程管理

这里写目录标题 进程特点并行和并发进程的状态进程的控制结构PCB包含什么信息 进程上下文切换进程上下文切换发生的场景 进程的通信方式 线程什么是线程线程的优缺点进程线程的区别线程的上下文切换线程的实现用户线程和内核线程的对应关系 用户线程如何理解、优缺点内核线程如…

在Echarts中的tooltip上添加点击按钮

需求&#xff1a; 在Echarts的tooltips中添加点击按钮并可以鼠标悬停点击该按钮 功能实现&#xff1a; 在option中的tooltip添加enterable: true的属性&#xff0c;表示鼠标可以移入tooltip中再在formatter中添加 <button onclick"onTooltipsFun()" stylecursor:…

protobuf 2定义string常量

背景 protobuf 2中定义的enum枚举值必须为数字类型&#xff0c;故不支持string类型&#xff0c;但有些业务场景又确实需要定义string常量。 目标 在protobuf 2中定义string常量。 方案 思路&#xff1a;通optional default实现string常量。 细节&#xff1a; 1、protobu…

直击HDC展区现场,华为天气开启天气+生活新方式

备受瞩目的HDC 2023 大会正式举办&#xff0c;华为天气携气象领域最新成果展现在大会现场&#xff0c;经过在线下展区实际体验过后&#xff0c;我被天气服务卡强势“种草”了。 天气与人们生活息息相关&#xff0c;面对日益复杂的天气场景&#xff0c;简单的“打开APP看天气”…

手搓单链表

文章目录 前言一、链表和顺序表的区别二、什么是单链表单链表分类单链表的结构 三、带头不循环单链表1.单链表的结构体2.带头不循环单链表的初始化和销毁3.带头不循环单链表的头插&#xff0c;尾插和打印4.带头不循环单链表的头删和尾删5.带头不循环单链表的查找&#xff0c;指…

冠达管理:创新药概念强势拉升,康希诺大涨超15%

立异药概念9日盘中强势拉升&#xff0c;到发稿&#xff0c;昊帆生物“20cm”涨停&#xff0c;康希诺大涨超15%&#xff0c;翰宇药业涨近13%&#xff0c;德展健康涨停&#xff0c;泰格医药、药石科技涨超7%。 康希诺昨日晚间公告&#xff0c;8月7日&#xff0c;公司与 AstraZene…