局域网控制系统-上位机-PC机

Posted weifeng727

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了局域网控制系统-上位机-PC机相关的知识,希望对你有一定的参考价值。

C#程序代码:

  1 using System;
  2 using System.Collections.Generic;
  3 using System.ComponentModel;
  4 using System.Data;
  5 using System.Drawing;
  6 using System.Linq;
  7 using System.Text;
  8 using System.Windows.Forms;
  9 using System.IO.Ports;
 10 //using System.Threading;  //用于多线程技术
 11 
 12 namespace WindowsFormsApplication1    //C#不再支持控件数组,也就意味不能灵活控制控件
 13 {
 14     public partial class Form1 : Form
 15     {
 16         const string deviceID = "03";               //用于串口通信时,定义本地设备ID
 17         const string datapackage_headflag = "A";    //用于串口通信时,定义数据包头部的验证标记
 18         
 19 
 20         //用来请求主线程的委托,利用delegat实现"请求主线程执行指定函数",由于delegate在定义的时候就确定了传递函数的参数,所以在需要传递不同函数给主线程的时候就需要定义多个delegate
 21         public delegate void ChangeUI_1(String arg);   //子线程不能操作UI,会导致程序崩毁,需要让主线程操作UI
 22         public delegate void ChangeUI_2(int[] arg);   
 23         public delegate void ChangeUI_3(String[] arg);
 24         public delegate Boolean ChangeUI_4();
 25 
 26         //----------定时器控制指令的发送----------//
 27         System.Timers.Timer timer_SendCMD = new System.Timers.Timer(1010);   //设定定时器计时周期为1000ms 
 28 
 29         //不断获取温度传感器值
 30         public void GetTemperature(object source, System.Timers.ElapsedEventArgs e)
 31         {
 32             UART_send(uart_data_temperature_sensor0, 40); //建议获取一次温度值后产生40ms发送间隔
 33         }
 34 
 35         //----------固定发送数据包集----------//
 36         const String uart_data_light0off = datapackage_headflag + deviceID + "_Ligt00Off_#";
 37         const String uart_data_light0on  = datapackage_headflag + deviceID + "_Ligt00On__#";
 38         const String uart_data_light1off = datapackage_headflag + deviceID + "_Ligt01Off_#";
 39         const String uart_data_light1on  = datapackage_headflag + deviceID + "_Ligt01On__#";
 40         const String uart_data_light2off = datapackage_headflag + deviceID + "_Ligt02Off_#";
 41         const String uart_data_light2on  = datapackage_headflag + deviceID + "_Ligt02On__#";
 42         const String uart_data_temperature_sensor0 = datapackage_headflag + deviceID + "_SenT00____#";
 43         const String uart_data_try = datapackage_headflag + deviceID + "_Try!______#";
 44         //----------通信监测----------//
 45         Boolean NeedToCheckUART = false;
 46         Boolean heartbeat = false;      //心跳包(用来协助监测通信是否断开)
 47         System.Timers.Timer timer_UARTMonitor = new System.Timers.Timer(2000);          
 48         public void CheckUART(object source, System.Timers.ElapsedEventArgs e)   
 49         {
 50             if (NeedToCheckUART)  //检查通信状态
 51             {
 52                 NeedToCheckUART = false;
 53                 if (heartbeat)
 54                 {
 55                     heartbeat = false;
 56                 }
 57                 else
 58                 {
 59                     this.Invoke(new ChangeUI_4(CloseUART));
 60                     this.Invoke(new ChangeUI_1(UpdateNotice), "已断开连接!没有接收到心跳包!");
 61                 }
 62             }
 63             else
 64             {
 65                 NeedToCheckUART = true;
 66                 //请求接收者反馈心跳包,以确认连接是否出现异常              
 67                 UART_send(uart_data_try,25);  
 68             } 
 69         }
 70         //----------产生发送数据的间隔----------//
 71         Boolean SendCMD_WaitFlag = false;
 72         void SetSendCMD_Interval(uint Interval)
 73         {
 74             System.Timers.Timer timer_SetSendCMD_Interval = new System.Timers.Timer(Interval);
 75             timer_SetSendCMD_Interval.Elapsed += new System.Timers.ElapsedEventHandler(Erase_SendCMD_WaitFlag);
 76             timer_SetSendCMD_Interval.AutoReset = false;
 77             timer_SetSendCMD_Interval.Start();
 78         }
 79         public void Erase_SendCMD_WaitFlag(object source, System.Timers.ElapsedEventArgs e)
 80         {
 81             SendCMD_WaitFlag = false;
 82         }
 83         //----------温度指示----------//
 84         int[] TemperatureSensor = new int[4];
 85         int   UpLimit_1 = 301,          //300=30℃
 86               DownLimit_1 = 100,
 87               UpLimit_2 = 300,
 88               DownLimit_2 = 100,
 89               UpLimit_3 = 300,
 90               DownLimit_3 = 100,
 91               UpLimit_4 = 300,
 92               DownLimit_4 = 100;
 93         SolidBrush brush1,
 94                    brush2;
 95         Graphics g1,
 96                  g2,
 97                  g3,
 98                  g4,
 99                  g5,
100                  g6,
101                  g7,
102                  g8;
103         //------------------------------------//
104         public Form1()
105         {
106             InitializeComponent();
107 
108         }
109 
110         private void Form1_Load(object sender, EventArgs e)
111         {
112             /*--------串口通信监测---------*/
113             timer_UARTMonitor.Elapsed += new System.Timers.ElapsedEventHandler(CheckUART);   // 添加定时器计时满一个周期的后要执行的函数;
114             timer_UARTMonitor.AutoReset = true;  //设置定时器是否启动自动复位,true意味着定时器一旦启动,如果没有手动关闭,则定时器会不断周期性执行任务,false意味着启动定时器后,到达周期时间值,执行一次任务,然后自动关闭定时器
115             //----------定时器控制指令的发送----------//
116             timer_SendCMD.Elapsed += new System.Timers.ElapsedEventHandler(GetTemperature);
117             timer_SendCMD.AutoReset = true;
118             /*----------串口通信接口设置----------*/
119             cmb_SerialPort.SelectedIndex = 0;
120             cmb_BaudRate.SelectedIndex = 1;
121             cmb_Parity.SelectedIndex = 0;
122             cmb_DataBit.SelectedIndex = 0;
123             cmb_StopBit.SelectedIndex = 0;
124             btn_Send.Enabled = false;
125             btn_UpdataReceive.Text = "关闭更新串口数据";
126 
127             //温度警报指示
128             brush1 = new SolidBrush(Color.Red);
129             brush2 = new SolidBrush(Color.Green);
130             g1 = this.pictureBox1.CreateGraphics();
131             g2 = this.pictureBox2.CreateGraphics();
132             g3 = this.pictureBox3.CreateGraphics();
133             g4 = this.pictureBox4.CreateGraphics();
134             g5 = this.pictureBox5.CreateGraphics();
135             g6 = this.pictureBox6.CreateGraphics();
136             g7 = this.pictureBox7.CreateGraphics();
137             g8 = this.pictureBox8.CreateGraphics();
138             
139             //温度上下限文本框初始化
140             textBox1.Text = Convert.ToString((float)(UpLimit_1)/10);
141             textBox2.Text = Convert.ToString((float)(DownLimit_1)/10);
142             textBox4.Text = Convert.ToString((float)(UpLimit_2)/10);
143             textBox3.Text = Convert.ToString((float)(DownLimit_2)/10);
144             textBox6.Text = Convert.ToString((float)(UpLimit_3)/10);
145             textBox5.Text = Convert.ToString((float)(DownLimit_3)/10);
146             textBox8.Text = Convert.ToString((float)(UpLimit_4)/10);
147             textBox7.Text = Convert.ToString((float)(DownLimit_4)/10);
148 
149         }
150        
151         /*----------串口通信接口设置----------*/
152         /*
153             客户端数据包格式解释(长度恒为15):
154             例如:A01_fmq_01Off___#
155             A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)
156             01-----设备代号
157             fmq_01Off___--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部
158             #---------数据包的结束标记
159 
160             服务器端数据包格式解释(长度恒为15):
161             例如:A02_SenT010250#
162             A--------数据包的开始标记(可以为A到Z,意味着数据包可以有26种)
163             02-----设备代号
164             SenT010250--------指令(长度恒为10),指令的前4个人字符是指令头部,指令的后6个字符是指令尾部
165             #---------数据包的结束标记
166          */
167         SerialPort com = new SerialPort("COM2", 9600, Parity.None, 8, StopBits.One);
168         //串口打开与关闭
169         public Boolean CloseUART()
170         {
171             timer_UARTMonitor.Stop();    //停止定时器监测通信状态
172             timer_SendCMD.Stop();       //停止定时器控制指令的定时发送
173             try
174             {
175                 com.Close(); //关闭串口
176                 btn_OpenSerial.Text = "打开串口";
177                 lab_Status.Text = "未连接!";
178                 btn_Send.Enabled = false;
179                 return true;
180             }
181             catch
182             {
183                 return false;
184             }
185         }
186         //处理接收数据包函数(成功处理数据包则返回true,否则返回false)
187         public Boolean Deal_UART_RecData(String ReceStr)   
188         {
189             if (ReceStr.Length == 15)  //数据包长度为15
190             {
191                 if ((ReceStr.Substring(0, 1) == datapackage_headflag) && (ReceStr.Substring(14, 1) == "#"))  //数据包头尾标记验证
192                 {
193                     switch (ReceStr.Substring(1, 1))   //识别发送者设备ID的第1位数字
194                     {
195                         case "0":
196                             switch (ReceStr.Substring(2, 1))   //识别发送者设备ID的第2位数字
197                             {
198                                 case "0":
199 
200                                     return false;
201                                 case "1":
202 
203                                     return false;
204                                 case "2":
205                                     //----------指令分析-----------//
206                                     switch (ReceStr.Substring(4, 4))   //对指令头部进行分析(4个字符)
207                                     {
208                                         case "SenT":
209                                             //对指令尾部进行分析(6个字符)
210                                             int[] temp = new int[2];
211                                             try
212                                             {
213                                                 temp[0] = int.Parse(ReceStr.Substring(8, 2));
214                                                 temp[1] = int.Parse(ReceStr.Substring(10, 4));
215                                                 TemperatureSensor[temp[0]] = temp[1];
216                                                 this.Invoke(new ChangeUI_2(UpdateSenT), temp);
217                                                 return true;
218                                             }
219                                             catch
220                                             {
221                                                 this.Invoke(new ChangeUI_1(UpdateNotice), "接收的指令:指令尾部异常");
222                                                 return false;
223                                             }                 
224                                         case "Beat":
225                                             heartbeat = true;
226                                             return true;
227                                         default:
228                                             this.Invoke(new ChangeUI_1(UpdateNotice), "接收的指令:指令头部异常");
229                                             return false;
230                                     }          
231                                 default:
232                                     this.Invoke(new ChangeUI_1(UpdateNotice), "接收的数据包:设备ID异常");
233                                     return false;
234                             }
235                         default:
236                             this.Invoke(new ChangeUI_1(UpdateNotice), "接收的数据包:设备ID异常");
237                             return false; 
238                     }                   
239                 }
240                 else
241                 {
242                     this.Invoke(new ChangeUI_1(UpdateNotice), "接收的数据包:头尾部验证异常");
243                     return false;
244                 }
245             }
246             else
247             {
248                 this.Invoke(new ChangeUI_1(UpdateNotice), "接收的数据包:长度异常");
249                 return false;
250             }
251         }
252         //打开或关闭串口按钮
253         private void btn_OpenSerial_Click(object sender, EventArgs e)
254         {
255             if (btn_OpenSerial.Text == "打开串口")
256             {
257                 try
258                 {
259                     if (!com.IsOpen)
260                     {
261                         com.PortName = cmb_SerialPort.Text;
262                         com.BaudRate = int.Parse(cmb_BaudRate.Text);
263                         com.DataBits = int.Parse(cmb_DataBit.Text);
264                         switch (cmb_StopBit.SelectedIndex)
265                         {
266                             case 0:
267                                 com.StopBits = StopBits.One; break;
268                             case 1:
269                                 com.StopBits = StopBits.Two; break;
270                             case 2:
271                                 com.StopBits = StopBits.OnePointFive; break;
272                             case 3:
273                                 com.StopBits = StopBits.None; break;
274                         }
275                         switch (cmb_Parity.SelectedIndex)
276                         {
277                             case 0: com.Parity = Parity.None; break;
278                             case 1: com.Parity = Parity.Odd; break;
279                             case 2: com.Parity = Parity.Even; break;
280                         }                  
281                         com.Open();//打开串口
282                         lab_Status.Text = "已连接!";
283                     }                
284                     btn_OpenSerial.Text = "关闭串口";
285                     btn_Send.Enabled = true;
286 
287                     //串口连接成功后进行初始化
288                     NeedToCheckUART = false;
289                     heartbeat = false;
290                     timer_SendCMD.Start();       //每隔一段时间获取一次温度值数据
291                     timer_UARTMonitor.Start();    //启动定时器监测通信状态
292 
293                     try
294                     {
295                         //给串口添加接收中断函数(串口中断函数在没有被执行的时候,也就是串口接收处理空闲的时候,系统会不断监测接收缓冲区是否有数据存在,如果有,则执行中断函数)
296                         com.DataReceived += new SerialDataReceivedEventHandler(com_DataReceived);
297                     }
298                     catch (Exception err)
299                     {
300                         lab_Status.Text = err.ToString();
301                     }
302                     
303                 }
304                 catch
305                 {
306                     lab_Status.Text = "串口打开错误";
307                 }
308             }
309             else //关闭串口
310             {
311                 CloseUART();
312             }
313         }
314         //串口接收中断函数(注意:不要出现数据包被分割,导致通信异常;数据包之间间隔时间不能太短)     
315         private void com_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
316         {
317             System.Threading.Thread.Sleep(30);  //让当前线程睡眠30ms,因为需要保证数据包完整接收到了(在执行中断函数并获取接收缓冲区接收到的字节数时,假如数据包还没有完全被接收完,这时数据包就会出现被“分割”),再去判断接收缓冲区接收到的字节数,才能保证正常通信
318             int count = com.BytesToRead;       //获取接收缓冲区接收到的字节数
319             byte[] readBuffer = new byte[count];
320             com.Read(readBuffer, 0, count);
321             String strReceive = Encoding.Default.GetString(readBuffer); //将ASCLL码  映射成  字符 
322             //String strReceive = getStringFromBytes(readBuffer);           //将ASCLL码  转换成  字符串 
323             this.Invoke(new ChangeUI_1(AddMessage), strReceive); //尝试更新接收数据框
324             //this.Invoke(new ChangeUI_1(UpdateNotice), strReceive.Length.ToString());  //此行代码用于测试数据包是否出现被分割
325             
326             //下面对接收到的数据包(strReceive)进行分析,根据情况执行相应事件      
327             if (Deal_UART_RecData(strReceive))
328             {
329                 this.Invoke(new ChangeUI_1(UpdateNotice), "处理接收的数据包成功!");
330             }
331            
332         }
333         //子线程请求主线程要执行的子函数,当发生多次请求时,主线程会分时执行函数(之所以要请求主线程是因为涉及到UI操作,子线程不能操作UI,否则导致程序崩毁)
334         public void UpdateSenT(int[] arg)
335         {
336             Int16 graphy_width = 44;
337             Int16 graphy_heigth = 21;
338             switch (arg[0])
339             {
340                 case 0:
341                     if (arg[1] == 9999)  
342                     {
343                         label6.Text = "不工作";
344                         return;
345                     }
346                     if (arg[1] < 0)
347                     {
348                         label6.Text = (arg[1] / 10).ToString() + "." + ((arg[1] % 10)*(-1)).ToString() + "";
349                     }
350                     else
351                     {
352                         label6.Text = "+"+(arg[1] / 10).ToString() + "." + (arg[1] % 10).ToString() + "";
353                     }
354                     if (TemperatureSensor[arg[0]] > UpLimit_1)
355                     {
356                         g1.FillRectangle(brush1, 0, 0, graphy_width, graphy_heigth);
357                         g2.FillRectangle(brush2, 0, 0, graphy_width, graphy_heigth);
358                     }
359                     else if (TemperatureSensor[arg[0]] < DownLimit_1)
360                     {
361                         g2.FillRectangle(brush1, 0, 0, graphy_width, graphy_heigth);
362                         g1.FillRectangle(brush2, 0, 0, graphy_width, graphy_heigth);
363                     }
364                     else
365                     {
366                         g1.FillRectangle(brush2, 0, 0, graphy_width, graphy_heigth);
367                         g2.FillRectangle(brush2, 0, 0, graphy_width, graphy_heigth);
368                     }
369                     break;
370                 case 1:
371                     if (arg[1] == 9999)
372                     {
373                         label7.Text = "不工作";
374                         

以上是关于局域网控制系统-上位机-PC机的主要内容,如果未能解决你的问题,请参考以下文章

家居环境监測系统设计(PC上位机版)(手机APP版待定)

PIBOT使用手册-PC是Windows系统, 车载上位机树莓派/nanopi

开源应用QT—TCP网络上位机的设计

什么叫上位机软件

上位机 下位机

zigbee上位机和网关通信代码以及代码应该放在啥部分,涉及到操作系统的