C#工控上位机开发

2023-05-16

对于电源软件开发者来说,上位机的开发难度是远远小于下位机的,之前几个月我一直在研究电力电子技术和下位机的控制算法,也有了一点点的收获,但说实话还是差的太远了,而且人力物力资源非常稀缺,为了做个负反馈控制实验还得自己掏钱买电机,到后来又发现负反馈电路还得专业人士搭建,示波器乱漆芭蕉的波形仿佛测的是自己的心电图,无奈。不过后续我会梳理一下这方面开发的学习心得,不得不说,整个电源的自主研发过程真的是道阻且长。

鲁迅先生曾经说过,柿子得挑软的捏,而且厂里确实也有需求,所以最近花了两周时间在开发工控上位机软件。虽说是个软柿子,但捏的确实不轻松(或许这就是弱者的世界吧T.T),不过不管怎么样,最终也是开发成功了,不枉我两周的爆肝。

那么废话不多说了,进入正题。

一.开发前的准备

(1)编程环境

我选用的编程环境是Vsual Studio 2019,之前在学linux操作系统时用过QTCreator,感觉两者也差不多,不过VS在制作窗体应用程序时采用的语言是C#,QT采用的是C++。C#是面向对象的,但语法上来看又是C,基本上懂C和C++的话,C#都能无师自通了。VS在官网上可以直接搜索下载,下载的教程也是比较丰富的,这里不做过多介绍。在选择工作负载时要确定好自己的设计目标,比如是进行游戏开发,还是网站开发,又或者是做个简单的窗体应用小程序,在进行窗体程序开发时是需要下载.netFramework框架的,框架已有多个版本,在确立好框架版本后你制作窗体软件的整个过程都是依赖于它的,(注意更新VS后,之前的框架可能会被删除,这个时候得去官网上找你之前的项目所依赖的.netFramework框架版本)。

因为是依赖于.netFramework框架的,因此很多底层的程序都是写完封装在类库里,只需要进行调用即可,当然开发过程中你也可以自己去写类库并进行添加和调用。

打开VS——>创建新项目——>搜索选择windows窗体应用(.netFramework)模板——>编辑项目名称,存储位置等——>创建,完成后会显示如下所示界面。

 在.cs[设计]中会有一个窗体,左边是工具箱,如果工具箱不见了可以按快捷键Ctrl+Alt+X,在工具箱中会有大量的控件,比如按钮,文本框,下拉框,进度条,定时器等等,制作时将该控件拖动到窗体中就行了,右边的属性就是你来对控件的操作,其实窗体也是个控件,因此上图的属性里就是对窗体进行设置,属性框里的闪电记号是事件的意思,当发生了某种事件时会执行的相应操作,可以通过双击某个事件进入.CS*的编程界面。那么窗体应用程序的整个开发也就是由这些基本的操作来展开的。

(2)下位机仿真

下位机采用的是西门子PLC,CPU型号是S7-1200,通信选择的是profinet通信协议。但控制板在工厂里的电源柜里使用中,实际的开发不可能跑现场去写一下运行一下。而想要进行完整的仿真我用到了两个软件,TIA Portal V16和S7-PLCSIM Advanced V3.0,前者为PLC控制板提供了编程环境,它本身可以当成一个PLC板,后者可以建立虚拟PLC与上位机的通信。

该图是TIA Portal V16某项目正在运行的界面。市面上的PLC控制板五花八门,每一种编程方式或者通信协议可能都不太一样,所以工控人多多少少有点难做,不过自主研发控制板就没那么纠结了,自产自销才是王道,毕竟学人家的完事儿了还得问人家买,典型的吃力不讨好。

下面说下TIA Portal V16打开后的一些操作。

  1. 创建一个新项目——>项目视图
  2. 添加一个CPU——>比如S7-1500
  3. CPU属性——>常规——>安全与防护——>允许远程访问
  4. 项目名——>属性——>保护——>允许块编译时仿真
  5. 程序块——>添加新块——>数据块
  6. 创建一个新数据类型后——>数据块——>属性——>常规——>属性——>取消所有勾选
  7. 工具下方的——>下载——>PC/PG接口(选择Siemens PLCSIM virtual Ethernet Adapter)——>开始搜索——>开始下载——>转至在线                            

在第七步下载之前需要打开PLCSIM仿真软件,否则在接口中是找不到想要的选项的。下图是进行配置时需要注意的一些事项:

 

首先是打开网络适配设置找到PLC的以太网,将IP地址改为与PLC处于同一网段的地址,然后在仿真软件里按如图所示进行连接,注意如果Online Acess选项中无法将按钮转至右侧,需要下载WinPcap,它可以提供网络接口。

在做好这些工作之后就可以通过编程来实现与PLC之间的数据通信了。

(3)数据库

数据库软件选择的是SQL Srever

SQL Server 2019 安装教程_SZU_黄其才-CSDN博客

这个博主写了详细的安装和配置细节。

 对数据库的所有操作都可以通过输入指令来完成(这也是为什么其他应用程序能够操作数据库的根本原因),当然能点击肯定还是点击方便,毕竟那些脚本指令也是挺多的,而且不太好记。因此可以很方便的通过点击去建立一个表并确定好各列的名称,对主键进行设置,是否允许控制,存储的数据类型等。

二.开发思路及代码详解

(1)实时显示系统时间

用到一个timer控件(工具箱组件里的,注意和日历控件区分)和一个label控件。Timer控件就是定时器,从功能来看类似于多线程的死循环,都拖入窗体后单击定时器在属性行为里把Enabled改为false,interval改成1000或者100也行,这代表它每100毫秒或是1000毫秒获取执行一次,(当然也可以在代码里进行更改,代码的优先级应该是高一点的吧)

private void timer1_Tick(object sender, EventArgs e)

        {

            label1.Text = DateTime.Now.ToString("yyyy年MM月dd日HH时mm分ss秒 ddd");

        }

执行的内容是将label1的文本内容进行方法(函数)返回值的赋值,该方法的作用是获取系统当前的时间并转化成字符串形式,如果要改成12小时制将HH改为hh即可,或者想以别的样式显示,但是某些特定的字符串在该方法中的显示出来的内容是固定的,比如ss返回的必然是系统的秒钟。

(2)连接PLC控制板

首先需要在VS添加一个程序包,操作方法是工具——>NuGet包管理器——>管理解决方案的程序包,在浏览中搜索S7netplus,安装

安装完成后在命名空间中引用 using S7.Net 即可(类似于添加头文件)

private Plc myplc;//实例化plc

private void radioButton5_CheckedChanged(object sender, EventArgs e)

        {

            if (radioButton5.Checked == true)

            {

                    myplc = new Plc(CpuType.S71200, "192.168.0.1", 0, 1);//Cpu型号,plc地址,机架号,插槽号

                    try

                    {

                        myplc.Open();

                    }

                    catch (Exception EX)

                    {

                        MessageBox.Show(EX.Message);

                    }

            }

        }

Try,catch语句用try来执行某个操作,当出现错误后catch执行某个操作,这里try的任务是与plc进行连接,出现错误的话,错误信息保存到变量EX中,由Messagebox(消息盒子)弹出错误信息。最外一层代表检测单选框的值是否改变,如果方式改变则触发事件,事件内容是判断单选按钮radiobutton5是否被选中,若被选中则打开(我在窗体加载事件中将该值赋值true,意味着一旦开始程序,plc就会打开)。

(3)文本框显示plc数据

首先这类文本框的作用是用来显示数据的,因此在相关属性中设置ReadOnly的值为true,这样用户就不可以对该文本框进行编辑了。

private void timer2_Tick(object sender, EventArgs e)

        {

            float c = ((uint)myplc.Read("DB1.DBD6.0")).ConvertToFloat();

            textBox1.Text = c.ToString();

        }

这里又用到了一个定时器,因为读取数据是一个循环往复的过程。Myplc.read是从plc读取数据,括号里参数的含义首先DB1代表是从编号为1的数据块读取的,DBD表示双字,其他的如DBW表示字,DBB表示字节,DBX表示位,6.0表示偏移量,由于在PLC中我们的数据是real型,也就是浮点型,转化的时候先转化为无符号整形(uint),再通过ConvertToFloat()方法转化为浮点型,定义一个浮点型变量c去保存这个数据,最后通过tostring方法将c保存的浮点型数据转化为字符串赋值给文本框内容。此外此次用到的布尔型数据转化方法bool a = (bool)myplc.Read("DB1.DBX4.0"),整形数据转化方法int a = (ushort)myplc.Read("DB1.DBW0.0")等等

(4)文本框写入plc数据

在实际操作过程中免不了要由用户输入值来控制plc的数据,比如我要设定一个输出电流值,或者打开某个开关,这都涉及到对plc中的数据进行写入。

private void textBox7_TextChanged(object sender, EventArgs e)

        {

           if (textBox7.Text == 1.ToString())

           {

               myplc.Write("DB1.DBD10.0",1);

           }

            else if(textBox7.Text == 2.ToString())

           {

              myplc.Write("DB1.DBD10.0", 2);

           }

            else

           {

             textBox7.Text = "";

MessageBox.Show("输入错误!");

             

           }

        }

因为不是最终版本,此段代码仅表示一个例子,myplc.write方法的两个参数分别表示数据块的地址和想要写入数据块的值,当输入的值为1时,把plc中该地址的值置1,当输入的值为2时,把plc中该地址的值置2,其他情况弹出弹窗表示输入错误。

(5)指示灯

关于指示灯其实一开始我是想找个相关的控件的,网上似乎也是有这种控件的,但后来发现是收费的,那就大可不必了。

private void timer2_Tick(object sender, EventArgs e)

        {

            float c = ((uint)myplc.Read("DB1.DBD6.0")).ConvertToFloat();

            textBox1.Text = c.ToString();

            if(c>2000)

            {

                pictureBox1.Image = Image.FromFile("C:\\Users\\DELL\\source\\图片素材\\微信图片_20211019080709.jpg");

            }

        }

 那么采用的方式是刷新picturebox控件的图片,在创建picturebox控件时可以在属性-外观-Image中导入初始图片,(这个图片的格式是否有限制还不太清除,不过就目前来看.jpg和.png类型的图片都可以导入)然后当某个变量的值到达某个点后更换该控件显示的图片,从而达到指示灯的作用,当然是否美观与导入的图片是有关联的,在调用Image.Fromfile方法时应注意地址格式。

(6)打开子窗体

前面说过,窗体本质上也是一个控件,不过添加方式不太一样。项目——>添加窗体(windows窗体)——>选择窗体并设置好名称即可。创建完该窗体后就可以通过其他窗体里的控件事件来打开该窗体了。

private void button2_Click(object sender, EventArgs e)

        {

            new Form2().Show();

        }

这是通过一个按钮的点击事件打开窗体的方法。

(7) 连接数据库及数据存储进数据库

在开发前的准备中已经将数据库配置好了,首先打开数据库并连接。在命名空间中引入数据库相关库文件

using System.Data.SqlClient;

private void timer3_Tick(object sender, EventArgs e)

        {

            SqlConnection connection = new SqlConnection();//新建连接对象

            connection.ConnectionString = "Data Source=DESKTOP-F57AF5E;Initial Catalog=Record;Integrated Security=SSPI;";//给连接对象指定连接的参数(连接字符串)

            connection.Open();

            string a = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");

            float c = ((uint)myplc.Read("DB1.DBD6.0")).ConvertToFloat();

            //添加数据库

            string strInsert = "INSERT INTO [dbo].[Table_1]([时间] ,[第一路输出电流],[第二路输出电流],[电压])VALUES('" + a + "','" + c.ToString() + "','" + c.ToString() + "','" + c.ToString() + "')";

            SqlCommand comm = new SqlCommand(strInsert, connection);

            try

            {

                int rc = comm.ExecuteNonQuery();

            }

            catch(Exception ex)

            {

               // MessageBox.Show(ex.Message);

            }  

            connection.Close();

        }

在这里又用到了一个定时器,因为数据是需要实时进行存储的。

第一句建一个名字叫connection的连接对象,

第二句是这个对象的连接字符串属性为(1.连接服务器时的服务器名称,打开数据库连接可以看到,2.连接的数据库的名字,3.连接安全性的设置吧,这点可照抄),

第三句打开这个对象,也就是打开数据库。

之前说过,对数据库的所有操作都有相应的脚本语句,因此定义了一个字符串strInsert来保存即将输入给数据库的脚本语句,语句的书写格式如代码所示,注意其中字符串的拼接。

Sqlcommond 建一个负责连接脚本指令的对象comm,sqlcommond方法里的参数分别是你要发送的指令和你的连接对象。在执行该语句后就相当于你已经在数据库中输入了该指令。如上文中的指令就是向数据库中的这些列插入某某变量的值,Sql server的脚本指令非常多,使用的时候需要根据具体需求去查,这里就不做汇总了。

下面try中定义了一个整型变量去接受comm.ExecuteNonQuery方法的返回值,该变量返回的值是受影响的行数,当返回的值为-1,说明输入的指令错误,不是insert型或是delete型或是updata型,因此在脚本指令不是这三种类型开头的情况下无法使用该方法去判断受影响的行数。但是有别的方法可以判断,在下面会讲到。

(8)实时曲线

这一部分是整个开发过程中最困难的一环,相当于一个低配版示波器。我本来应该分成几个部分来讲,但是代码中这几个部分绑在一起,干脆一并讲了。

首先曲线的话VS里是有自带的chart图表控件的,但是听说该控件的实时性不是很好,于是从网上下载了ZedGraph控件,搜索后在官网就能够下载,该控件是一个开源免费且功能强大的图表控件,你几乎可以使用它绘制出任何你想绘制的图表,下载完成后点击视图——工具箱——选择项——.Net Framework 组件——浏览——找到ZedGraph.dll并点击“打开”按钮,然后ZedGraphControl出现在.Net Framework 组件列表中——选中ZedGraphControl,然后点击“确定”按钮,即可在工具箱中看见ZedGraphControl控件。在使用该控件时有个非常难受的地方就是控件里的属性和事件全是英文,包括解释也是英文,所以英文不好用起来确实有点折磨。

同样的,引用该控件需要在命名控件引入控件相关库文件。

using ZedGraph;

  private void timer5_Tick (object sender, EventArgs e)

        {

            //曲线

            GraphPane panel = zgc.GraphPane;//控件声明

            PointPairList listAmp = new PointPairList();//电压曲线声明

            PointPairList listFreq = new PointPairList();//电流曲线声明

            LineItem cureAmp = panel.AddCurve("电压", listAmp, Color.Red, SymbolType.None);//电压曲线规格赋值

            LineItem cureFreq = panel.AddCurve("电流", listFreq, Color.Blue, SymbolType.None);//电流曲线规格赋值

            cureAmp.IsY2Axis = true; // 关联cureAmp曲线到右边的纵坐标轴

            //cureFreq.

            panel.Title.Text = "电压电流实时曲线";//标题

            panel.XAxis.Title.Text = "时间/s";//横坐标

            panel.YAxis.Title.Text = "电流/A";//纵坐标

            panel.Y2Axis.Title.Text = "电压/V";//纵坐标2   

            panel.Y2Axis.IsVisible = true;//纵坐标2显示使能

            panel.Title.FontSpec.Family = "Arial";//标题字体样式

            panel.Title.FontSpec.Size = 26;//标题字体大小

            panel.Title.FontSpec.IsBold = true;//标题字体粗体显示

            zgc.PanModifierKeys = Keys.Shift;//想用鼠标拖动坐标轴的话得按住shift

            zgc.IsEnableHPan = true; // 鼠标拖动时允许横向移动

            zgc.IsEnableVPan = true; // 鼠标拖动时允许纵向移动

            zgc.IsShowContextMenu = true;//鼠标右键菜单

            zgc.GraphPane.XAxis.MajorTic.IsOpposite = false;//上x轴大刻度禁止显示

            zgc.GraphPane.XAxis.MinorTic.IsOpposite = false;//上x轴小刻度禁止显示

            zgc.GraphPane.XAxis.MajorGrid.IsVisible = true; // 显示大刻度对应的网格

            zgc.GraphPane.XAxis.MinorGrid.IsVisible = true; // 显示小刻度对应的网格

            panel.XAxis.MajorGrid.DashOn = 5f;  // 网格为虚线,这句话是设置虚线中的实线部分长度

            panel.XAxis.MajorGrid.DashOff = 2f; // 设置虚线中的空白部分长度

            panel.XAxis.MajorGrid.PenWidth = 1.5f;   // 设置虚线线宽

            zgc.IsEnableVZoom = true// 纵轴允许缩放

            zgc.IsEnableHZoom = true;   // 横轴允许缩放

            zgc.ZoomStepFraction = 0.03; // 缩放速度

            zgc.IsShowCursorValues = true;

            panel.YAxis.Scale.BaseTic = 0;  // 纵坐标轴的起点从零开始

            panel.Y2Axis.Scale.BaseTic = 0; // 纵2坐标轴的起点从零开始

            panel.YAxis.Scale.Min = 0;//纵坐标最小值为0

            panel.YAxis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴的最大值

            panel.Y2Axis.Scale.Min = 0;///纵坐标2最小值为0

            panel.Y2Axis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴2的最大值

            panel.XAxis.Scale.MinAuto = false; // 根据数据自动匹配横坐标轴的最小值

            panel.XAxis.Scale.MaxAuto = true; // 根据数据自动匹配横坐标轴的最大值

            panel.XAxis.Scale.IsVisible = true; // 允许显示x轴刻度值

            panel.XAxis.Scale.MajorStepAuto = true;//大刻度自动匹配

            panel.XAxis.Scale.MinorStepAuto = true;//小刻度自动匹配

            panel.Fill = new Fill(Color.Yellow, Color.Pink, 45.0f); // 从左上角45.0°开始,从黄色过渡到粉色

            zgc.IsShowPointValues = true;//鼠标移动到某个点时显示该点坐标

            zgc.IsZoomOnMouseCenter = true;//以鼠标为中心进行放大

            SqlConnection connection = new SqlConnection();//新建连接对象

            connection.ConnectionString = "Data Source=DESKTOP-F57AF5E;Initial Catalog=Record;Integrated Security=SSPI;";//给连接对象指定连接的参数(连接字符串)

            connection.Open();

            string strSQL = "select top 600 * from Table_1 order by 时间 desc";//选择数据表数据的行数

            SqlCommand comm = new SqlCommand(strSQL, connection);

            SqlDataAdapter da = new SqlDataAdapter(strSQL, connection);

            DataSet ds = new DataSet();

            da.Fill(ds);

            dataGridView1.DataSource = ds.Tables[0];

            Double[] szy = new Double[dataGridView1.RowCount];//Y轴的数据数组

            string[] dates0 = new string[dataGridView1.RowCount];//制作string类型数组,这个数组存的是数据库最近保存的数据的时间信息

            for (int i =0; i <600; i++)//i表示行标

            {

                listAmp.Add(i, Convert.ToDouble(dataGridView1[3, 599-i].Value.ToString()));

                listFreq.Add(i, Convert.ToDouble(dataGridView1[3, 599 - i].Value.ToString())+1000);

                szy[i] = Convert.ToDouble(dataGridView1[3, 599-i].Value.ToString());

                dates0[i] = dataGridView1[0, 599-i].Value == null ? "" : dataGridView1[0,599-i].Value.ToString();

            }

            panel.XAxis.Type = AxisType.Text;//x轴选择为日期格式

            panel.XAxis.Scale.TextLabels = dates0;//数据显示格式为分秒  

            zgc.AxisChange(); // 因为点增加,需要自动修改横轴最大值(前提是MaxAuto为true),所以需要更新坐标

            Refresh(); // 把变化后的点集显示在图里

            connection.Close();

            panel.CurveList.Clear();//清除这次的曲线

        }

因为是实时曲线,因此整个函数也是封装在一个定时器里面的,每隔一秒刷新一次,注释基本都写了,下面讲一下注释没有提到的内容。首先是数据表控件DataGridView,上文已经实现了向数据库中写入数据了,那么从数据库中读取数据就需要用到数据表了,在连接数据库后向数据库写指令"select top 600 * from Table_1 order by 时间 desc",那么这句脚本指令是什么意思呢,它表示获取数据表中最近的600条数据,如果程序一直在运行,那么最近的600条数据其实就是最近600秒的数据,DataSet方法调用的是缓冲区数据,SqlDataAdapter类与SqlCommand类似,不过它针对的是缓冲区,因此算是后者的增强版,这里没有把SqlCommand屏蔽掉也没有影响。DataAdapter将数据从数据表拿到手保存到da中,ds用来表示缓冲区数据,然后da.Fill(ds)表示把da里的所有数据给到缓冲区,然后再由数据表读取出缓冲区数据。到现在我们就可以得到一个只显示最近600条数据的表格了,但是难点是如何将这写数据传达给曲线控件。其实想通了并不算复杂,首先我们是在一个定时器里,因此只需要将某一时刻的坐标值包括曲线确定下来,然后在末尾去加一个坐标轴更新和曲线清除,那么每次计时时都会重新进行绘制当下时刻的曲线,从而实现动态刷新,那么问题就转变成怎样将一个静态的数据导入到曲线控件中。ZedGraph控件是按照给的点然后连线完成曲线图的。我们定义两个数组去保存该时刻的变量,用一个Double型数组保存某一时刻y轴的点,用一个string类型的数组去保存同一时刻的时间数据,Rowcount代表行数,有多少行这个数组就存多少个数据。用一个for循环来将数组中的值赋给listXX.Add,我这里有两条曲线,因此将第二条曲线的y值+1000以区分,同时x轴的数据是不能直接赋值的,因为他是个时间数据,是个字符串,所以直接用i代替,然后在for循环下面一句对x轴的时间进行表现,但因为我时间数据过于详细,所以显示的点也是比较有限,dataGridview[,]数组里的两个数据分别是第几列和第几行的意思,599-i的原因是数据表中表头数据是最新时刻的数据,如果使用i那么x轴的时间就反过来显示了,最后因为是实时曲线,所以将该数据表隐藏了,在数据表控件属性-Visible改为false即可。

(8)选择起始时间和结束时间获取数据表信息和曲线

首先通过下拉框的形式由用户来确认可供选择的时间,这里是在窗体二加载过程中对下拉框内容的赋值过程。

private void Form2_Load(object sender, EventArgs e)

        {

            int i,j,k,l,m;

            for (i=2021;i<2041;i++)//

            {

                comboBox1.Items.Add(i.ToString());

                comboBox7.Items.Add(i.ToString());

            }

            for (j = 1; j < 10; j++)//

            {

                comboBox2.Items.Add('0'+j.ToString());

                comboBox8.Items.Add('0'+j.ToString());

            }

            for (j = 10; j < 13; j++)

            {

                comboBox2.Items.Add(j.ToString());

                comboBox8.Items.Add(j.ToString());

            }

            for (k = 1; k < 10; k++)//

            {

                comboBox3.Items.Add('0'+k.ToString());

                comboBox9.Items.Add('0'+k.ToString());

            }

            for(k=10;k<32;k++)

            {

                comboBox3.Items.Add(k.ToString());

                comboBox9.Items.Add(k.ToString());

            }

            for (l = 1; l < 10; l++)//

            {

                comboBox4.Items.Add('0'+l.ToString());

                comboBox10.Items.Add('0'+l.ToString());

            }

            for (l = 10; l < 25; l++)//

            {

                comboBox4.Items.Add(l.ToString());

                comboBox10.Items.Add(l.ToString());

            }

            for (m = 0; m < 10; m++)//分秒

            {

                comboBox5.Items.Add('0'+m.ToString());

                comboBox6.Items.Add('0'+m.ToString());

                comboBox11.Items.Add('0'+m.ToString());

                comboBox12.Items.Add('0'+m.ToString());

            }

            for (m = 10; m < 60; m++)//分秒

            {

                comboBox5.Items.Add(m.ToString());

                comboBox6.Items.Add(m.ToString());

                comboBox11.Items.Add(m.ToString());

                comboBox12.Items.Add(m.ToString());

            }

        }

下面就是由用户选择数据了,基本上是一些对用户输入数据是否正确的逻辑判断,首先判断是否是否有哪个框没选,然后判断两个时间的先后顺序是否正确,如果错误是哪个数据发生了错误,剩下的操作和实时曲线几乎差不多,有一点需要的注意到的,当用户输入的两个时间点的数据量非常庞大或者两个时间点间数据量非常小,那么数据表中的行数我们如何得知,因为这是由用户的输入来决定的,上面说过,comm.ExecuteNonQuery方法只能用来获取特定脚本输入的返回行,而现在对数据库的指令内容是获取并返回两个时间节点之间的所有数据,开头的脚本指令是Select,因此只能另谋他路。从数据库中读取多少行行不通,但是可以从数据表中想办法,在数据表被写入之前所有的数据都是存在于缓冲区的,这个时候我们可以直接对缓冲区的行数进行读取,定义一个整形变量count去保存dt.row.count就行,然后下面的for循环中i小于的值就是count。代码如下:

private void button1_Click(object sender, EventArgs e)

        {

            if(comboBox1.Text==""||comboBox2.Text==""||comboBox3.Text==""||comboBox4.Text==""||comboBox5.Text==""||comboBox6.Text==""||comboBox7.Text==""||comboBox8.Text==""||comboBox9.Text==""||comboBox10.Text==""||comboBox11.Text==""||comboBox12.Text=="")

            {

                MessageBox.Show("请将选取时间段设定完整!");

            }

            else

            {   

                if(Convert.ToInt32(comboBox1.Text)> Convert.ToInt32(comboBox7.Text))

                {

                    MessageBox.Show("年份顺序错误!请重新确立!");

                }

                else if(Convert.ToInt32(comboBox1.Text) < Convert.ToInt32(comboBox7.Text))

                {

                    SqlConnection connection = new SqlConnection();//新建连接对象

                    connection.ConnectionString = "Data Source=DESKTOP-F57AF5E;Initial Catalog=Record;Integrated Security=SSPI;";//给连接对象指定连接的参数(连接字符串)

                    connection.Open();

                    string strSQL = "select * from Table_1 where 时间>='" + comboBox1.Text + "-" + comboBox2.Text + "-" + comboBox3.Text + " " + comboBox4.Text + ":" + comboBox5.Text + ":" + comboBox6.Text + "' and 时间<='" + comboBox7.Text + "-" + comboBox8.Text + "-" + comboBox9.Text + " " + comboBox10.Text + ":" + comboBox11.Text + ":" + comboBox12.Text + "'";

                    SqlCommand comm = new SqlCommand(strSQL, connection);

                    SqlDataAdapter da = new SqlDataAdapter(strSQL, connection);

                    DataSet ds = new DataSet();

                    da.Fill(ds, "Table_1");

                    dataGridView1.DataSource = ds.Tables["Table_1"];

                    SqlDataAdapter dant = new SqlDataAdapter(comm);

                    DataTable dt = new DataTable();

                    dant.Fill(dt);

                    int count = dt.Rows.Count;

                    //曲线

                    GraphPane panel = zgc.GraphPane;//控件声明

                    PointPairList listAmp = new PointPairList();//电压曲线声明

                    PointPairList listFreq = new PointPairList();//电流曲线声明

                    LineItem cureAmp = panel.AddCurve("电压", listAmp, Color.Red, SymbolType.None);//电压曲线规格赋值

                    LineItem cureFreq = panel.AddCurve("电流", listFreq, Color.Blue, SymbolType.None);//电流曲线规格赋值

                    cureAmp.IsY2Axis = true; // 关联cureAmp曲线到右边的纵坐标轴

                                             //cureFreq.

                    panel.Title.Text = "电压电流实时曲线";//标题

                    panel.XAxis.Title.Text = "时间/s";//横坐标

                    panel.YAxis.Title.Text = "电流/A";//纵坐标

                    panel.Y2Axis.Title.Text = "电压/V";//纵坐标2   

                    panel.Y2Axis.IsVisible = true;//纵坐标2显示使能

                    panel.Title.FontSpec.Family = "Arial";//标题字体样式

                    panel.Title.FontSpec.Size = 26;//标题字体大小

                    panel.Title.FontSpec.IsBold = true;//标题字体粗体显示

                    zgc.PanModifierKeys = Keys.Shift;//想用鼠标拖动坐标轴的话得按住shift

                    zgc.IsEnableHPan = true; // 鼠标拖动时允许横向移动

                    zgc.IsEnableVPan = true; // 鼠标拖动时允许纵向移动

                    zgc.IsShowContextMenu = true;//鼠标右键菜单

                    zgc.GraphPane.XAxis.MajorTic.IsOpposite = false;//上x轴大刻度禁止显示

                    zgc.GraphPane.XAxis.MinorTic.IsOpposite = false;//上x轴小刻度禁止显示

                    zgc.GraphPane.XAxis.MajorGrid.IsVisible = true; // 显示大刻度对应的网格

                    zgc.GraphPane.XAxis.MinorGrid.IsVisible = true; // 显示小刻度对应的网格

                    panel.XAxis.MajorGrid.DashOn = 5f;  // 网格为虚线,这句话是设置虚线中的实线部分长度

                    panel.XAxis.MajorGrid.DashOff = 2f; // 设置虚线中的空白部分长度

                    panel.XAxis.MajorGrid.PenWidth = 1.5f;  // 设置虚线线宽

                    zgc.IsEnableVZoom = true;  // 纵轴允许缩放

                    zgc.IsEnableHZoom = true;   // 横轴允许缩放

                    zgc.ZoomStepFraction = 0.03; // 缩放速度

                    zgc.IsShowCursorValues = true;

                    panel.YAxis.Scale.BaseTic = 0;  // 纵坐标轴的起点从零开始

                    panel.Y2Axis.Scale.BaseTic = 0; // 纵2坐标轴的起点从零开始

                    panel.YAxis.Scale.Min = 0;//纵坐标最小值为0

                    panel.YAxis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴的最大值

                    panel.Y2Axis.Scale.Min = 0;///纵坐标2最小值为0

                    panel.Y2Axis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴2的最大值

                    panel.XAxis.Scale.MinAuto = false; // 根据数据自动匹配横坐标轴的最小值

                    panel.XAxis.Scale.MaxAuto = true; // 根据数据自动匹配横坐标轴的最大值

                    panel.XAxis.Scale.IsVisible = true; // 允许显示x轴刻度值

                    panel.XAxis.Scale.MajorStepAuto = true;//大刻度自动匹配

                    panel.XAxis.Scale.MinorStepAuto = true;//小刻度自动匹配

                    panel.Fill = new Fill(Color.Yellow, Color.Pink, 45.0f); // 从左上角45.0°开始,从黄色过渡到粉色

                    zgc.IsShowPointValues = true;//鼠标移动到某个点时显示该点坐标

                    zgc.IsZoomOnMouseCenter = true;//以鼠标为中心进行放大

                    Double[] szy = new Double[dataGridView1.RowCount];//Y轴的数据数组

                    string[] dates0 = new string[dataGridView1.RowCount];//制作string类型数组,这个数组存的是数据库最近保存的数据的时间信息

                    for (int i = 0; i < count; i++)//i表示行标

                    {

                        listAmp.Add(i, Convert.ToDouble(dataGridView1[3,i].Value.ToString()));

                        listFreq.Add(i, Convert.ToDouble(dataGridView1[3,i].Value.ToString()) + 1000);

                        szy[i] = Convert.ToDouble(dataGridView1[3,i].Value.ToString());

                        dates0[i] = dataGridView1[0,i].Value == null ? "" : dataGridView1[0,i].Value.ToString();

                    }

                    panel.XAxis.Type = AxisType.Text;//x轴选择为日期格式

                    panel.XAxis.Scale.TextLabels = dates0;//数据显示格式为分秒  

                    zgc.AxisChange(); // 因为点增加,需要自动修改横轴最大值(前提是MaxAuto为true),所以需要更新坐标

                    Refresh(); // 把变化后的点集显示在图里

                    connection.Close();

                }

                else

                {

                    if(Convert.ToInt32(comboBox2.Text)>Convert.ToInt32(comboBox8.Text))

                    {

                        MessageBox.Show("月份顺序错误!请重新确立!");

                    }

                    else if (Convert.ToInt32(comboBox2.Text) < Convert.ToInt32(comboBox8.Text))

                    {

                        SqlConnection connection = new SqlConnection();//新建连接对象

                        connection.ConnectionString = "Data Source=DESKTOP-F57AF5E;Initial Catalog=Record;Integrated Security=SSPI;";//给连接对象指定连接的参数(连接字符串)

                        connection.Open();

                        string strSQL = "select * from Table_1 where 时间>='" + comboBox1.Text + "-" + comboBox2.Text + "-" + comboBox3.Text + " " + comboBox4.Text + ":" + comboBox5.Text + ":" + comboBox6.Text + "' and 时间<='" + comboBox7.Text + "-" + comboBox8.Text + "-" + comboBox9.Text + " " + comboBox10.Text + ":" + comboBox11.Text + ":" + comboBox12.Text + "'";

                        SqlCommand comm = new SqlCommand(strSQL, connection);

                        //new Form4().Show();

                        SqlDataAdapter da = new SqlDataAdapter(strSQL, connection);

                        DataSet ds = new DataSet();

                        da.Fill(ds, "Table_1");

                        dataGridView1.DataSource = ds.Tables["Table_1"];

                        SqlDataAdapter dant = new SqlDataAdapter(comm);

                        DataTable dt = new DataTable();

                        dant.Fill(dt);

                        int count = dt.Rows.Count;

                        //曲线

                        GraphPane panel = zgc.GraphPane;//控件声明

                        PointPairList listAmp = new PointPairList();//电压曲线声明

                        PointPairList listFreq = new PointPairList();//电流曲线声明

                        LineItem cureAmp = panel.AddCurve("电压", listAmp, Color.Red, SymbolType.None);//电压曲线规格赋值

                        LineItem cureFreq = panel.AddCurve("电流", listFreq, Color.Blue, SymbolType.None);//电流曲线规格赋值

                        cureAmp.IsY2Axis = true; // 关联cureAmp曲线到右边的纵坐标轴

                                                 //cureFreq.

                        panel.Title.Text = "电压电流实时曲线";//标题

                        panel.XAxis.Title.Text = "时间/s";//横坐标

                        panel.YAxis.Title.Text = "电流/A";//纵坐标

                        panel.Y2Axis.Title.Text = "电压/V";//纵坐标2   

                        panel.Y2Axis.IsVisible = true;//纵坐标2显示使能

                        panel.Title.FontSpec.Family = "Arial";//标题字体样式

                        panel.Title.FontSpec.Size = 26;//标题字体大小

                        panel.Title.FontSpec.IsBold = true;//标题字体粗体显示

                        zgc.PanModifierKeys = Keys.Shift;//想用鼠标拖动坐标轴的话得按住shift

                        zgc.IsEnableHPan = true; // 鼠标拖动时允许横向移动

                        zgc.IsEnableVPan = true; // 鼠标拖动时允许纵向移动

                        zgc.IsShowContextMenu = true;//鼠标右键菜单

                        zgc.GraphPane.XAxis.MajorTic.IsOpposite = false;//上x轴大刻度禁止显示

                        zgc.GraphPane.XAxis.MinorTic.IsOpposite = false;//上x轴小刻度禁止显示

                        zgc.GraphPane.XAxis.MajorGrid.IsVisible = true; // 显示大刻度对应的网格

                        zgc.GraphPane.XAxis.MinorGrid.IsVisible = true; // 显示小刻度对应的网格

                        panel.XAxis.MajorGrid.DashOn = 5f;  // 网格为虚线,这句话是设置虚线中的实线部分长度

                        panel.XAxis.MajorGrid.DashOff = 2f; // 设置虚线中的空白部分长度

                        panel.XAxis.MajorGrid.PenWidth = 1.5f;  // 设置虚线线宽

                        zgc.IsEnableVZoom = true;  // 纵轴允许缩放

                        zgc.IsEnableHZoom = true;   // 横轴允许缩放

                        zgc.ZoomStepFraction = 0.03; // 缩放速度

                        zgc.IsShowCursorValues = true;

                        panel.YAxis.Scale.BaseTic = 0;  // 纵坐标轴的起点从零开始

                        panel.Y2Axis.Scale.BaseTic = 0; // 纵2坐标轴的起点从零开始

                        panel.YAxis.Scale.Min = 0;//纵坐标最小值为0

                        panel.YAxis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴的最大值

                        panel.Y2Axis.Scale.Min = 0;///纵坐标2最小值为0

                        panel.Y2Axis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴2的最大值

                        panel.XAxis.Scale.MinAuto = false; // 根据数据自动匹配横坐标轴的最小值

                        panel.XAxis.Scale.MaxAuto = true; // 根据数据自动匹配横坐标轴的最大值

                        panel.XAxis.Scale.IsVisible = true; // 允许显示x轴刻度值

                        panel.XAxis.Scale.MajorStepAuto = true;//大刻度自动匹配

                        panel.XAxis.Scale.MinorStepAuto = true;//小刻度自动匹配

                        panel.Fill = new Fill(Color.Yellow, Color.Pink, 45.0f); // 从左上角45.0°开始,从黄色过渡到粉色

                        zgc.IsShowPointValues = true;//鼠标移动到某个点时显示该点坐标

                        zgc.IsZoomOnMouseCenter = true;//以鼠标为中心进行放大

                        Double[] szy = new Double[dataGridView1.RowCount];//Y轴的数据数组

                        string[] dates0 = new string[dataGridView1.RowCount];//制作string类型数组,这个数组存的是数据库最近保存的数据的时间信息

                        for (int i = 0; i < count; i++)//i表示行标

                        {

                            listAmp.Add(i, Convert.ToDouble(dataGridView1[3,i].Value.ToString()));

                            listFreq.Add(i, Convert.ToDouble(dataGridView1[3,i].Value.ToString()) + 1000);

                            szy[i] = Convert.ToDouble(dataGridView1[3,i].Value.ToString());

                            dates0[i] = dataGridView1[0,i].Value == null ? "" : dataGridView1[0,i].Value.ToString();

                        }

                        panel.XAxis.Type = AxisType.Text;//x轴选择为日期格式

                        panel.XAxis.Scale.TextLabels = dates0;//数据显示格式为分秒  

                        zgc.AxisChange(); // 因为点增加,需要自动修改横轴最大值(前提是MaxAuto为true),所以需要更新坐标

                        Refresh(); // 把变化后的点集显示在图里

                        connection.Close();

                    }

                    else

                    {

                        if(Convert.ToInt32(comboBox3.Text)>Convert.ToInt32(comboBox9.Text))

                        {

                            MessageBox.Show("日期时间顺序错误!请重新确立!");

                        }

                        else if (Convert.ToInt32(comboBox3.Text) < Convert.ToInt32(comboBox9.Text))

                        {

                            SqlConnection connection = new SqlConnection();//新建连接对象

                            connection.ConnectionString = "Data Source=DESKTOP-F57AF5E;Initial Catalog=Record;Integrated Security=SSPI;";//给连接对象指定连接的参数(连接字符串)

                            connection.Open();

                            string strSQL = "select * from Table_1 where 时间>='" + comboBox1.Text + "-" + comboBox2.Text + "-" + comboBox3.Text + " " + comboBox4.Text + ":" + comboBox5.Text + ":" + comboBox6.Text + "' and 时间<='" + comboBox7.Text + "-" + comboBox8.Text + "-" + comboBox9.Text + " " + comboBox10.Text + ":" + comboBox11.Text + ":" + comboBox12.Text + "'";

                            SqlCommand comm = new SqlCommand(strSQL, connection);

                            //new Form4().Show();

                            SqlDataAdapter da = new SqlDataAdapter(strSQL, connection);

                            DataSet ds = new DataSet();

                            da.Fill(ds, "Table_1");

                            dataGridView1.DataSource = ds.Tables["Table_1"];

                            SqlDataAdapter dant = new SqlDataAdapter(comm);

                            DataTable dt = new DataTable();

                            dant.Fill(dt);

                            int count = dt.Rows.Count;

                            //曲线

                            GraphPane panel = zgc.GraphPane;//控件声明

                            PointPairList listAmp = new PointPairList();//电压曲线声明

                            PointPairList listFreq = new PointPairList();//电流曲线声明

                            LineItem cureAmp = panel.AddCurve("电压", listAmp, Color.Red, SymbolType.None);//电压曲线规格赋值

                            LineItem cureFreq = panel.AddCurve("电流", listFreq, Color.Blue, SymbolType.None);//电流曲线规格赋值

                            cureAmp.IsY2Axis = true; // 关联cureAmp曲线到右边的纵坐标轴

                                                     //cureFreq.

                            panel.Title.Text = "电压电流实时曲线";//标题

                            panel.XAxis.Title.Text = "时间/s";//横坐标

                            panel.YAxis.Title.Text = "电流/A";//纵坐标

                            panel.Y2Axis.Title.Text = "电压/V";//纵坐标2   

                            panel.Y2Axis.IsVisible = true;//纵坐标2显示使能

                            panel.Title.FontSpec.Family = "Arial";//标题字体样式

                            panel.Title.FontSpec.Size = 26;//标题字体大小

                            panel.Title.FontSpec.IsBold = true;//标题字体粗体显示

                            zgc.PanModifierKeys = Keys.Shift;//想用鼠标拖动坐标轴的话得按住shift

                            zgc.IsEnableHPan = true; // 鼠标拖动时允许横向移动

                            zgc.IsEnableVPan = true; // 鼠标拖动时允许纵向移动

                            zgc.IsShowContextMenu = true;//鼠标右键菜单

                            zgc.GraphPane.XAxis.MajorTic.IsOpposite = false;//上x轴大刻度禁止显示

                            zgc.GraphPane.XAxis.MinorTic.IsOpposite = false;//上x轴小刻度禁止显示

                            zgc.GraphPane.XAxis.MajorGrid.IsVisible = true; // 显示大刻度对应的网格

                            zgc.GraphPane.XAxis.MinorGrid.IsVisible = true; // 显示小刻度对应的网格

                            panel.XAxis.MajorGrid.DashOn = 5f;  // 网格为虚线,这句话是设置虚线中的实线部分长度

                            panel.XAxis.MajorGrid.DashOff = 2f; // 设置虚线中的空白部分长度

                            panel.XAxis.MajorGrid.PenWidth = 1.5f;  // 设置虚线线宽

                            zgc.IsEnableVZoom = true;  // 纵轴允许缩放

                            zgc.IsEnableHZoom = true;   // 横轴允许缩放

                            zgc.ZoomStepFraction = 0.03; // 缩放速度

                            zgc.IsShowCursorValues = true;

                            panel.YAxis.Scale.BaseTic = 0;  // 纵坐标轴的起点从零开始

                            panel.Y2Axis.Scale.BaseTic = 0; // 纵2坐标轴的起点从零开始

                            panel.YAxis.Scale.Min = 0;//纵坐标最小值为0

                            panel.YAxis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴的最大值

                            panel.Y2Axis.Scale.Min = 0;///纵坐标2最小值为0

                            panel.Y2Axis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴2的最大值

                            panel.XAxis.Scale.MinAuto = false; // 根据数据自动匹配横坐标轴的最小值

                            panel.XAxis.Scale.MaxAuto = true; // 根据数据自动匹配横坐标轴的最大值

                            panel.XAxis.Scale.IsVisible = true; // 允许显示x轴刻度值

                            panel.XAxis.Scale.MajorStepAuto = true;//大刻度自动匹配

                            panel.XAxis.Scale.MinorStepAuto = true;//小刻度自动匹配

                            panel.Fill = new Fill(Color.Yellow, Color.Pink, 45.0f); // 从左上角45.0°开始,从黄色过渡到粉色

                            zgc.IsShowPointValues = true;//鼠标移动到某个点时显示该点坐标

                            zgc.IsZoomOnMouseCenter = true;//以鼠标为中心进行放大

                            Double[] szy = new Double[dataGridView1.RowCount];//Y轴的数据数组

                            string[] dates0 = new string[dataGridView1.RowCount];//制作string类型数组,这个数组存的是数据库最近保存的数据的时间信息

                            for (int i = 0; i < count; i++)//i表示行标

                            {

                                listAmp.Add(i, Convert.ToDouble(dataGridView1[3,i].Value.ToString()));

                                listFreq.Add(i, Convert.ToDouble(dataGridView1[3,i].Value.ToString()) + 1000);

                                szy[i] = Convert.ToDouble(dataGridView1[3,i].Value.ToString());

                                dates0[i] = dataGridView1[0,i].Value == null ? "" : dataGridView1[0,i].Value.ToString();

                            }

                            panel.XAxis.Type = AxisType.Text;//x轴选择为日期格式

                            panel.XAxis.Scale.TextLabels = dates0;//数据显示格式为分秒  

                            zgc.AxisChange(); // 因为点增加,需要自动修改横轴最大值(前提是MaxAuto为true),所以需要更新坐标

                            Refresh(); // 把变化后的点集显示在图里

                            connection.Close();

                        }

                        else

                        {

                            if(Convert.ToInt32(comboBox4.Text)>Convert.ToInt32(comboBox10.Text))

                            {

                                MessageBox.Show("小时顺序错误!请重新确立!");

                            }

                            else if (Convert.ToInt32(comboBox4.Text) < Convert.ToInt32(comboBox10.Text))

                            {

                                SqlConnection connection = new SqlConnection();//新建连接对象

                                connection.ConnectionString = "Data Source=DESKTOP-F57AF5E;Initial Catalog=Record;Integrated Security=SSPI;";//给连接对象指定连接的参数(连接字符串)

                                connection.Open();

                                string strSQL = "select * from Table_1 where 时间>='" + comboBox1.Text + "-" + comboBox2.Text + "-" + comboBox3.Text + " " + comboBox4.Text + ":" + comboBox5.Text + ":" + comboBox6.Text + "' and 时间<='" + comboBox7.Text + "-" + comboBox8.Text + "-" + comboBox9.Text + " " + comboBox10.Text + ":" + comboBox11.Text + ":" + comboBox12.Text + "'";

                                SqlCommand comm = new SqlCommand(strSQL, connection);

                                //new Form4().Show();

                                SqlDataAdapter da = new SqlDataAdapter(strSQL, connection);

                                DataSet ds = new DataSet();

                                da.Fill(ds, "Table_1");

                                dataGridView1.DataSource = ds.Tables["Table_1"];

                                SqlDataAdapter dant = new SqlDataAdapter(comm);

                                DataTable dt = new DataTable();

                                dant.Fill(dt);

                                int count = dt.Rows.Count;

                                //曲线

                                GraphPane panel = zgc.GraphPane;//控件声明

                                PointPairList listAmp = new PointPairList();//电压曲线声明

                                PointPairList listFreq = new PointPairList();//电流曲线声明

                                LineItem cureAmp = panel.AddCurve("电压", listAmp, Color.Red, SymbolType.None);//电压曲线规格赋值

                                LineItem cureFreq = panel.AddCurve("电流", listFreq, Color.Blue, SymbolType.None);//电流曲线规格赋值

                                cureAmp.IsY2Axis = true; // 关联cureAmp曲线到右边的纵坐标轴

                                                         //cureFreq.

                                panel.Title.Text = "电压电流实时曲线";//标题

                                panel.XAxis.Title.Text = "时间/s";//横坐标

                                panel.YAxis.Title.Text = "电流/A";//纵坐标

                                panel.Y2Axis.Title.Text = "电压/V";//纵坐标2   

                                panel.Y2Axis.IsVisible = true;//纵坐标2显示使能

                                panel.Title.FontSpec.Family = "Arial";//标题字体样式

                                panel.Title.FontSpec.Size = 26;//标题字体大小

                                panel.Title.FontSpec.IsBold = true;//标题字体粗体显示

                                zgc.PanModifierKeys = Keys.Shift;//想用鼠标拖动坐标轴的话得按住shift

                                zgc.IsEnableHPan = true; // 鼠标拖动时允许横向移动

                                zgc.IsEnableVPan = true; // 鼠标拖动时允许纵向移动

                                zgc.IsShowContextMenu = true;//鼠标右键菜单

                                zgc.GraphPane.XAxis.MajorTic.IsOpposite = false;//上x轴大刻度禁止显示

                                zgc.GraphPane.XAxis.MinorTic.IsOpposite = false;//上x轴小刻度禁止显示

                                zgc.GraphPane.XAxis.MajorGrid.IsVisible = true; // 显示大刻度对应的网格

                                zgc.GraphPane.XAxis.MinorGrid.IsVisible = true; // 显示小刻度对应的网格

                                panel.XAxis.MajorGrid.DashOn = 5f;  // 网格为虚线,这句话是设置虚线中的实线部分长度

                                panel.XAxis.MajorGrid.DashOff = 2f; // 设置虚线中的空白部分长度

                                panel.XAxis.MajorGrid.PenWidth = 1.5f;  // 设置虚线线宽

                                zgc.IsEnableVZoom = true;  // 纵轴允许缩放

                                zgc.IsEnableHZoom = true;   // 横轴允许缩放

                                zgc.ZoomStepFraction = 0.03; // 缩放速度

                                zgc.IsShowCursorValues = true;

                                panel.YAxis.Scale.BaseTic = 0;  // 纵坐标轴的起点从零开始

                                panel.Y2Axis.Scale.BaseTic = 0; // 纵2坐标轴的起点从零开始

                                panel.YAxis.Scale.Min = 0;//纵坐标最小值为0

                                panel.YAxis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴的最大值

                                panel.Y2Axis.Scale.Min = 0;///纵坐标2最小值为0

                                panel.Y2Axis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴2的最大值

                                panel.XAxis.Scale.MinAuto = false; // 根据数据自动匹配横坐标轴的最小值

                                panel.XAxis.Scale.MaxAuto = true; // 根据数据自动匹配横坐标轴的最大值

                                panel.XAxis.Scale.IsVisible = true; // 允许显示x轴刻度值

                                panel.XAxis.Scale.MajorStepAuto = true;//大刻度自动匹配

                                panel.XAxis.Scale.MinorStepAuto = true;//小刻度自动匹配

                                panel.Fill = new Fill(Color.Yellow, Color.Pink, 45.0f); // 从左上角45.0°开始,从黄色过渡到粉色

                                zgc.IsShowPointValues = true;//鼠标移动到某个点时显示该点坐标

                                zgc.IsZoomOnMouseCenter = true;//以鼠标为中心进行放大

                                Double[] szy = new Double[dataGridView1.RowCount];//Y轴的数据数组

                                string[] dates0 = new string[dataGridView1.RowCount];//制作string类型数组,这个数组存的是数据库最近保存的数据的时间信息

                                for (int i = 0; i < count; i++)//i表示行标

                                {

                                    listAmp.Add(i, Convert.ToDouble(dataGridView1[3,i].Value.ToString()));

                                    listFreq.Add(i, Convert.ToDouble(dataGridView1[3,i].Value.ToString()) + 1000);

                                    szy[i] = Convert.ToDouble(dataGridView1[3,i].Value.ToString());

                                    dates0[i] = dataGridView1[0,i].Value == null ? "" : dataGridView1[0,i].Value.ToString();

                                }

                                panel.XAxis.Type = AxisType.Text;//x轴选择为日期格式

                                panel.XAxis.Scale.TextLabels = dates0;//数据显示格式为分秒  

                                zgc.AxisChange(); // 因为点增加,需要自动修改横轴最大值(前提是MaxAuto为true),所以需要更新坐标

                                Refresh(); // 把变化后的点集显示在图里

                                connection.Close();

                            }

                            else

                            {

                                if (Convert.ToInt32(comboBox5.Text) > Convert.ToInt32(comboBox11.Text))

                                {

                                    MessageBox.Show("分钟顺序错误!请重新确立!");

                                }

                                else if (Convert.ToInt32(comboBox5.Text) < Convert.ToInt32(comboBox11.Text))

                                {

                                    SqlConnection connection = new SqlConnection();//新建连接对象

                                    connection.ConnectionString = "Data Source=DESKTOP-F57AF5E;Initial Catalog=Record;Integrated Security=SSPI;";//给连接对象指定连接的参数(连接字符串)

                                    connection.Open();

                                    string strSQL = "select * from Table_1 where 时间>='" + comboBox1.Text + "-" + comboBox2.Text + "-" + comboBox3.Text + " " + comboBox4.Text + ":" + comboBox5.Text + ":" + comboBox6.Text + "' and 时间<='" + comboBox7.Text + "-" + comboBox8.Text + "-" + comboBox9.Text + " " + comboBox10.Text + ":" + comboBox11.Text + ":" + comboBox12.Text + "'";

                                    SqlCommand comm = new SqlCommand(strSQL, connection);

                                    //new Form4().Show();

                                    SqlDataAdapter da = new SqlDataAdapter(strSQL, connection);

                                    DataSet ds = new DataSet();

                                    da.Fill(ds, "Table_1");

                                    dataGridView1.DataSource = ds.Tables["Table_1"];

                                    SqlDataAdapter dant = new SqlDataAdapter(comm);

                                    DataTable dt = new DataTable();

                                    dant.Fill(dt);

                                    int count = dt.Rows.Count;

                                    //曲线

                                    GraphPane panel = zgc.GraphPane;//控件声明

                                    PointPairList listAmp = new PointPairList();//电压曲线声明

                                    PointPairList listFreq = new PointPairList();//电流曲线声明

                                    LineItem cureAmp = panel.AddCurve("电压", listAmp, Color.Red, SymbolType.None);//电压曲线规格赋值

                                    LineItem cureFreq = panel.AddCurve("电流", listFreq, Color.Blue, SymbolType.None);//电流曲线规格赋值

                                    cureAmp.IsY2Axis = true; // 关联cureAmp曲线到右边的纵坐标轴

                                                             //cureFreq.

                                    panel.Title.Text = "电压电流实时曲线";//标题

                                    panel.XAxis.Title.Text = "时间/s";//横坐标

                                    panel.YAxis.Title.Text = "电流/A";//纵坐标

                                    panel.Y2Axis.Title.Text = "电压/V";//纵坐标2   

                                    panel.Y2Axis.IsVisible = true;//纵坐标2显示使能

                                    panel.Title.FontSpec.Family = "Arial";//标题字体样式

                                    panel.Title.FontSpec.Size = 26;//标题字体大小

                                    panel.Title.FontSpec.IsBold = true;//标题字体粗体显示

                                    zgc.PanModifierKeys = Keys.Shift;//想用鼠标拖动坐标轴的话得按住shift

                                    zgc.IsEnableHPan = true; // 鼠标拖动时允许横向移动

                                    zgc.IsEnableVPan = true; // 鼠标拖动时允许纵向移动

                                    zgc.IsShowContextMenu = true;//鼠标右键菜单

                                    zgc.GraphPane.XAxis.MajorTic.IsOpposite = false;//上x轴大刻度禁止显示

                                    zgc.GraphPane.XAxis.MinorTic.IsOpposite = false;//上x轴小刻度禁止显示

                                    zgc.GraphPane.XAxis.MajorGrid.IsVisible = true; // 显示大刻度对应的网格

                                    zgc.GraphPane.XAxis.MinorGrid.IsVisible = true; // 显示小刻度对应的网格

                                    panel.XAxis.MajorGrid.DashOn = 5f;  // 网格为虚线,这句话是设置虚线中的实线部分长度

                                    panel.XAxis.MajorGrid.DashOff = 2f; // 设置虚线中的空白部分长度

                                    panel.XAxis.MajorGrid.PenWidth = 1.5f;  // 设置虚线线宽

                                    zgc.IsEnableVZoom = true;  // 纵轴允许缩放

                                    zgc.IsEnableHZoom = true;   // 横轴允许缩放

                                    zgc.ZoomStepFraction = 0.03; // 缩放速度

                                    zgc.IsShowCursorValues = true;

                                    panel.YAxis.Scale.BaseTic = 0;  // 纵坐标轴的起点从零开始

                                    panel.Y2Axis.Scale.BaseTic = 0; // 纵2坐标轴的起点从零开始

                                    panel.YAxis.Scale.Min = 0;//纵坐标最小值为0

                                    panel.YAxis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴的最大值

                                    panel.Y2Axis.Scale.Min = 0;///纵坐标2最小值为0

                                    panel.Y2Axis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴2的最大值

                                    panel.XAxis.Scale.MinAuto = false; // 根据数据自动匹配横坐标轴的最小值

                                    panel.XAxis.Scale.MaxAuto = true; // 根据数据自动匹配横坐标轴的最大值

                                    panel.XAxis.Scale.IsVisible = true; // 允许显示x轴刻度值

                                    panel.XAxis.Scale.MajorStepAuto = true;//大刻度自动匹配

                                    panel.XAxis.Scale.MinorStepAuto = true;//小刻度自动匹配

                                    panel.Fill = new Fill(Color.Yellow, Color.Pink, 45.0f); // 从左上角45.0°开始,从黄色过渡到粉色

                                    zgc.IsShowPointValues = true;//鼠标移动到某个点时显示该点坐标

                                    zgc.IsZoomOnMouseCenter = true;//以鼠标为中心进行放大

                                    Double[] szy = new Double[dataGridView1.RowCount];//Y轴的数据数组

                                    string[] dates0 = new string[dataGridView1.RowCount];//制作string类型数组,这个数组存的是数据库最近保存的数据的时间信息

                                    for (int i = 0; i < count; i++)//i表示行标

                                    {

                                        listAmp.Add(i, Convert.ToDouble(dataGridView1[3,i].Value.ToString()));

                                        listFreq.Add(i, Convert.ToDouble(dataGridView1[3,i].Value.ToString()) + 1000);

                                        szy[i] = Convert.ToDouble(dataGridView1[3,i].Value.ToString());

                                        dates0[i] = dataGridView1[0,i].Value == null ? "" : dataGridView1[0,i].Value.ToString();

                                    }

                                    panel.XAxis.Type = AxisType.Text;//x轴选择为日期格式

                                    panel.XAxis.Scale.TextLabels = dates0;//数据显示格式为分秒  

                                    zgc.AxisChange(); // 因为点增加,需要自动修改横轴最大值(前提是MaxAuto为true),所以需要更新坐标

                                    Refresh(); // 把变化后的点集显示在图里

                                    connection.Close();

                                }

                                else

                                {

                                    if(Convert.ToInt32(comboBox6.Text)>Convert.ToInt32(comboBox12.Text))

                                    {

                                        MessageBox.Show("秒钟顺序错误!请重新确立!");

                                    }

                                    else

                                    {

                                        SqlConnection connection = new SqlConnection();//新建连接对象

                                        connection.ConnectionString = "Data Source=DESKTOP-F57AF5E;Initial Catalog=Record;Integrated Security=SSPI;";//给连接对象指定连接的参数(连接字符串)

                                        connection.Open();

                                        string strSQL = "select * from Table_1 where 时间>='" + comboBox1.Text + "-" + comboBox2.Text + "-" + comboBox3.Text + " " + comboBox4.Text + ":" + comboBox5.Text + ":" + comboBox6.Text + "' and 时间<='" + comboBox7.Text + "-" + comboBox8.Text + "-" + comboBox9.Text + " " + comboBox10.Text + ":" + comboBox11.Text + ":" + comboBox12.Text + "'";

                                        SqlCommand comm = new SqlCommand(strSQL, connection);

                                        //new Form4().Show();

                                        SqlDataAdapter da = new SqlDataAdapter(strSQL, connection);

                                        DataSet ds = new DataSet();

                                        da.Fill(ds, "Table_1");

                                        dataGridView1.DataSource = ds.Tables["Table_1"];

                                        SqlDataAdapter dant = new SqlDataAdapter(comm);

                                        DataTable dt = new DataTable();

                                        dant.Fill(dt);

                                        int count = dt.Rows.Count;

                                        //曲线

                                        GraphPane panel = zgc.GraphPane;//控件声明

                                        PointPairList listAmp = new PointPairList();//电压曲线声明

                                        PointPairList listFreq = new PointPairList();//电流曲线声明

                                        LineItem cureAmp = panel.AddCurve("电压", listAmp, Color.Red, SymbolType.None);//电压曲线规格赋值

                                        LineItem cureFreq = panel.AddCurve("电流", listFreq, Color.Blue, SymbolType.None);//电流曲线规格赋值

                                        cureAmp.IsY2Axis = true; // 关联cureAmp曲线到右边的纵坐标轴

                                                                 //cureFreq.

                                        panel.Title.Text = "电压电流实时曲线";//标题

                                        panel.XAxis.Title.Text = "时间/s";//横坐标

                                        panel.YAxis.Title.Text = "电流/A";//纵坐标

                                        panel.Y2Axis.Title.Text = "电压/V";//纵坐标2   

                                        panel.Y2Axis.IsVisible = true;//纵坐标2显示使能

                                        panel.Title.FontSpec.Family = "Arial";//标题字体样式

                                        panel.Title.FontSpec.Size = 26;//标题字体大小

                                        panel.Title.FontSpec.IsBold = true;//标题字体粗体显示

                                        zgc.PanModifierKeys = Keys.Shift;//想用鼠标拖动坐标轴的话得按住shift

                                        zgc.IsEnableHPan = true; // 鼠标拖动时允许横向移动

                                        zgc.IsEnableVPan = true; // 鼠标拖动时允许纵向移动

                                        zgc.IsShowContextMenu = true;//鼠标右键菜单

                                        zgc.GraphPane.XAxis.MajorTic.IsOpposite = false;//上x轴大刻度禁止显示

                                        zgc.GraphPane.XAxis.MinorTic.IsOpposite = false;//上x轴小刻度禁止显示

                                        zgc.GraphPane.XAxis.MajorGrid.IsVisible = true; // 显示大刻度对应的网格

                                        zgc.GraphPane.XAxis.MinorGrid.IsVisible = true; // 显示小刻度对应的网格

                                        panel.XAxis.MajorGrid.DashOn = 5f;  // 网格为虚线,这句话是设置虚线中的实线部分长度

                                        panel.XAxis.MajorGrid.DashOff = 2f; // 设置虚线中的空白部分长度

                                        panel.XAxis.MajorGrid.PenWidth = 1.5f;  // 设置虚线线宽

                                        zgc.IsEnableVZoom = true;  // 纵轴允许缩放

                                        zgc.IsEnableHZoom = true;   // 横轴允许缩放

                                        zgc.ZoomStepFraction = 0.03; // 缩放速度

                                        zgc.IsShowCursorValues = true;

                                        panel.YAxis.Scale.BaseTic = 0;  // 纵坐标轴的起点从零开始

                                        panel.Y2Axis.Scale.BaseTic = 0; // 纵2坐标轴的起点从零开始

                                        panel.YAxis.Scale.Min = 0;//纵坐标最小值为0

                                        panel.YAxis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴的最大值

                                        panel.Y2Axis.Scale.Min = 0;///纵坐标2最小值为0

                                        panel.Y2Axis.Scale.MaxAuto = true; // 根据数据自动匹配纵坐标轴2的最大值

                                        panel.XAxis.Scale.MinAuto = false; // 根据数据自动匹配横坐标轴的最小值

                                        panel.XAxis.Scale.MaxAuto = true; // 根据数据自动匹配横坐标轴的最大值

                                        panel.XAxis.Scale.IsVisible = true; // 允许显示x轴刻度值

                                        panel.XAxis.Scale.MajorStepAuto = true;//大刻度自动匹配

                                        panel.XAxis.Scale.MinorStepAuto = true;//小刻度自动匹配

                                        panel.Fill = new Fill(Color.Yellow, Color.Pink, 45.0f); // 从左上角45.0°开始,从黄色过渡到粉色

                                        zgc.IsShowPointValues = true;//鼠标移动到某个点时显示该点坐标

                                        zgc.IsZoomOnMouseCenter = true;//以鼠标为中心进行放大

                                        Double[] szy = new Double[dataGridView1.RowCount];//Y轴的数据数组

                                        string[] dates0 = new string[dataGridView1.RowCount];//制作string类型数组,这个数组存的是数据库最近保存的数据的时间信息

                                        for (int i = 0; i < count; i++)//i表示行标

                                        {

                                            listAmp.Add(i, Convert.ToDouble(dataGridView1[3,i].Value.ToString()));

                                            listFreq.Add(i, Convert.ToDouble(dataGridView1[3,i].Value.ToString()) + 1000);

                                            szy[i] = Convert.ToDouble(dataGridView1[3,i].Value.ToString());

                                            dates0[i] = dataGridView1[0,i].Value == null ? "" : dataGridView1[0,i].Value.ToString();

                                        }

                                        panel.XAxis.Type = AxisType.Text;//x轴选择为日期格式

                                        panel.XAxis.Scale.TextLabels = dates0;//数据显示格式为分秒  

                                        zgc.AxisChange(); // 因为点增加,需要自动修改横轴最大值(前提是MaxAuto为true),所以需要更新坐标

                                        Refresh(); // 把变化后的点集显示在图里

                                        connection.Close();

                                        //panel.CurveList.Clear();//清除这次的曲线

                                    }

                                }

                            }

                        }

                    }

                }

            }

               

        }

三.初步运行界面

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C#工控上位机开发 的相关文章

  • CocosCreator项目实战(13):功能-排行榜

    文章目录 一 主域设置二 子域设置三 其他相关设置 参考Cocos接入微信小游戏官方文档 xff0c 为了保护其社交关系链数据 xff0c 微信小游戏增加了开放数据域的概念 只有在开放数据域中才能访问微信提供的wx getFriendClo
  • Android MotionLayout 运动布局的使用

    Google 在 2018 年开发者大会上推出一种新的布局组件 MotionLayout 其官方定义如下 xff1a MotionLayout is a layout type that helps you manage motion an
  • Jetpack练手(03):DataBinding

    文章目录 一 导入依赖二 搭建布局三 创建 ViewModel 数据对象四 修改布局为 DataBinding 布局五 绑定数据六 Demo 效果 一 导入依赖 新建 DataBindingDemo 工程 xff0c 参照 LiveData
  • Jetpack练手(04):Lifecycle

    文章目录 一 搭建布局二 非 Lifecycle 实现三 Lifecycle 实现四 Demo 效果 一 搭建布局 新建 LifecycleDemo 工程实现 界面停留时间计时 xff0c 在 activity main xml 搭建简单布
  • OpenDDS学习笔记(4):OpenDDS在Linux环境编译

    文章目录 一 编译前准备1 1 环境1 2 下载ACE 43 TAO与OpenDDS1 3 解压安装ACE 43 TAO与OpenDDS1 4 设置相关环境变量 二 编译2 1 设置config h2 2 设置Platform macros
  • OpenDDS学习笔记(2):DDS概述

    文章目录 一 DDS体系结构1 1 DLRL层1 2 DCPS层 二 DDS通信过程三 DDS通信特点四 DDS标准实现4 1 RTI DDS软件4 2 OpenSplice DDS软件4 3 OpenDDS软件 一 DDS体系结构 DDS
  • OpenDDS学习笔记(3):OpenDDS概述

    文章目录 一 DCPS概述1 1 基本组成1 2 内置主题1 3 QoS策略1 4 Listener1 5 条件 二 OpenDDS实现2 1 兼容性2 1 1 DDS兼容性2 1 2 DDS RTPS兼容性 2 2 OpenDDS架构2
  • FastRTPS学习笔记(2):安装、创建简单应用

    文章目录 一 FastRTPS v1 8 0 安装运行1 1 环境准备1 2 下载FastRTPS v1 8 01 3 编译安装1 4 创建简单应用1 4 1 编写简单程序1 4 2 编译简单程序1 4 3 运行简单示例 二 FastRTP
  • EOF是什么?

    转载自 xff1a http www ruanyifeng com blog 2011 11 eof html 我学习C语言的时候 xff0c 遇到的一个问题就是EOF 它是end of file的缩写 xff0c 表示 34 文字流 34
  • FastRTPS学习笔记(1):RTPS概述

    文章目录 一 RTPS简介二 RTPS优点三 RTPS架构3 1 结构模块3 2 消息模块3 3 行为模块3 4 发现模块 四 参考来源 一 RTPS简介 实时发布订阅协议 xff08 Real Time Publish Subscribe
  • 面试笔记:面经-猿辅导-一面

    文章目录 一 自我介绍二 项目相关三 Java后台3 1 Java异常处理3 1 1 Exception和Error的区别3 1 2 RuntimeException和CheckedException的区别 3 2 Java线程3 2 1
  • TensorFlow安装和下载(超详细)

    TensorFlow是一款开源的机器学习框架 xff0c 可用于构建和训练各种深度学习模型 在下面的回答中 xff0c 我将向您介绍如何在Windows Linux和Mac OS系统上安装和下载TensorFlow Windows系统上安装
  • geometry_msgs::PoseWithCovarianceStamped

    该消息表示带有时间标签和参考坐标的估计位姿 两部分构成 xff1a std msgs Header header geometry msgs PoseWithCovariance pose 1 std msgs Header msg主要由三
  • ubuntu vnc 下面小企鹅输入法 的安装及使用

    使用VNC View远程访问ubuntu xff0c 总是没有办法切换出小企鹅输入法的解决办法 安装Fcitx输入法 sudo apt get install fcitx 安装 im switch s fcitx 配置默认输入法为 fcit
  • java解析html之HTMLparser初次尝试

    为了爬取一个网页的数据 xff0c 尝试了一下Htmlparser来做小爬虫 下面是一个小案例 xff0c 用来爬取论坛的帖子内容 1 HtmlParser 简介 htmlparser是一个纯的java写的html解析的库 xff0c 主要
  • px4自定义mavlink收不到消息的问题

    px4版本1 12稳定版 最近在做px4二次开发相关工作 按照网上的一些教程自定义了一个mavlink消息用来控制无人机 按照教程里面的单独开了一个xml来定义消息 最后生成的消息在px4端通过流传输的方式自己写的客户端可以收到消息 但是客
  • windows WSL2 使用Xfce+dummy虚拟显示+VNC显示方案

    最近准备在自己的电脑 windows 下用wsl2装docker 然后将显卡共享给别人用 别骂了别骂了太穷啦太穷了 发现windows微软商店下载的ubuntu20 04子系统没有预装图形界面 想在wsl里面显示东西不好使用 摸索了一番 x
  • 有趣的docker镜像收藏

    docker一键安装脚本 wget qO get docker com sh 官方安装 curl sSL https get daocloud io docker sh 国内daodocker安装 推荐 镜像1 xff1a rastashe
  • vc 网络编程(socket)

    vc 网络编程 xff08 socket xff09 在网上找了很多的资料 xff0c 现将这些资料整合起来 xff0c 详细介绍一下VC下的socket编程 xff0c 并提供一个服务器客户端具体的实例 希望对您有所帮助 一 原理部分 个
  • ROS创建工作空间与功能包

    ROS学习笔记 学习古月居ros21讲笔记 第一章 ROS命令行工具的使用 第二章 创建工作空间与功能包 目录 ROS学习笔记 一 工作空间 二 功能包 一 工作空间 工作空间是存放ROS工程相关文件的文件夹 所有的源码 xff0c 编译文

随机推荐

  • C++类、结构对象内存布局浅析

    最近面试多 xff0c 出的题目很多都有如下形式 xff0c 给定一个class或者struct的定义 xff0c 例如这样 xff1a struct node int a char b int c char d 问题是 xff1a siz
  • 2014校园招聘总结

    本篇博文已迁移至吹水小镇reetsee com xff0c 迁移后地址为 xff1a http blog reetsee com archives 215 注 xff1a 貌似不少童鞋看到这篇东西觉得我是牛人 其实不是stO xff0c 以
  • 今天终于刷完leetcode的题了,同时分享一些资料

    如题了 持续了将近2个月的leetcode刷题之旅今天终于暂时告一段落了 xff08 以后肯定还会加题 xff09 记得我当初刷的时候只有134题 xff0c 现在就变成150题了 xff0c 可以说这些题都是基础 xff0c 但是却是十分
  • 路由器连接校园网并发WIFI:WR703N路由器安装OpenWRT并运行H3C客户端操作步骤(主要针对中山大学东校区)

    注意 xff1a 本文所有的最新更正请全部前往http blog reetsee com archives 227查看 本文主要目的在于让你的路由器能自动连接学校的校园网并且能发出WIFI让所有设备使用 要注意的是这篇作者呕心沥血写的超级傻
  • 教程:用OpenWRT进行WIFI接力——扩大WIFI覆盖范围

    因为准备去实习 xff0c 所以把宿舍很多东西都带回家了 xff0c 包括一个装了OpenWRT的路由器WR703N Step 0 为什么要这么做 在家里有一个地方不爽 xff0c 就是WIFI的信号覆盖不到我的房间 xff0c 所以我就想
  • 一个简单的开源PHP爬虫框架『Phpfetcher』

    这篇文章首发在吹水小镇 xff1a http blog reetsee com archives 366 要在手机或者电脑看到更好的图片或代码欢迎到博文原地址 也欢迎到博文原地址批评指正 转载请注明 xff1a 吹水小镇 reetsee c
  • 「更快!更爽!」吹水新闻2.0

    这篇文章首发在吹水小镇 xff1a http blog reetsee com archives 388 要在手机或者电脑看到更好的图片或代码欢迎到博文原地址 也欢迎到博文原地址批评指正 转载请注明 xff1a 吹水小镇 reetsee c
  • 如何对日志文件进行二分查找?开源文件二分查找工具『timecat』介绍

    这篇文章是我从自己的博客搬运过来的 转载请注明 xff1a 吹水小镇 reetsee com 原文链接地址 xff1a http blog reetsee com archives 502 要获得更好的阅读体验 xff0c 欢迎大家到这篇文
  • 阿里的电话面试是神马感觉

    感觉就是被问了个稀巴烂 xff0c 估计到不了下一轮 问了神马呢 xff0c 问了我的项目 xff0c 我描述了一阵子之后 xff0c 当他问到使用人数的时候 xff0c 我说是内部使用 没有发布 xff0c 只是一件比赛的作品的时候 xf
  • keil5 制作自己的pack

    转发自 xff1a http blog sina com cn s blog dc9571b90102vhqf html 以前都是用的keil5以下版本的keil xff0c 没有RTE这个功能 xff0c 后来安装了keil5以上的版本
  • 找出带环单向链表的环入口(交点)

    其实这个问题已经被问烂了 xff0c 但是之前没有想透 xff0c 今天算是解决得差不多 找环的入口这个问题 xff0c 其实是建立在另外一个问题之上的 判断单向链表是否有环 土方法很多 xff0c 但是比较好的目前就那么一个 xff1a
  • 关于我最近看的一本书——大名鼎鼎的APUE

    APUE xff0c Know as Unix环境高级编程 xff0c 我每天都在用自己的绳命去看 xff0c 每天都燃烧自己去看 什么样的书 xff0c 一看就是上乘之中的珍稀之品 xff1f 这本 不同于不少机械工业出版社的大部头 xf
  • 写博客加分不

    写第一篇博客 xff0c 就看看加分不 xff0c 这个网站分很重要 xff0c 不然下不了东西
  • 若在Ubantu中查询IP地址输入ifconfig时显示没找到该命令时怎么办?

    新手在学习Linux中想要查询IP地址输入ifconfig时却显示如下图 xff1a 这时我们只需要输入sudo apt install net tools 显示这下图时就证明已经安装好了 这时我们只需要 输入ifcogfig xff0c
  • 小觅相机深度版运行Vins-mono

    首先声明 xff0c 本人自己也是slam新手 xff0c 此贴只因为自己在用小觅相机深度版运行Vins的时候太过无助 xff0c 所以想写个自己运行出结果的完整过程 xff0c 仅供参考 xff0c 如有不对之处 xff0c 还望不吝指教
  • shell如何判定C/C++程序是否执行成功

    linux编程中经常遇到这样的问题 xff0c 即判断一个程序执行是否成功 xff0c 通常实现方法是通过进程的退出状态来判断 xff0c 当linux的一个进程执行完成后会返回一个进程的退出状态 xff0c 通过判断退出状态码 可以确定该
  • 删除数组中的指定元素或数组对象

    1 删除数组中的某个指定元素 1 xff09 首先获取元素下标 xff0c 用indexOf 函数找到他的位置index xff0c 如果没有找到这个元素那么index将会等于 1 xff1b 如下为找到元素2的下标 var array 6
  • stm32cubemx 配置FreeRTOS相关基础基础知识及串口接收中断实验

    本实验首先大家自身要有stm32cubemx基础配置 xff0c 比如GPIO 中断 串口 SPI等 xff0c FreeRTOS有相关的调用函数基础及调度任务的概念都需要提前理解 单独stm32cubemx或FreeRTOS网上很多 xf
  • select()

    select 简述 xff1a 确定一个或多个套接口的状态 xff0c 如需要则等待 include lt winsock h gt int PASCAL FAR select int nfds fd set FAR readfds fd
  • C#工控上位机开发

    对于电源软件开发者来说 xff0c 上位机的开发难度是远远小于下位机的 xff0c 之前几个月我一直在研究电力电子技术和下位机的控制算法 xff0c 也有了一点点的收获 xff0c 但说实话还是差的太远了 xff0c 而且人力物力资源非常稀