2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Add time (timer)
Because the wind speed and wind direction need to be automatically refreshed
①Server connection button
- // 连接按钮
- private void button1_Click(object sender, EventArgs e)
- {
- if (button1.Text =="连接")
- {
- ConnectSocke();// 连接服务器
- }
- else
- {
- CloseSocket(); // 关闭服务器
- }
- }
- Socket soc;
- // 连接方法
- void ConnectSocke()
- {
- try
- {
- // 创建socket对象
- soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// 套接字对象
- // 连接服务器ip地址,端口号
- soc.Connect(this.textBox1.Text, int.Parse(this.textBox2.Text));
- button1.Text = "关闭";
- textBox1.Enabled = false;
- textBox2.Enabled = false;
- }
- catch (Exception ex)
- {
- MessageBox.Show("串口服务器连接失败");
- }
- }
- // 关闭方法
- void CloseSocket()
- {
- if (soc!=null && soc.Connected)
- {
- soc.Close();
- }
- button1.Text = "连接";
- this.textBox1.Enabled = true;
- this.textBox2.Enabled = true;
- }
- // 连接方法
- void ConnectSocke()
- {
- try
- {
- // 创建socket对象
- soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// 套接字对象
-
- // 连接服务器ip地址,端口号
- soc.Connect(this.textBox1.Text, int.Parse(this.textBox2.Text));
- button1.Text = "关闭";
- textBox1.Enabled = false;
- textBox2.Enabled = false;
- }
- catch (Exception ex)
- {
-
- MessageBox.Show("串口服务器连接失败");
- }
- }
Determine whether button1.text is "Connect". If it is connected, perform ConnectSocket(); to run the server method, otherwise perform CloseSocket(); to close the server method.
Connection method: Use try catch exception handling to create a global variable Socket soc; create an object to connect to the ip port number, change textbox1.text to close, textBox1.Enabled=false; make the input box unable to input, catch exception handling to determine whether the code in try reports an error, if an error is reported, run the code in catch
Disconnect method: determine whether soc is empty or connected. If the connection is closed, soc.Close();, set button1.text = "Connect", so that textbox1 and 2 can be Enabled = true; release
- // 发送按钮
- private void button2_Click(object sender, EventArgs e)
- {
- string sendS = this.textBox3.Text.Trim();// 发送字符串
- if (soc == null || !soc.Connected)
- {
- MessageBox.Show("服务器没连接");
- return;
- }
- if (string.IsNullOrEmpty(sendS))
- {
- MessageBox.Show("指令不能为空");
- return;
- }
-
- //1 把字符串转成字符数组
- byte[] data = StringToHexByte(sendS);
- //2 计算校检码
- byte[] b1 = CRCCalc(data);
- //3 合并字节数组和校检码数组
- data = data.Concat(b1).ToArray();
-
- button2.Enabled = false;
- Task.Run(() =>
- {
- //4 发起请求帧
- soc.Send(data);// 发消息 请求 温度请求帧data = []
-
- Thread.Sleep(1000);// 休眠1秒
-
- //5 接受数据 // 接收温度
- byte[] rec = new byte[1024]; // rec =
- int length = soc.Receive(rec);
-
- // 6 解析数据并且展示数据 把字节数组转成字符串
- string s = ByteToString(rec, length);
- s += "rn";
- int temp = (rec[3] * 256 + rec[4]) / 10;// 温度
- this.richTextBox1.Invoke((Action)(() =>
- {
- richTextBox1.AppendText(s);// 响应帧
- richTextBox1.AppendText($"当前温度温度为:{temp}摄氏度,时间为:{DateTime.Now.ToString()}rn");
- button2.Enabled = true;
- }));
-
- });
- }
- string ByteToString(byte[] b1,int l)
- {
- StringBuilder sb = new StringBuilder();// 可变字符串
- for (int i = 0; i < l; i++)
- {
- sb.Append(b1[i].ToString("X2")+" ");
- }
-
- return sb.ToString();
- }
-
-
- // 字符串转成字符数组
- byte[] StringToHexByte(string s)
- {
- string[] ss = s.Split(' ');
- byte[] result = new byte[ss.Length];// 字节数组
- for (int i = 0; i < ss.Length; i++)
- {
- result[i] = Convert.ToByte(ss[i], 16);//转成16进制字节
- }
- return result;
- }
- // 校检方法
- public static byte[] CRCCalc(byte[] data)
- {
- //crc计算赋初始值
- int crc = 0xffff;
- for (int i = 0; i < data.Length; i++)
- {
- //XOR
- //(1) 0^0=0,0^1=1 0异或任何数=任何数
- //(2) 1 ^ 0 = 1,1 ^ 1 = 0 1异或任何数-任何数取反
- //(3) 1 ^ 1 = 0,0 ^ 0 = 0 任何数异或自己=把自己置0
- //异或操作符是^。异或的特点是相同为false,不同为true。
- crc = crc ^ data[i]; //和^表示按位异或运算。
- //0x0fff ^ 0x01 Console.WriteLine(result.ToString("X"));
- // 输出结果为4094,即十六进制数1001
- for (int j = 0; j < 8; j++)
- {
- int temp;
- temp = crc & 1; // & 运算符(与) 1 & 0 为 0 ;0 & 0 为0;1 & 1 为1
-
- //右移 (>>) 将第一个操作数向右移动第二个操作数所指定的位数,空出的位置补0。右移相当于整除. 右移一位相当于除以2;右移两位相当于除以4;右移三位相当于除以8。
- //int i = 7;
- //int j = 2;
- //Console.WriteLine(i >> j); //输出结果为1
- crc = crc >> 1;
- crc = crc & 0x7fff;
- if (temp == 1)
- {
- crc = crc ^ 0xa001;
- }
- crc = crc & 0xffff;
- }
- }
- //CRC寄存器的高低位进行互换
- byte[] crc16 = new byte[2];
- //CRC寄存器的高8位变成低8位,
- crc16[1] = (byte)((crc >> 8) & 0xff);
- //CRC寄存器的低8位变成高8位
- crc16[0] = (byte)(crc & 0xff);
- return crc16;
- }
- // 刷新按钮
- private void button3_Click(object sender, EventArgs e)
- {
- Refresh1();
- }
- void Refresh1()
- {
- if (soc == null || !soc.Connected)
- {
- MessageBox.Show("没连接");
- return;
- }
- Task.Run(() =>
- {
- // 请求帧的组织
- byte[] bs = new byte[] {0x01,0x03,0x00,0x00,0x00,0x02};// 风速和风向请求放在一起
-
- // 数据和校检
- bs = bs.Concat(CRCCalc(bs)).ToArray();
-
- soc.Send(bs);// 发送
-
- Thread.Sleep(1000);
-
- // 接受数据表
- byte[] rec = new byte[1024];
- int length = soc.Receive(rec);
-
- double wind = (rec[3] * 256 + rec[4]) * 0.01;
- double dir = (rec[5] * 256 + rec[6]);
- this.Invoke((Action)(() =>
- {
- this.textBox4.Text = wind + "m/s";
- this.textBox5.Text = dir + "";
- }));
-
-
- });
- }
-
- // 定时器
- private void timer1_Tick(object sender, EventArgs e)
- {
- if (checkBox1.Checked)// 复选框被选中
- {
- Refresh1();
- }
-
- }
- }
-
- }