鱼C论坛

 找回密码
 立即注册
查看: 1128|回复: 34

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

[复制链接]
发表于 2024-1-28 14:36:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
用C语言写一个串口收发的上位机。执行文件是.exe文件@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2024-1-28 14:37:31 | 显示全部楼层
首先,你需要选择一个可用的串口库来完成串口收发功能。在C语言中,常用的串口库有Windows API、libserialport等。在这里,我使用Windows API来演示。

下面是一个简单的例子,展示如何通过串口与设备进行收发数据。
#include <stdio.h>
#include <windows.h>

int main()
{
    HANDLE hSerial;
    DCB dcbSerialParams = { 0 };
    COMMTIMEOUTS timeouts = { 0 };
    char port[] = "\\\\.\\COM1"; // 根据实际的串口号修改

    // 打开串口
    hSerial = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hSerial == INVALID_HANDLE_VALUE) {
        printf("无法打开串口\n");
        return 1;
    }

    // 配置串口参数
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams)) {
        printf("无法获取串口参数\n");
        CloseHandle(hSerial);
        return 1;
    }
    dcbSerialParams.BaudRate = CBR_9600; // 波特率设置为9600bps
    dcbSerialParams.ByteSize = 8; // 数据位设置为8位
    dcbSerialParams.StopBits = ONESTOPBIT; // 停止位设置为1位停止位
    dcbSerialParams.Parity = NOPARITY; // 校验位设置为无校验
    if (!SetCommState(hSerial, &dcbSerialParams)){
        printf("无法设置串口参数\n");
        CloseHandle(hSerial);
        return 1;
    }

    // 设置串口读写超时时间
    timeouts.ReadIntervalTimeout = 50;
    timeouts.ReadTotalTimeoutConstant = 50;
    timeouts.ReadTotalTimeoutMultiplier = 10;
    timeouts.WriteTotalTimeoutConstant = 50;
    timeouts.WriteTotalTimeoutMultiplier = 10;
    if (!SetCommTimeouts(hSerial, &timeouts)) {
        printf("无法设置串口超时时间\n");
        CloseHandle(hSerial);
        return 1;
    }

    // 向串口发送数据
    char sendData[] = "Hello, Serial!";
    DWORD bytesWritten = 0;
    if (!WriteFile(hSerial, sendData, sizeof(sendData), &bytesWritten, NULL)) {
        printf("无法向串口发送数据\n");
        CloseHandle(hSerial);
        return 1;
    }
    printf("已发送数据:%s\n", sendData);

    // 从串口接收数据
    char recvData[32] = { 0 };
    DWORD bytesRead = 0;
    if (!ReadFile(hSerial, recvData, sizeof(recvData), &bytesRead, NULL)) {
        printf("无法从串口接收数据\n");
        CloseHandle(hSerial);
        return 1;
    }
    printf("已接收数据:%s\n", recvData);

    // 关闭串口
    CloseHandle(hSerial);

    return 0;
}

请注意,上述代码使用了Windows API中的串口相关函数。在运行之前,你需要根据实际的串口号修改`port[]`的值,并确保你的计算机上具有相应的串口设备。

这只是一个简单的示例,用于演示如何使用C语言进行串口收发的上位机控制。你可以根据自己的需求进行进一步的开发和扩展。希望对你有所帮助!

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

使用道具 举报

 楼主| 发表于 2024-1-28 14:46:00 | 显示全部楼层
FishC 发表于 2024-1-28 14:37
首先,你需要选择一个可用的串口库来完成串口收发功能。在C语言中,常用的串口库有Windows API、libserialp ...

请先设计出一个上位机窗口
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-1-28 14:47:18 | 显示全部楼层
XYZ_XYZ 发表于 2024-01-28 14:46
请先设计出一个上位机窗口


好的!首先,我们需要选择一个图形用户界面(GUI)库来创建上位机窗口。在C语言中,常用的GUI库有GTK、Qt等。在这里,我使用Qt来演示。下面是一个简单的例子,展示如何使用Qt创建一个上位机窗口。
#include <QApplication>#include <QWidget>#include <QVBoxLayout>#include <QLabel>#include <QPushButton>#include <QSerialPort>#include <QSerialPortInfo>class UpperComputer : public QWidget{    Q_OBJECTpublic:    explicit UpperComputer(QWidget *parent = nullptr) : QWidget(parent){        // 创建串口选择标签和下拉框        QLabel* labelSerialPort = new QLabel("选择串口:", this);        comboSerialPort = new QComboBox(this);        // 获取可用的串口列表        QList<QSerialPortInfo> serialPortList = QSerialPortInfo::availablePorts();        for(const auto& portInfo : serialPortList){            comboSerialPort->addItem(portInfo.portName());        }        // 创建发送按钮        QPushButton* sendButton = new QPushButton("发送", this);        connect(sendButton, &QPushButton::clicked, this, &UpperComputer::sendDataToSerialPort);        // 创建布局        QVBoxLayout* layout = new QVBoxLayout;        layout->addWidget(labelSerialPort);        layout->addWidget(comboSerialPort);        layout->addWidget(sendButton);        setLayout(layout);    }private slots:    void sendDataToSerialPort(){        // 获取选择的串口号        QString portName = comboSerialPort->currentText();        // 打开串口        QSerialPort serialPort(portName);        if(!serialPort.open(QIODevice::ReadWrite)){            qDebug() << "无法打开串口";            return;        }        // 向串口发送数据        QByteArray data = "Hello, Serial!";        serialPort.write(data);        qDebug() << "已发送数据:" << data;        // 关闭串口        serialPort.close();    }private:    QComboBox* comboSerialPort;};int main(int argc, char *argv[]){    QApplication app(argc, argv);    UpperComputer upperComputer;    upperComputer.show();    return app.exec();}#include "main.moc"
首先,你需要安装Qt并配置好环境。然后使用Qt Creator创建一个新的Qt Widgets项目,将上述代码复制到项目中,并编译运行。这段代码创建了一个简单的上位机窗口,其中包含一个标签用于选择串口,一个下拉框显示可用的串口列表,以及一个发送按钮。当点击发送按钮时,会向选择的串口发送数据(在代码中是"Hello, Serial!")。请注意,你可能需要根据你的环境进行必要的配置和修改。希望对你有帮助!

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

使用道具 举报

 楼主| 发表于 2024-3-4 21:35:27 | 显示全部楼层
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;

namespace 串口数据显示
{
    public partial class Form1 : Form
    {
        private SerialPort serialPort = null;// 初始化为null,以便我们可以检查它是否已被实例化


        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);
        }

        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)
        {
            try
            {
                if (serialPort == null)
                {
                    serialPort = new SerialPort(); // 创建SerialPort对象实例  
                }

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

                    serialPort.Open(); // 现在打开串口  
                    MessageBox.Show("串口已打开");
                }
                else
                {
                    MessageBox.Show("请选择一个串口或串口已经打开");
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show("打开串口时出错: " + ex.Message);
                if (serialPort != null)
                {
                    serialPort.Close(); // 尝试关闭串口,以便下次可以尝试重新打开  
                }
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                serialPort.Close();
                serialPort.Dispose();
                MessageBox.Show("串口已关闭");
            }
        }
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                serialPort.Close();
                serialPort.Dispose();
            }
        }
    }
}
这是我的C#代码,请简单的介绍一下@FishC
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-4 21:35:49 | 显示全部楼层
XYZ_XYZ 发表于 2024-03-04 21:35
using System;
using System.Collections.Generic;
...


这是一个简单的串口数据显示程序。让我来解释一下代码的功能。

首先,在命名空间“串口数据显示”中,我们定义了一个名为"Form1"的窗体类。这个类继承自Windows Forms的Form类,表示一个应用程序窗体。

在Form1类中,我们声明了一个私有变量"serialPort",用来表示串口对象。并将其初始化为null,以便我们可以检查它是否已经实例化。

接下来,在Form1类的构造函数中,我们完成了一些初始化工作。我们为comboBox1控件的DropDown事件和button1、button2按钮的Click事件注册了事件处理程序。

在comboBox1的DropDown事件处理程序中,我们通过SerialPort.GetPortNames()方法获取当前计算机上所有可用的串口号,并将它们添加到comboBox1控件中进行选择。

在button1的Click事件处理程序中,当用户点击了“打开串口”按钮时,我们首先判断serialPort对象是否为空,并创建一个新的SerialPort对象实例。然后,我们根据用户选择的串口号和一些默认设置(波特率、校验位、停止位、数据位、握手方式),对serialPort对象进行配置。最后,我们通过调用Open方法打开串口,并显示一个提示对话框告知用户串口已打开。

button2的Click事件处理程序中,当用户点击了“关闭串口”按钮时,我们判断serialPort对象是否为空且串口是否处于打开状态,然后调用Close方法关闭串口,并通过调用Dispose方法释放资源,最后显示一个提示对话框告知用户串口已关闭。

最后,在Form1类中,我们还定义了一个MainForm_FormClosing事件处理程序,当窗体即将关闭时,如果串口已打开,则先关闭串口并释放资源。

这就是这个程序的主要功能。当用户在comboBox1中选择了一个串口号并点击“打开串口”按钮后,就可以打开串口并开始接收来自串口的数据。当用户点击“关闭串口”按钮时,程序会关闭串口并停止接收数据。

希望这段解释对你有帮助!如果还有其他问题,请随时提问。

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

使用道具 举报

 楼主| 发表于 2024-3-4 21:42:06 | 显示全部楼层
FishC 发表于 2024-3-4 21:35
这是一个简单的串口数据显示程序。让我来解释一下代码的功能。

首先,在命名空间“串口数据显示”中 ...

我想将两个按键合并成一个按键,应该怎么写代码。功能是点击button1,串口打开,button1 的 text 显示打开;再点击button1,串口关闭,button1 的 text 显示关闭。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-4 21:42:36 | 显示全部楼层
XYZ_XYZ 发表于 2024-03-04 21:42
我想将两个按键合并成一个按键,应该怎么写代码。功能 ...


要将两个按钮合并成一个按钮,并根据串口的状态来切换按钮的文本,你可以使用一个标志变量来表示串口的状态。当串口关闭时,将标志变量设置为false;当串口打开时,将标志变量设置为true。然后,在按钮的Click事件处理程序中,根据标志变量的值来执行相应的操作并更新按钮的文本。以下是一个示例代码:
bool isSerialPortOpen = false; // 标志变量,表示串口是否已打开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 = 9600;                serialPort.Parity = Parity.None;                serialPort.StopBits = StopBits.One;                serialPort.DataBits = 8;                serialPort.Handshake = Handshake.None;                serialPort.Open();                MessageBox.Show("串口已打开");                isSerialPortOpen = true;                button1.Text = "关闭";            }            else{                MessageBox.Show("请选择一个串口或串口已经打开");            }        }        catch (Exception ex){            MessageBox.Show("打开串口时出错: " + ex.Message);            if (serialPort != null){                serialPort.Close();                serialPort.Dispose();            }        }    }}
在这个示例代码中,我添加了一个名为"isSerialPortOpen"的标志变量,并将其初始化为false。在按钮的Click事件处理程序中,如果isSerialPortOpen为true,则表示串口已打开,那么执行关闭串口的操作,并将isSerialPortOpen设置为false,同时将按钮的文本设置为"打开";如果isSerialPortOpen为false,则表示串口未打开,那么执行打开串口的操作,并将isSerialPortOpen设置为true,同时将按钮的文本设置为"关闭"。希望这个示例代码能满足你的需求!如果还有其他问题,请随时提问。

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

使用道具 举报

 楼主| 发表于 2024-3-4 21:47:59 | 显示全部楼层
FishC 发表于 2024-3-4 21:42
要将两个按钮合并成一个按钮,并根据串口的状态来切换按钮的文本,你可以使用一个标志变量来表示串口的 ...

请重新整理一下代码格式
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-4 21:48:20 | 显示全部楼层
XYZ_XYZ 发表于 2024-03-04 21:47
请重新整理一下代码格式


当然!以下是重新整理过的代码,以提高可读性:
bool isSerialPortOpen = false; // 标志变量,表示串口是否已打开

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 = 9600;
                serialPort.Parity = Parity.None;
                serialPort.StopBits = StopBits.One;
                serialPort.DataBits = 8;
                serialPort.Handshake = Handshake.None;
                serialPort.Open();
                
                MessageBox.Show("串口已打开");
                isSerialPortOpen = true;
                button1.Text = "关闭";
            }
            else
            {
                MessageBox.Show("请选择一个串口或串口已经打开");
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("打开串口时出错: " + ex.Message);
            
            if (serialPort != null)
            {
                serialPort.Close();
                serialPort.Dispose();
            }
        }
    }
}
这段代码包含了一个名为"isSerialPortOpen"的标志变量,用于表示串口的状态。在按钮的Click事件处理程序中,根据isSerialPortOpen的值来执行相应的操作,并更新按钮的文本。希望这样更易于阅读和理解!如果还有其他问题,请随时提问。

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

使用道具 举报

 楼主| 发表于 2024-3-4 21:58:19 | 显示全部楼层
FishC 发表于 2024-3-4 21:48
当然!以下是重新整理过的代码,以提高可读性:

这段代码包含了一个名为"isSerialPortOpen"的标志变 ...

我想个button1加一个功能,当串口打开时,按键显示绿色。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-4 21:58:36 | 显示全部楼层
XYZ_XYZ 发表于 2024-03-04 21:58
我想个button1加一个功能,当串口打开时,按键显示绿 ...


好的!你可以使用以下代码在串口打开时将按钮的背景颜色设置为绿色:private void button1_Click(object sender, EventArgs e){    if (isSerialPortOpen)    {        // 如果串口已打开,则关闭串口        if (serialPort != null && serialPort.IsOpen)        {            serialPort.Close();            serialPort.Dispose();        }                isSerialPortOpen = false;        button1.Text = "打开";        button1.BackColor = DefaultBackColor; // 恢复默认背景颜色    }    else    {        // 如果串口未打开,则打开串口        try        {            if (serialPort == null)            {                serialPort = new SerialPort();            }                        if (!serialPort.IsOpen && comboBox1.SelectedItem != null)            {                serialPort.PortName = comboBox1.SelectedItem.ToString();                serialPort.BaudRate = 9600;                serialPort.Parity = Parity.None;                serialPort.StopBits = StopBits.One;                serialPort.DataBits = 8;                serialPort.Handshake = Handshake.None;                serialPort.Open();                                MessageBox.Show("串口已打开");                isSerialPortOpen = true;                button1.Text = "关闭";                button1.BackColor = Color.Green; // 设置背景颜色为绿色            }            else            {                MessageBox.Show("请选择一个串口或串口已经打开");            }        }        catch (Exception ex)        {            MessageBox.Show("打开串口时出错: " + ex.Message);                        if (serialPort != null)            {                serialPort.Close();                serialPort.Dispose();            }        }    }}在这段代码中,我在按钮的Click事件处理程序中添加了`button1.BackColor = Color.Green;`这一行代码。当串口打开时,按钮的背景颜色将被设置为绿色。希望这个功能满足了你的需求!

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

使用道具 举报

 楼主| 发表于 2024-3-4 21:59:15 | 显示全部楼层
FishC 发表于 2024-3-4 21:58
好的!你可以使用以下代码在串口打开时将按钮的背景颜色设置为绿色:private void button1_Click(objec ...

请整理代码格式
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-4 21:59:27 | 显示全部楼层


当然!以下是经过整理的代码,以更好地展示可读性:
void button1_Click(object sender, EventArgs e)
{
    if (isSerialPortOpen)
    {
        // 如果串口已打开,则关闭串口
        if (serialPort != null && serialPort.IsOpen)
        {
            serialPort.Close();
            serialPort.Dispose();
        }
        
        isSerialPortOpen = false;
        button1.Text = "打开";
        button1.BackColor = DefaultBackColor; // 恢复默认背景颜色
    }
    else
    {
        // 如果串口未打开,则打开串口
        try
        {
            if (serialPort == null)
            {
                serialPort = new SerialPort();
            }
            
            if (!serialPort.IsOpen && comboBox1.SelectedItem != null)
            {
                serialPort.PortName = comboBox1.SelectedItem.ToString();
                serialPort.BaudRate = 9600;
                serialPort.Parity = Parity.None;
                serialPort.StopBits = StopBits.One;
                serialPort.DataBits = 8;
                serialPort.Handshake = Handshake.None;
                
                serialPort.Open();
                MessageBox.Show("串口已打开");
                
                isSerialPortOpen = true;
                button1.Text = "关闭";
                button1.BackColor = Color.Green; // 设置背景颜色为绿色
            }
            else
            {
                MessageBox.Show("请选择一个串口或串口已经打开");
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("打开串口时出错: " + ex.Message);
            
            if (serialPort != null)
            {
                serialPort.Close();
                serialPort.Dispose();
            }
        }
    }
}
通过以上整理,代码更加清晰易读。希望对你有所帮助!

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

使用道具 举报

 楼主| 发表于 2024-3-4 22:12:41 | 显示全部楼层
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;

namespace 串口数据显示
{
    public partial class Form1 : Form
    {
        private SerialPort serialPort = null;// 初始化为null,以便我们可以检查它是否已被实例化


        public Form1()
        {
            InitializeComponent();
            this.comboBox1.DropDown += new System.EventHandler(this.comboBox1_DropDown);
            this.button1.Click += new System.EventHandler(this.button1_Click);
        }

        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;
            }
        }

        bool isSerialPortOpen = false; // 标志变量,表示串口是否已打开

        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.Open();
                        //MessageBox.Show("串口已打开");

                        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();
            }
        }
    }
}
我想要在我的代码基础上添加一个按键button2,并按下button2,实现串口发送0x99的功能。请完善代码,并规范代码格式。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-4 22:13:12 | 显示全部楼层
XYZ_XYZ 发表于 2024-03-04 22:12
using System;
using System.Collections.Generic;
...


好的!以下是在你的代码基础上添加了button2按键,并实现了串口发送0x99功能的完整代码,并进行了格式规范化: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;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.Open();                        isSerialPortOpen = true;                        button1.Text = "关闭";                    }                    else                    {                        MessageBox.Show("请选择一个串口或串口已经打开");                    }                }                catch (Exception ex)                {                    MessageBox.Show("打开串口时出错: " + ex.Message);                    if (serialPort != null)                    {                        serialPort.Close();                        serialPort.Dispose();                    }                }            }        }        private void button2_Click(object sender, EventArgs e)        {            if (isSerialPortOpen)            {                try                {                    // 发送0x99给串口                    byte[] sendData = { 0x99 };                    serialPort.Write(sendData, 0, sendData.Length);                }                catch (Exception ex)                {                    MessageBox.Show("发送数据时出错: " + ex.Message);                }            }            else            {                MessageBox.Show("请先打开串口");            }        }        private void Form1_FormClosing(object sender, FormClosingEventArgs e)        {            if (serialPort != null && serialPort.IsOpen)            {                serialPort.Close();                serialPort.Dispose();            }        }    }}希望这段代码满足了你的需求!如果还有其他问题,请随时提问。

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

使用道具 举报

 楼主| 发表于 2024-3-4 22:14:39 | 显示全部楼层
FishC 发表于 2024-3-4 22:13
好的!以下是在你的代码基础上添加了button2按键,并实现了串口发送0x99功能的完整代码,并进行了格式 ...

请规范代码格式
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-4 22:15:05 | 显示全部楼层


以下是格式规范化后的代码: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;

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.Open();

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

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

        private void button2_Click(object sender, EventArgs e)
        {
            if (isSerialPortOpen)
            {
                try
                {
                    // 发送0x99给串口
                    byte[] sendData = { 0x99 };
                    serialPort.Write(sendData, 0, sendData.Length);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("发送数据时出错: " + ex.Message);
                }
            }
            else
            {
                MessageBox.Show("请先打开串口");
            }
        }

        private void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serialPort != null && serialPort.IsOpen)
            {
                serialPort.Close();
                serialPort.Dispose();
            }
        }
    }
}希望这次的格式满足了你的要求!如果还有其他问题,请随时提问。

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

使用道具 举报

 楼主| 发表于 2024-3-4 22:21:46 | 显示全部楼层
FishC 发表于 2024-3-4 22:15
以下是格式规范化后的代码:using System;
using System.Collections.Generic;
using System.Compone ...

请在加上串口接收的功能
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2024-3-4 22:23:20 | 显示全部楼层
XYZ_XYZ 发表于 2024-03-04 22:21
请在加上串口接收的功能


以下是加上串口接收功能的代码示例:
#include <stdio.h>
#include <Windows.h>

#define MAX_BUF_SIZE 255

int main() {
    HANDLE hSerial;
    DCB dcbSerialParams = { 0 };
    COMMTIMEOUTS timeouts = { 0 };
    char port[] = "\\\\.\\COM1"; // 根据实际的串口号修改

    // 打开串口
    hSerial = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
    if (hSerial == INVALID_HANDLE_VALUE) {
        printf("无法打开串口\n");
        return 1;
    }

    // 配置串口参数
    dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
    if (!GetCommState(hSerial, &dcbSerialParams)) {
        printf("无法获取串口参数\n");
        CloseHandle(hSerial);
        return 1;
    }
    dcbSerialParams.BaudRate = CBR_9600; // 波特率设置为9600bps
    dcbSerialParams.ByteSize = 8; // 数据位设置为8位
    dcbSerialParams.StopBits = ONESTOPBIT; // 停止位设置为1位停止位
    dcbSerialParams.Parity = NOPARITY; // 校验位设置为无校验
    if (!SetCommState(hSerial, &dcbSerialParams)){
        printf("无法设置串口参数\n");
        CloseHandle(hSerial);
        return 1;
    }

    // 设置串口读写超时时间
    timeouts.ReadIntervalTimeout = 50;
    timeouts.ReadTotalTimeoutConstant = 50;
    timeouts.ReadTotalTimeoutMultiplier = 10;
    timeouts.WriteTotalTimeoutConstant = 50;
    timeouts.WriteTotalTimeoutMultiplier = 10;
    if (!SetCommTimeouts(hSerial, &timeouts)) {
        printf("无法设置串口超时时间\n");
        CloseHandle(hSerial);
        return 1;
    }

    // 向串口发送数据
    char sendData[] = "Hello, Serial!";
    DWORD bytesWritten = 0;
    if (!WriteFile(hSerial, sendData, sizeof(sendData), &bytesWritten, NULL)) {
        printf("无法向串口发送数据\n");
        CloseHandle(hSerial);
        return 1;
    }
    printf("已发送数据:%s\n", sendData);

    // 从串口接收数据
    char recvData[MAX_BUF_SIZE + 1] = { 0 };
    DWORD bytesRead = 0;
    if (!ReadFile(hSerial, recvData, MAX_BUF_SIZE, &bytesRead, NULL)) {
        printf("无法从串口接收数据\n");
        CloseHandle(hSerial);
        return 1;
    }
    recvData[bytesRead] = '\0'; // 添加字符串结束符
    printf("已接收数据:%s\n", recvData);

    // 关闭串口
    CloseHandle(hSerial);
    return 0;
}

这个示例代码演示了如何通过C语言进行串口发送和接收数据的操作。你可以根据实际情况对代码进行修改和扩展。

希望对你有所帮助!如有其他问题,请随时提问。

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

使用道具 举报

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

本版积分规则

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

GMT+8, 2024-11-24 00:13

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

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