Compartir tecnología

Transferencia de datos del puerto serie C# al puerto de red para realizar la detección de la velocidad y dirección del viento

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1. Construcción de formularios

Agregar tiempo (temporizador)

Porque la velocidad y la dirección del viento deben actualizarse automáticamente

2. Realizar la detección de aire en el puerto de red

①Botón de conexión al servidor

  1. // 连接按钮
  2. private void button1_Click(object sender, EventArgs e)
  3. {
  4. if (button1.Text =="连接")
  5. {
  6. ConnectSocke();// 连接服务器
  7. }
  8. else
  9. {
  10. CloseSocket(); // 关闭服务器
  11. }
  12. }
  13. Socket soc;
  14. // 连接方法
  15. void ConnectSocke()
  16. {
  17. try
  18. {
  19. // 创建socket对象
  20. soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// 套接字对象
  21. // 连接服务器ip地址,端口号
  22. soc.Connect(this.textBox1.Text, int.Parse(this.textBox2.Text));
  23. button1.Text = "关闭";
  24. textBox1.Enabled = false;
  25. textBox2.Enabled = false;
  26. }
  27. catch (Exception ex)
  28. {
  29. MessageBox.Show("串口服务器连接失败");
  30. }
  31. }
  32. // 关闭方法
  33. void CloseSocket()
  34. {
  35. if (soc!=null && soc.Connected)
  36. {
  37. soc.Close();
  38. }
  39. button1.Text = "连接";
  40. this.textBox1.Enabled = true;
  41. this.textBox2.Enabled = true;
  42. }
  43. // 连接方法
  44. void ConnectSocke()
  45. {
  46. try
  47. {
  48. // 创建socket对象
  49. soc = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);// 套接字对象
  50. // 连接服务器ip地址,端口号
  51. soc.Connect(this.textBox1.Text, int.Parse(this.textBox2.Text));
  52. button1.Text = "关闭";
  53. textBox1.Enabled = false;
  54. textBox2.Enabled = false;
  55. }
  56. catch (Exception ex)
  57. {
  58. MessageBox.Show("串口服务器连接失败");
  59. }
  60. }

Determine si button1.text está "conectado". Si está conectado, ejecute el método ConnectSocke() para ejecutar el servidor; de lo contrario, CloseSocket();

Método de conexión: use el manejo de excepciones try catch, cree una variable global Socket soc; cree un número de puerto IP de conexión de objeto, cambie textbox1.text a cerrado, textBox1.Enabled = false; código en try ¿Se debe informar un error? Si se informa un error, ejecute el código en catch.

Método de desconexión: determine si el soc está vacío o si el soc está conectado. Si la conexión está cerrada soc.Close();, configure button1.text="Connect" para que textbox1 y 2 puedan Enabled = true;

3.Método de conexión

  1. // 发送按钮
  2. private void button2_Click(object sender, EventArgs e)
  3. {
  4. string sendS = this.textBox3.Text.Trim();// 发送字符串
  5. if (soc == null || !soc.Connected)
  6. {
  7. MessageBox.Show("服务器没连接");
  8. return;
  9. }
  10. if (string.IsNullOrEmpty(sendS))
  11. {
  12. MessageBox.Show("指令不能为空");
  13. return;
  14. }
  15. //1 把字符串转成字符数组
  16. byte[] data = StringToHexByte(sendS);
  17. //2 计算校检码
  18. byte[] b1 = CRCCalc(data);
  19. //3 合并字节数组和校检码数组
  20. data = data.Concat(b1).ToArray();
  21. button2.Enabled = false;
  22. Task.Run(() =>
  23. {
  24. //4 发起请求帧
  25. soc.Send(data);// 发消息 请求 温度请求帧data = []
  26. Thread.Sleep(1000);// 休眠1秒
  27. //5 接受数据 // 接收温度
  28. byte[] rec = new byte[1024]; // rec =
  29. int length = soc.Receive(rec);
  30. // 6 解析数据并且展示数据 把字节数组转成字符串
  31. string s = ByteToString(rec, length);
  32. s += "rn";
  33. int temp = (rec[3] * 256 + rec[4]) / 10;// 温度
  34. this.richTextBox1.Invoke((Action)(() =>
  35. {
  36. richTextBox1.AppendText(s);// 响应帧
  37. richTextBox1.AppendText($"当前温度温度为:{temp}摄氏度,时间为:{DateTime.Now.ToString()}rn");
  38. button2.Enabled = true;
  39. }));
  40. });
  41. }
  42. string ByteToString(byte[] b1,int l)
  43. {
  44. StringBuilder sb = new StringBuilder();// 可变字符串
  45. for (int i = 0; i < l; i++)
  46. {
  47. sb.Append(b1[i].ToString("X2")+" ");
  48. }
  49. return sb.ToString();
  50. }
  51. // 字符串转成字符数组
  52. byte[] StringToHexByte(string s)
  53. {
  54. string[] ss = s.Split(' ');
  55. byte[] result = new byte[ss.Length];// 字节数组
  56. for (int i = 0; i < ss.Length; i++)
  57. {
  58. result[i] = Convert.ToByte(ss[i], 16);//转成16进制字节
  59. }
  60. return result;
  61. }
  62. // 校检方法
  63. public static byte[] CRCCalc(byte[] data)
  64. {
  65. //crc计算赋初始值
  66. int crc = 0xffff;
  67. for (int i = 0; i < data.Length; i++)
  68. {
  69. //XOR
  70. //(1) 0^0=0,0^1=1 0异或任何数=任何数
  71. //(2) 1 ^ 0 = 1,1 ^ 1 = 0 1异或任何数-任何数取反
  72. //(3) 1 ^ 1 = 0,0 ^ 0 = 0 任何数异或自己=把自己置0
  73. //异或操作符是^。异或的特点是相同为false,不同为true。
  74. crc = crc ^ data[i]; //和^表示按位异或运算。
  75. //0x0fff ^ 0x01 Console.WriteLine(result.ToString("X"));
  76. // 输出结果为4094,即十六进制数1001
  77. for (int j = 0; j < 8; j++)
  78. {
  79. int temp;
  80. temp = crc & 1; // & 运算符(与) 1 & 0 为 0 ;0 & 0 为0;1 & 1 为1
  81. //右移 (>>) 将第一个操作数向右移动第二个操作数所指定的位数,空出的位置补0。右移相当于整除. 右移一位相当于除以2;右移两位相当于除以4;右移三位相当于除以8。
  82. //int i = 7;
  83. //int j = 2;
  84. //Console.WriteLine(i >> j); //输出结果为1
  85. crc = crc >> 1;
  86. crc = crc & 0x7fff;
  87. if (temp == 1)
  88. {
  89. crc = crc ^ 0xa001;
  90. }
  91. crc = crc & 0xffff;
  92. }
  93. }
  94. //CRC寄存器的高低位进行互换
  95. byte[] crc16 = new byte[2];
  96. //CRC寄存器的高8位变成低8位,
  97. crc16[1] = (byte)((crc >> 8) & 0xff);
  98. //CRC寄存器的低8位变成高8位
  99. crc16[0] = (byte)(crc & 0xff);
  100. return crc16;
  101. }

3. Botón Actualizar

  1. // 刷新按钮
  2. private void button3_Click(object sender, EventArgs e)
  3. {
  4. Refresh1();
  5. }
  6. void Refresh1()
  7. {
  8. if (soc == null || !soc.Connected)
  9. {
  10. MessageBox.Show("没连接");
  11. return;
  12. }
  13. Task.Run(() =>
  14. {
  15. // 请求帧的组织
  16. byte[] bs = new byte[] {0x01,0x03,0x00,0x00,0x00,0x02};// 风速和风向请求放在一起
  17. // 数据和校检
  18. bs = bs.Concat(CRCCalc(bs)).ToArray();
  19. soc.Send(bs);// 发送
  20. Thread.Sleep(1000);
  21. // 接受数据表
  22. byte[] rec = new byte[1024];
  23. int length = soc.Receive(rec);
  24. double wind = (rec[3] * 256 + rec[4]) * 0.01;
  25. double dir = (rec[5] * 256 + rec[6]);
  26. this.Invoke((Action)(() =>
  27. {
  28. this.textBox4.Text = wind + "m/s";
  29. this.textBox5.Text = dir + "";
  30. }));
  31. });
  32. }
  33. // 定时器
  34. private void timer1_Tick(object sender, EventArgs e)
  35. {
  36. if (checkBox1.Checked)// 复选框被选中
  37. {
  38. Refresh1();
  39. }
  40. }
  41. }
  42. }