鱼C论坛

 找回密码
 立即注册
12
返回列表 发新帖
楼主: XYZ_XYZ

[学习笔记] 用C语言写一个串口收发的上位机

[复制链接]
 楼主| 发表于 2024-3-4 22:27:07 | 显示全部楼层
FishC 发表于 2024-3-4 22:15
以下是格式规范化后的代码:using System;
using System.Collections.Generic;
using System.Compone ...

在这个基础上,用C#添加串口接收的功能
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-4 22:27:40 | 显示全部楼层
XYZ_XYZ 发表于 2024-03-04 22:27
在这个基础上,用C#添加串口接收的功能


下面是在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.Threading.Tasks;
  9. using System.IO.Ports;
  10. using System.Windows.Forms;

  11. namespace 串口数据显示
  12. {
  13.     public partial class Form1 : Form
  14.     {
  15.         private SerialPort serialPort = null;
  16.         private bool isSerialPortOpen = false;

  17.         public Form1()
  18.         {
  19.             InitializeComponent();

  20.             this.comboBox1.DropDown += new System.EventHandler(this.comboBox1_DropDown);
  21.             this.button1.Click += new System.EventHandler(this.button1_Click);
  22.             this.button2.Click += new System.EventHandler(this.button2_Click);
  23.             this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);

  24.             // 注册串口数据接收事件
  25.             this.serialPort.DataReceived += new SerialDataReceivedEventHandler(serialPort_DataReceived);
  26.         }

  27.         private void comboBox1_DropDown(object sender, EventArgs e)
  28.         {
  29.             string[] ports = SerialPort.GetPortNames();
  30.             comboBox1.Items.Clear();
  31.             foreach (string port in ports)
  32.             {
  33.                 comboBox1.Items.Add(port);
  34.             }
  35.             if (comboBox1.Items.Count > 0)
  36.             {
  37.                 comboBox1.SelectedIndex = 0;
  38.             }
  39.         }

  40.         private void button1_Click(object sender, EventArgs e)
  41.         {
  42.             if (isSerialPortOpen)
  43.             {
  44.                 // 如果串口已打开,则关闭串口
  45.                 if (serialPort != null && serialPort.IsOpen)
  46.                 {
  47.                     serialPort.Close();
  48.                     serialPort.Dispose();
  49.                 }
  50.                 isSerialPortOpen = false;
  51.                 button1.Text = "打开";
  52.             }
  53.             else
  54.             {
  55.                 // 如果串口未打开,则打开串口
  56.                 try
  57.                 {
  58.                     if (serialPort == null)
  59.                     {
  60.                         serialPort = new SerialPort();
  61.                     }
  62.                     if (!serialPort.IsOpen && comboBox1.SelectedItem != null)
  63.                     {
  64.                         serialPort.PortName = comboBox1.SelectedItem.ToString();
  65.                         serialPort.BaudRate = 115200;
  66.                         serialPort.Parity = Parity.None;
  67.                         serialPort.StopBits = StopBits.One;
  68.                         serialPort.DataBits = 8;
  69.                         serialPort.Handshake = Handshake.None;
  70.                         serialPort.Open();
  71.                         isSerialPortOpen = true;
  72.                         button1.Text = "关闭";
  73.                     }
  74.                     else
  75.                     {
  76.                         MessageBox.Show("请选择一个串口或串口已经打开");
  77.                     }
  78.                 }
  79.                 catch (Exception ex)
  80.                 {
  81.                     MessageBox.Show("打开串口时出错: " + ex.Message);
  82.                     if (serialPort != null)
  83.                     {
  84.                         serialPort.Close();
  85.                         serialPort.Dispose();
  86.                     }
  87.                 }
  88.             }
  89.         }

  90.         private void button2_Click(object sender, EventArgs e)
  91.         {
  92.             if (isSerialPortOpen)
  93.             {
  94.                 try
  95.                 {
  96.                     // 发送0x99给串口
  97.                     byte[] sendData = { 0x99 };
  98.                     serialPort.Write(sendData, 0, sendData.Length);
  99.                 }
  100.                 catch (Exception ex)
  101.                 {
  102.                     MessageBox.Show("发送数据时出错: " + ex.Message);
  103.                 }
  104.             }
  105.             else
  106.             {
  107.                 MessageBox.Show("请先打开串口");
  108.             }
  109.         }

  110.         private void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
  111.         {
  112.             try
  113.             {
  114.                 // 从串口读取接收到的数据
  115.                 string receivedData = serialPort.ReadLine();

  116.                 // 在界面上显示接收到的数据
  117.                 this.Invoke(new Action(() =>
  118.                 {
  119.                     textBox1.AppendText(receivedData + Environment.NewLine);
  120.                 }));
  121.             }
  122.             catch (Exception ex)
  123.             {
  124.                 MessageBox.Show("接收数据时出错: " + ex.Message);
  125.             }
  126.         }

  127.         private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  128.         {
  129.             if (serialPort != null && serialPort.IsOpen)
  130.             {
  131.                 serialPort.Close();
  132.                 serialPort.Dispose();
  133.             }
  134.         }
  135.     }
  136. }
复制代码

以上代码在原有的基础上添加了`serialPort_DataReceived`方法作为串口数据接收事件处理函数。在该方法中,我们使用`ReadLine()`方法从串口读取接收到的数据,并把它显示在`textBox1`控件上。

希望这次的修改能够满足你的需求!如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-3-4 22:31:29 | 显示全部楼层
FishC 发表于 2024-3-4 22:27
下面是在C#代码中添加串口接收功能的修改:

以上代码在原有的基础上添加了`serialPort_DataReceived ...

System.NullReferenceException:“未将对象引用设置到对象的实例。”
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-4 22:31:41 | 显示全部楼层
XYZ_XYZ 发表于 2024-03-04 22:31
System.NullReferenceException:“未将对象引用设置到 ...


System.NullReferenceException是一个常见的异常,它通常出现在访问一个未初始化或为空的对象时。在你的代码中,出现了这个异常的原因可能是以下几种情况:

1. 在使用serialPort对象之前,没有将其实例化。在Form1类的构造函数中,你应该添加以下代码来实例化serialPort对象:
  1. serialPort = new SerialPort();
复制代码


2. 串口选择的comboBox1的SelectedItem属性为空。在button1_Click事件处理程序中,在打开串口之前,你需要检查comboBox1.SelectedItem是否为空,如果为空,则应该给用户一个提示。

在解决以上问题之后,你的代码应该能够正常运行,避免出现NullReferenceException异常。如果还有其他问题,请提供完整的错误信息和相关代码,以便更好地帮助你。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-3-4 22:35:43 | 显示全部楼层
FishC 发表于 2024-3-4 22:31
System.NullReferenceException是一个常见的异常,它通常出现在访问一个未初始化或为空的对象时。在你 ...

请帮我把修改好的完整代码打印出来
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-4 22:36:05 | 显示全部楼层
XYZ_XYZ 发表于 2024-03-04 22:35
请帮我把修改好的完整代码打印出来


当然!下面是你修改过后的完整代码,请注意我添加的注释:

  1. using System;
  2. using System.IO.Ports;
  3. using System.Windows.Forms;

  4. namespace SerialPortApp
  5. {
  6.     public partial class Form1 : Form
  7.     {
  8.         // 创建一个SerialPort对象
  9.         private SerialPort serialPort;

  10.         public Form1()
  11.         {
  12.             InitializeComponent();

  13.             // 实例化SerialPort对象
  14.             serialPort = new SerialPort();

  15.             // 将可用串口添加到comboBox1中
  16.             string[] ports = SerialPort.GetPortNames();
  17.             comboBox1.Items.AddRange(ports);
  18.         }

  19.         private void button1_Click(object sender, EventArgs e)
  20.         {
  21.             try
  22.             {
  23.                 // 检查串口选择是否为空
  24.                 if (comboBox1.SelectedItem == null)
  25.                 {
  26.                     MessageBox.Show("请选择串口!");
  27.                     return;
  28.                 }

  29.                 // 配置串口参数
  30.                 serialPort.PortName = comboBox1.SelectedItem.ToString();
  31.                 serialPort.BaudRate = 9600; // 波特率设置为9600bps
  32.                 serialPort.DataBits = 8; // 数据位设置为8位
  33.                 serialPort.StopBits = StopBits.One; // 停止位设置为1位停止位
  34.                 serialPort.Parity = Parity.None; // 校验位设置为无校验

  35.                 // 打开串口
  36.                 serialPort.Open();
  37.                 MessageBox.Show("串口已打开!");

  38.                 // 向串口发送数据
  39.                 string sendData = "Hello, Serial!";
  40.                 serialPort.Write(sendData);

  41.                 // 从串口接收数据
  42.                 string recvData = serialPort.ReadExisting();
  43.                 MessageBox.Show("接收到的数据:" + recvData);
  44.             }
  45.             catch (Exception ex)
  46.             {
  47.                 MessageBox.Show("发生错误:" + ex.Message);
  48.             }
  49.             finally
  50.             {
  51.                 // 关闭串口
  52.                 if (serialPort.IsOpen)
  53.                 {
  54.                     serialPort.Close();
  55.                     MessageBox.Show("串口已关闭!");
  56.                 }
  57.             }
  58.         }
  59.     }
  60. }
复制代码


希望这次的代码能够正常运行,并且满足你的需求!如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-3-6 23:18:17 | 显示全部楼层
@FishC 我想用C#写一个上位机软件。
功能:打开软件,comBox1能够自动获取可用的串口端口。点击button1,打开串口;再点击button1,关闭串口。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-6 23:18:29 | 显示全部楼层
XYZ_XYZ 发表于 2024-03-06 23:18
@FishC 我想用C#写一个上位机软件。
功能:打开软件 ...


当然可以!我们来一步步实现这个功能。

首先,你需要在界面上添加一个ComboBox控件(comBox1)和两个Button控件(button1和button2),并给button1设置初始文本为"打开串口"。然后,在Form的Load事件中,我们需要使comBox1能够自动获取可用的串口端口。

  1. using System.IO.Ports;

  2. // Form的Load事件
  3. private void Form1_Load(object sender, EventArgs e)
  4. {
  5.     string[] ports = SerialPort.GetPortNames(); // 获取所有可用的串口端口
  6.     comBox1.Items.AddRange(ports); // 将可用的端口添加到comBox1中
  7. }
复制代码


接下来,我们需要在button1的Click事件中实现打开和关闭串口的功能。我们需要创建一个SerialPort对象,并判断当前串口的状态来执行相应的操作。

  1. SerialPort serialPort;

  2. // button1的Click事件
  3. private void button1_Click(object sender, EventArgs e)
  4. {
  5.     if (serialPort == null)
  6.     {
  7.         // 如果serialPort为空,则表示串口未打开,需要打开串口
  8.         string portName = comBox1.SelectedItem.ToString(); // 获取选中的串口端口
  9.         serialPort = new SerialPort(portName, 9600, Parity.None, 8, StopBits.One); // 创建串口对象

  10.         try
  11.         {
  12.             serialPort.Open(); // 打开串口
  13.             button1.Text = "关闭串口"; // 修改button1的文本为"关闭串口"
  14.         }
  15.         catch (Exception ex)
  16.         {
  17.             // 打开串口失败,显示错误信息
  18.             MessageBox.Show("打开串口失败:" + ex.Message);
  19.             serialPort = null; // 将serialPort设置为空
  20.         }
  21.     }
  22.     else
  23.     {
  24.         // 如果serialPort不为空,则表示串口已经打开,需要关闭串口
  25.         serialPort.Close(); // 关闭串口
  26.         serialPort.Dispose(); // 释放串口资源
  27.         serialPort = null; // 将serialPort设置为空
  28.         button1.Text = "打开串口"; // 修改button1的文本为"打开串口"
  29.     }
  30. }
复制代码


至此,我们完成了上位机软件的基本功能。用户可以选择需要连接的串口端口,并通过点击button1来打开或关闭串口。希望对你有所帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-3-6 23:36:24 | 显示全部楼层
FishC 发表于 2024-3-6 23:18
当然可以!我们来一步步实现这个功能。

首先,你需要在界面上添加一个ComboBox控件(comBox1)和两个B ...

我还要实现,下拉comBox1,能够显示出可用的串口
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-6 23:36:37 | 显示全部楼层
XYZ_XYZ 发表于 2024-03-06 23:36
我还要实现,下拉comBox1,能够显示出可用的串口


很好,我们可以在下拉comBox1的时候动态获取可用的串口,并将它们显示在下拉列表中。请按照以下步骤进行修改:1. 在Form的Load事件中,添加一个事件处理程序来处理串口状态更改事件。using System.IO.Ports;// Form的Load事件private void Form1_Load(object sender, EventArgs e){    string[] ports = SerialPort.GetPortNames(); // 获取所有可用的串口端口    comBox1.Items.AddRange(ports); // 将可用的端口添加到comBox1中    // 串口状态更改事件处理程序    SerialPort.SerialPinChangedEventHandler pinChangedHandler = new SerialPort.SerialPinChangedEventHandler(SerialPort_PinChanged);    SerialPort.DataReceivedEventHandler dataReceivedHandler = new SerialPort.DataReceivedEventHandler(SerialPort_DataReceived);    foreach (string portName in ports)    {        SerialPort serialPort = new SerialPort(portName);        serialPort.PinChanged += pinChangedHandler;        serialPort.DataReceived += dataReceivedHandler;        serialPort.Open();        serialPort.Close();    }}2. 添加两个事件处理程序,分别用于处理串口状态更改事件和接收到数据事件。// 处理串口状态更改事件private void SerialPort_PinChanged(object sender, SerialPinChangedEventArgs e){    SerialPort serialPort = (SerialPort)sender;    // 如果串口打开,则重新获取可用的串口端口    if (serialPort.IsOpen)    {        string[] ports = SerialPort.GetPortNames();        comBox1.Items.Clear();        comBox1.Items.AddRange(ports);    }}// 处理接收到数据事件private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){    // 在这里处理接收到的数据}3. 在Form的Activated事件中,添加一个事件处理程序来处理串口状态更改事件。这是为了在程序已经打开的情况下,当用户切换回上位机软件时能够刷新可用的串口列表。private void Form1_Activated(object sender, EventArgs e){    comBox1.DroppedDown = true;}现在,当程序加载时会获取可用的串口并显示在下拉comBox1中。当串口状态发生更改时,会自动更新可用的串口列表。同时,当用户切换回上位机软件时,也会自动刷新可用的串口列表。希望对你有所帮助!

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2024-3-8 23:47:32 | 显示全部楼层
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.Windows.Forms;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace 串口数据显示
{
    public partial class Form1 : Form
    {
        private SerialPort serialPort = null;
        private bool isSerialPortOpen = false;


        public Form1()
        {
            InitializeComponent();

            this.comboBox1.DropDown += new System.EventHandler(this.comboBox1_DropDown);
            this.button1.Click += new System.EventHandler(this.button1_Click);
            this.button2.Click += new System.EventHandler(this.button2_Click);
            this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing);
        }
        private void comboBox1_DropDown(object sender, EventArgs e)
        {
            string[] ports = SerialPort.GetPortNames();
            comboBox1.Items.Clear();
            foreach (string port in ports)
            {
                comboBox1.Items.Add(port);
            }
            if (comboBox1.Items.Count > 0)
            {
                comboBox1.SelectedIndex = 0;
            }
        }
        private void button1_Click(object sender, EventArgs e)
        {
            if (isSerialPortOpen)
            {
                // 如果串口已打开,则关闭串口
                if (serialPort != null && serialPort.IsOpen)
                {
                    serialPort.Close();
                    serialPort.Dispose();
                }

                isSerialPortOpen = false;
                button1.Text = "打开";
            }
            else
            {
                // 如果串口未打开,则打开串口
                try
                {
                    if (serialPort == null)
                    {
                        serialPort = new SerialPort();
                    }

                    if (!serialPort.IsOpen && comboBox1.SelectedItem != null)
                    {
                        serialPort.PortName = comboBox1.SelectedItem.ToString();
                        serialPort.BaudRate = 115200;
                        serialPort.Parity = Parity.None;
                        serialPort.StopBits = StopBits.One;
                        serialPort.DataBits = 8;
                        serialPort.Handshake = Handshake.None;

                        serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
                        
                        serialPort.Open();

                        isSerialPortOpen = true;
                        button1.Text = "关闭";
                    }
                    else
                    {
                        MessageBox.Show("请选择一个串口或串口已经打开");
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("打开串口时出错: " + ex.Message);

                    if (serialPort != null)
                    {
                        serialPort.Close();
                        serialPort.Dispose();
                    }
                }
            }
        }
        


        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                serialPort.Close();
                serialPort.Dispose();
            }
        }

        private void button3_Click(object sender, EventArgs e)
        {
            textBox1.Clear();
            textBox2.Clear();
            textBox3.Clear();
            textBox4.Clear();
            textBox5.Clear();
        }

        private void button4_Click(object sender, EventArgs e)
        {
            if (isSerialPortOpen)
            {
                try
                {
                    // 定义要发送的16进制数据  
                    byte[] sendData = { 0xFF, 0x99, 0x01, 0x00, 0x9A, 0xFE };

                    // 将发送的字节数组转换为字符串,方便显示在textBox1中  
                    string sendStr = BitConverter.ToString(sendData).Replace("-", " ");

                    // 在textBox1中显示发送的数据  
                    textBox1.AppendText("发送数据: " + sendStr + "\r\n");

                    // 通过串口发送数据  
                    serialPort.Write(sendData, 0, sendData.Length);
                }
                catch (Exception ex)
                {
                    // 显示发送数据时发生的错误  
                    MessageBox.Show("发送数据时出错: " + ex.Message);
                }
            }
            else
            {
                // 如果串口未打开,则提示用户先打开串口  
                MessageBox.Show("请先打开串口");
            }
        }

        private void button5_Click(object sender, EventArgs e)
        {
            if (isSerialPortOpen)
            {
                try
                {
                    // 定义要发送的16进制数据  
                    byte[] sendData = { 0xFF, 0x33, 0x01, 0x00, 0x34, 0xFE };

                    // 将发送的字节数组转换为字符串,方便显示在textBox1中  
                    string sendStr = BitConverter.ToString(sendData).Replace("-", " ");

                    // 在textBox1中显示发送的数据  
                    textBox1.AppendText("发送数据: " + sendStr + "\r\n");

                    // 通过串口发送数据  
                    serialPort.Write(sendData, 0, sendData.Length);
                }
                catch (Exception ex)
                {
                    // 显示发送数据时发生的错误  
                    MessageBox.Show("发送数据时出错: " + ex.Message);
                }
            }
            else
            {
                // 如果串口未打开,则提示用户先打开串口  
                MessageBox.Show("请先打开串口");
            }
        }

        private void button6_Click(object sender, EventArgs e)
        {
            if (isSerialPortOpen)
            {
                try
                {
                    // 定义要发送的16进制数据  
                    byte[] sendData = { 0xFF, 0x99, 0x02, 0x00, 0x9B, 0xFE };

                    // 将发送的字节数组转换为字符串,方便显示在textBox1中  
                    string sendStr = BitConverter.ToString(sendData).Replace("-", " ");

                    // 在textBox1中显示发送的数据  
                    textBox1.AppendText("发送数据: " + sendStr + "\r\n");

                    // 通过串口发送数据  
                    serialPort.Write(sendData, 0, sendData.Length);
                }
                catch (Exception ex)
                {
                    // 显示发送数据时发生的错误  
                    MessageBox.Show("发送数据时出错: " + ex.Message);
                }
            }
            else
            {
                // 如果串口未打开,则提示用户先打开串口  
                MessageBox.Show("请先打开串口");
            }
        }

        private void button7_Click(object sender, EventArgs e)
        {
            if (isSerialPortOpen)
            {
                try
                {
                    // 定义要发送的16进制数据  
                    byte[] sendData = { 0xFF, 0x33, 0x02, 0x00, 0x35, 0xFE };

                    // 将发送的字节数组转换为字符串,方便显示在textBox1中  
                    string sendStr = BitConverter.ToString(sendData).Replace("-", " ");

                    // 在textBox1中显示发送的数据  
                    textBox1.AppendText("发送数据: " + sendStr + "\r\n");

                    // 通过串口发送数据  
                    serialPort.Write(sendData, 0, sendData.Length);
                }
                catch (Exception ex)
                {
                    // 显示发送数据时发生的错误  
                    MessageBox.Show("发送数据时出错: " + ex.Message);
                }
            }
            else
            {
                // 如果串口未打开,则提示用户先打开串口  
                MessageBox.Show("请先打开串口");
            }
        }

        // 定义 DataReceivedHandler 方法  
        private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
        {
            SerialPort sp = (SerialPort)sender;
            string indata = sp.ReadExisting();

            if (indata.StartsWith(""))
            {
                string[] dataParts = indata.Split(' ');
                if (dataParts.Length >= 5)
                {
                    UpdateTextBoxes(dataParts);
                }
            }
        }

        // 另一个方法来更新文本框,以避免代码重复  
        private void UpdateTextBoxes(string[] dataParts)
        {
            if (textBox2.InvokeRequired)
            {
                textBox2.Invoke(new MethodInvoker(delegate { textBox2.Text = dataParts[1]; }));
            }
            else
            {
                textBox2.Text = dataParts[1];
            }

            if (textBox3.InvokeRequired)
            {
                textBox3.Invoke(new MethodInvoker(delegate { textBox3.Text = dataParts[2]; }));
            }
            else
            {
                textBox3.Text = dataParts[2];
            }

            if (textBox4.InvokeRequired)
            {
                textBox4.Invoke(new MethodInvoker(delegate { textBox4.Text = dataParts[3]; }));
            }
            else
            {
                textBox4.Text = dataParts[3];
            }

            if (textBox5.InvokeRequired)
            {
                textBox5.Invoke(new MethodInvoker(delegate { textBox5.Text = dataParts[4]; }));
            }
            else
            {
                textBox5.Text = dataParts[4];
            }
        }

        private void button8_Click(object sender, EventArgs e)
        {
            if (isSerialPortOpen)
            {
                try
                {
                    // 定义要发送的字符串  
                    string sendStr = "*1 2050 2121 510 004 ";

                    // 将字符串转换为字节数组  
                    byte[] sendData = Encoding.ASCII.GetBytes(sendStr);

                    // 添加发送的字符串到 textBox1 中  
                    textBox1.AppendText(sendStr + "\r\n");

                    // 发送数据到串口  
                    serialPort.Write(sendData, 0, sendData.Length);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("发送数据时出错: " + ex.Message);
                }
            }
            else
            {
                MessageBox.Show("请先打开串口");
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (isSerialPortOpen)
            {
                try
                {
                    // 定义要发送的字符串  
                    string sendStr = "*1 2048 3000 525 400";

                    // 将字符串转换为字节数组  
                    byte[] sendData = Encoding.ASCII.GetBytes(sendStr);

                    // 添加发送的字符串到 textBox1 中  
                    textBox1.AppendText(sendStr + "\r\n");

                    // 发送数据到串口  
                    serialPort.Write(sendData, 0, sendData.Length);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("发送数据时出错: " + ex.Message);
                }
            }
            else
            {
                MessageBox.Show("请先打开串口");
            }
        }
    }
}
@FishC 我串口发送数据的时候,我的DataReceivedHandler函数,并没有触发到。请帮我检查一下代码不合理的地方。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-8 23:48:04 | 显示全部楼层
XYZ_XYZ 发表于 2024-03-08 23:47
using System;
using System.Collections.Generic;
...


在您的代码中,将DataReceivedHandler方法与DataReceived事件绑定的部分有问题。在您的button1_Click方法中,您应该添加以下代码:

  1. serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
复制代码


这样,当串口接收到数据时,DataReceived事件将触发DataReceivedHandler方法。

另外,在DataReceivedHandler方法中,您使用ReadExisting方法来获取接收到的数据。但是,ReadExisting方法将返回缓冲区中所有的字节,并且不保证接收到的数据长度为您期望的格式。建议您使用ReadLine或ReadTo方法来读取特定的结束字符或字符串,以确保接收到完整的数据。

下面是您修改后的代码:

  1. using System;
  2. using System.IO.Ports;
  3. using System.Windows.Forms;

  4. namespace 串口数据显示
  5. {
  6.     public partial class Form1 : Form
  7.     {
  8.         private SerialPort serialPort = null;
  9.         private bool isSerialPortOpen = false;

  10.         public Form1()
  11.         {
  12.             InitializeComponent();

  13.             this.comboBox1.DropDown += new EventHandler(this.comboBox1_DropDown);
  14.             this.button1.Click += new EventHandler(this.button1_Click);
  15.             this.FormClosing += new FormClosingEventHandler(this.Form1_FormClosing);
  16.             
  17.             this.serialPort = new SerialPort();
  18.             this.serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
  19.         }

  20.         private void comboBox1_DropDown(object sender, EventArgs e)
  21.         {
  22.             string[] ports = SerialPort.GetPortNames();
  23.             comboBox1.Items.Clear();
  24.             foreach (string port in ports)
  25.             {
  26.                 comboBox1.Items.Add(port);
  27.             }
  28.             if (comboBox1.Items.Count > 0)
  29.             {
  30.                 comboBox1.SelectedIndex = 0;
  31.             }
  32.         }

  33.         private void button1_Click(object sender, EventArgs e)
  34.         {
  35.             if (isSerialPortOpen)
  36.             {
  37.                 // 如果串口已打开,则关闭串口
  38.                 if (serialPort != null && serialPort.IsOpen)
  39.                 {
  40.                     serialPort.Close();
  41.                     serialPort.Dispose();
  42.                 }

  43.                 isSerialPortOpen = false;
  44.                 button1.Text = "打开";
  45.             }
  46.             else
  47.             {
  48.                 // 如果串口未打开,则打开串口
  49.                 try
  50.                 {
  51.                     if (!serialPort.IsOpen && comboBox1.SelectedItem != null)
  52.                     {
  53.                         serialPort.PortName = comboBox1.SelectedItem.ToString();
  54.                         serialPort.BaudRate = 115200;
  55.                         serialPort.Parity = Parity.None;
  56.                         serialPort.StopBits = StopBits.One;
  57.                         serialPort.DataBits = 8;
  58.                         serialPort.Handshake = Handshake.None;

  59.                         serialPort.Open();

  60.                         isSerialPortOpen = true;
  61.                         button1.Text = "关闭";
  62.                     }
  63.                     else
  64.                     {
  65.                         MessageBox.Show("请选择一个串口或串口已经打开");
  66.                     }
  67.                 }
  68.                 catch (Exception ex)
  69.                 {
  70.                     MessageBox.Show("打开串口时出错: " + ex.Message);

  71.                     if (serialPort != null)
  72.                     {
  73.                         serialPort.Close();
  74.                         serialPort.Dispose();
  75.                     }
  76.                 }
  77.             }
  78.         }

  79.         private void Form1_FormClosing(object sender, FormClosingEventArgs e)
  80.         {
  81.             if (serialPort != null && serialPort.IsOpen)
  82.             {
  83.                 serialPort.Close();
  84.                 serialPort.Dispose();
  85.             }
  86.         }

  87.         // 定义 DataReceivedHandler 方法  
  88.         private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
  89.         {
  90.             SerialPort sp = (SerialPort)sender;
  91.             string indata = sp.ReadLine();

  92.             // 处理接收到的数据
  93.             if (indata.StartsWith(""))
  94.             {
  95.                 string[] dataParts = indata.Split(' ');
  96.                 if (dataParts.Length >= 5)
  97.                 {
  98.                     UpdateTextBoxes(dataParts);
  99.                 }
  100.             }
  101.         }

  102.         // 另一个方法来更新文本框,以避免代码重复  
  103.         private void UpdateTextBoxes(string[] dataParts)
  104.         {
  105.             if (textBox2.InvokeRequired)
  106.             {
  107.                 textBox2.Invoke(new MethodInvoker(delegate { textBox2.Text = dataParts[1]; }));
  108.             }
  109.             else
  110.             {
  111.                 textBox2.Text = dataParts[1];
  112.             }

  113.             if (textBox3.InvokeRequired)
  114.             {
  115.                 textBox3.Invoke(new MethodInvoker(delegate { textBox3.Text = dataParts[2]; }));
  116.             }
  117.             else
  118.             {
  119.                 textBox3.Text = dataParts[2];
  120.             }

  121.             if (textBox4.InvokeRequired)
  122.             {
  123.                 textBox4.Invoke(new MethodInvoker(delegate { textBox4.Text = dataParts[3]; }));
  124.             }
  125.             else
  126.             {
  127.                 textBox4.Text = dataParts[3];
  128.             }

  129.             if (textBox5.InvokeRequired)
  130.             {
  131.                 textBox5.Invoke(new MethodInvoker(delegate { textBox5.Text = dataParts[4]; }));
  132.             }
  133.             else
  134.             {
  135.                 textBox5.Text = dataParts[4];
  136.             }
  137.         }

  138.         // 其他按钮事件处理方法...
  139.     }
  140. }
复制代码


希望这可以解决您的问题!如果还有其他问题,请随时提问。

以上回复来自 FishC AI 小助理,如未能正确解答您的问题,请继续追问。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-4-30 22:44

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表