当前位置: 首页 > news >正文

C# SerialPort 使用详解

总目录


前言

在工业控制、物联网、嵌入式开发等领域,串口通信(Serial Port Communication)是连接串行设备(如条码扫描器、GPS接收器等)与计算机的重要手段。C# 提供了内置的 SerialPort 类,简化了串口开发的流程。本文将详细介绍如何在C#中使用SerialPort类进行串口通信。


一、什么是 SerialPort?

1. 定义

System.IO.Ports.SerialPort 类(简称 SerialPort)是 .NET 框架中用于串口通信的核心类,它提供了对串行端口的访问,允许我们进行数据的读写、配置串口参数以及处理事件等操作。

2. 串行通信简介

串口通信(Serial Communication)是通过单条数据线按顺序传输数据的通信方式,具有接线简单、成本低廉的特点。在工业控制、物联网设备、传感器等领域广泛应用,波特率范围常见为 9600 9600 9600 115200 115200 115200

  • 在工业自动化、嵌入式系统开发等场景中,串口通信(Serial Communication)仍是硬件交互的核心技术之一。
  • 串行通信是一种数据按位顺序传输的通信方式,常用于连接各种串行设备。
  • C# 通过 System.IO.Ports.SerialPort 类为开发者提供了简洁高效的串口操作接口,支持参数配置、数据读写及事件处理等功能。

3. SerialPort核心功能

  • 端口配置参数:波特率、数据位、校验位、停止位等。
  • 数据读写操作:同步或异步发送/接收数据。
  • 事件驱动通信:通过 DataReceived 事件实时响应数据到达。

4. 典型应用场景

  • 工业设备通信
  • 传感器数据采集
  • 嵌入式系统交互

二、常用的属性和方法

1. 常用属性

属性名类型/说明
PortNamestring 串口名称(如 COM1COM3)。
BaudRateint 波特率,表示数据传输速率。
常用的有9600192003840057600以及115200
ParityParity 奇偶校验类型
None无奇偶校验、Even偶检验、Odd奇检验。
DataBitsint 数据位数。
常见数据位为8位,如需要特别设置,还可设置位5位,6位,7位
StopBitsStopBits 停止位数
None 不使用停止位One 1个停止位、Two2个停止位、OnePointFive1.5个停止位)。
HandshakeHandshake 握手协议(如 NoneRequestToSendXOnXOff)。
EncodingEncoding 数据编码方式(如 Encoding.UTF8)。
ReadTimeoutint 读取操作超时时间(毫秒),默认为 InfiniteTimeout
WriteTimeoutint 写入操作超时时间(毫秒),默认为 InfiniteTimeout
IsOpenbool 表示串口是否已打开。
NewLinestring 定义行结束符(如 "\r\n"),用于 ReadLine()WriteLine()
DtrEnablebool 控制数据终端就绪(DTR)信号状态。
RtsEnablebool 控制请求发送(RTS)信号状态。
ReceivedBytesThresholdint 触发 DataReceived 事件的最小字节数。

2. 常用方法

方法名说明
Open()打开串口。
Close()关闭已打开的串口。
Read(byte[] buffer, int offset, int count)从串口读取指定字节数到缓冲区。
ReadByte()读取单个字节(返回 int,范围 0-255,失败返回 -1)。
ReadLine()读取一行数据,直到遇到 NewLine 定义的结束符。
ReadExisting()读取接收缓冲区中所有可用数据(不阻塞)。
Write(string text)写入字符串到串口(自动按 Encoding 编码)。
Write(byte[] buffer, int offset, int count)写入字节数组到串口。
DiscardInBuffer()清空输入缓冲区中的数据。
DiscardOutBuffer()清空输出缓冲区中的数据。

3. 常用事件

事件名说明
DataReceived当接收到数据且字节数达到 ReceivedBytesThreshold 时触发。
ErrorReceived当串口发生错误(如奇偶校验错误)时触发。

4. 其他重要属性(扩展)

属性名类型/说明
BytesToReadint 接收缓冲区中已接收的字节数。
BytesToWriteint 输出缓冲区中待发送的字节数。
ReadBufferSizeint 设置输入缓冲区大小(默认 4096)。
WriteBufferSizeint 设置输出缓冲区大小(默认 2048)。

三、SerialPort 基础

1. 添加命名空间引用

在使用SerialPort类之前,需要先添加对System.IO.Ports命名空间的引用:

using System.IO.Ports;

2. 初始化与参数配置

串口通信的核心是正确配置参数,确保与硬件设备匹配,否则通信失败。

1)方式1:构造函数

using System.IO.Ports;// 创建对象并指定端口名称(如COM3)
SerialPort serialPort = new SerialPort("COM3", 9600, Parity.None, 8, StopBits.One);

2)方式2:属性配置

// 可选:手动设置参数(适用于动态配置)
SerialPort serialPort = new SerialPort();
serialPort.PortName = "COM3";       // 端口号
serialPort.BaudRate = 9600;         // 波特率
serialPort.Parity = Parity.None;    // 校验位
serialPort.DataBits = 8;            // 数据位
serialPort.StopBits = StopBits.One; // 停止位

3. 打开与关闭串口

1)打开串口

在进行数据传输之前,需要打开串行端口:

serialPort.Open(); // 打开串口

优化一下:加上try catch 做异常处理

try 
{if (!serialPort.IsOpen){serialPort.Open();Console.WriteLine("端口已打开");}
}
catch (Exception ex)
{Console.WriteLine($"打开失败:{ex.Message}");
}

2)关闭串口

数据传输完成后,应及时关闭串行端口。务必在程序退出前调用Close

serialPort.Close(); // 关闭端口

优化一下:加上try catch 做异常处理

try 
{if (serialPort.IsOpen){// 关闭端口serialPort.Close();Console.WriteLine("端口已关闭");// 销毁serialPort对象serialPort.Dispose();}
}
catch (Exception ex)
{Console.WriteLine($"关闭失败:{ex.Message}");
}

4. 读取和写入数据

1)写入数据

▶ 写入字符串数据
  • 使用Write()方法:将指定的字符串写入串行端口。
  • 使用WriteLine方法:将指定的字符串和 SerialPort.NewLine 值写入串行端口。
serialPort.Write("Hello, Serial!");// 自动添加换行符:发送字符串并添加换行符(WriteLine)
serialPort.WriteLine("Hello, Serial Port!");
▶ 写入字节流(字节数组)数据
// 发送字节数组
byte[] data = Encoding.UTF8.GetBytes("Test Data");
serialPort.Write(data, 0, data.Length);byte[] data = { 0x01, 0xFF, 0xAB }; // 十六进制数据
serialPort.Write(data, 0, data.Length); // 发送字节

2)读取数据

可以通过Read()ReadLine()等方法从串口读取数据。

// 读取指定字节数
byte[] buffer = new byte[1024];
int bytesRead = serialPort.Read(buffer, 0, buffer.Length);
string received = Encoding.UTF8.GetString(buffer, 0, bytesRead);// 读取一行数据(依赖 NewLine 配置)
string line = serialPort.ReadLine();

5. 处理数据接收事件

通过 DataReceived 事件实时接收串口数据。当有数据到达时,DataReceived事件会被触发。可以通过注册该事件来实时处理接收到的数据:

1)使用方式1

// 注册 DataReceived 事件
serialPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{SerialPort sp = (SerialPort)sender;string received = sp.ReadExisting(); // 读取所有可用数据Console.WriteLine($"Received: {received}");
}

2)使用方式2

serialPort.DataReceived += SerialPort_DataReceived;
private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{//首先实例化一个字节数组// 字节数组的大小:通过BytesToRead 属性,获取得到缓冲区中数据的字节数byte[] buffer = new byte[serialPort.BytesToRead];//再通过 Read() 方法 读取缓存区内全部数据,并将数据写入字节数组中serialPort.Read(buffer, 0, buffer.Length);// 解码string received = Encoding.ASCII.GetString(buffer); Console.WriteLine(received);
}

3)使用方式3

serialPort.DataReceived += (sender, e) => 
{if (e.EventType == SerialData.Chars){byte[] buffer = new byte[serialPort.BytesToRead];serialPort.Read(buffer, 0, buffer.Length);string data = Encoding.ASCII.GetString(buffer);Console.WriteLine($"收到数据:{data}");}
};

以上三种方式,基本原理一致,只是部分的读取数据方式和事件定义的方式稍有不同而已。

6. 完整示例

示例1:简单示例

using System;
using System.IO.Ports;
using System.Windows.Forms;public class SerialPortDemo
{//配置并创建SerialPort实例private SerialPort sp = new SerialPort("COM1", 9600, Parity.None, 8, StopBits.One);public void Start(){try{// 注册数据接收事件sp.DataReceived += DataReceivedHandler;// 打开串口sp.Open();//写入数据sp.WriteLine("Start Communication");}catch (Exception ex){MessageBox.Show($"初始化失败:{ex.Message}");}}// 接收数据private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e){// 读取数据string data = sp.ReadExisting();Console.WriteLine($"实时数据:{data}");}// 关闭端口public void Stop() => sp.Close();
}

示例2:WinForm 示例

以下是一个完整的示例,展示如何在C#中使用SerialPort类进行串口通信。

using System;
using System.IO.Ports;
using System.Windows.Forms;namespace SerialPortExample
{public partial class MainForm : Form{private SerialPort serialPort;public MainForm(){InitializeComponent();InitializeSerialPort();}private void InitializeSerialPort(){serialPort = new SerialPort();serialPort.PortName = "COM1";serialPort.BaudRate = 9600;serialPort.Parity = Parity.None;serialPort.DataBits = 8;serialPort.StopBits = StopBits.One;serialPort.Handshake = Handshake.None;serialPort.DataReceived += new SerialDataReceivedEventHandler(SerialPort_DataReceived);}private void btnOpen_Click(object sender, EventArgs e){try{if (!serialPort.IsOpen){serialPort.Open();MessageBox.Show("串口已打开");}}catch (Exception ex){MessageBox.Show("打开串口时出错: " + ex.Message);}}private void btnSend_Click(object sender, EventArgs e){if (serialPort.IsOpen){string message = txtSend.Text;serialPort.WriteLine(message);txtReceive.AppendText("发送: " + message + Environment.NewLine);}else{MessageBox.Show("请先打开串口");}}private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e){SerialPort sp = (SerialPort)sender;string indata = sp.ReadExisting();this.Invoke(new Action(() =>{txtReceive.AppendText("接收: " + indata);}));}private void btnClose_Click(object sender, EventArgs e){if (serialPort.IsOpen){serialPort.Close();MessageBox.Show("串口已关闭");}}}
}

示例3:扫码枪数据接收

SerialPort port = new("COM3", 115200, Parity.None, 8, StopBits.One);
port.DataReceived += (s, e) => 
{byte[] barcode = new byte[port.BytesToRead];port.Read(barcode, 0, barcode.Length);// 解析扫码枪数据(通常以回车结尾)if (barcode.Last() == 0x0D) {string code = Encoding.ASCII.GetString(barcode);ProcessBarcode(code);}
};

四、SerialPort 进阶

1. 高级参数配置

1)配置超时时间

防止长时间阻塞(单位:毫秒)。

// 设置读取超时为 1000ms
serialPort.ReadTimeout = 1000;
// 设置写入超时
serialPort.WriteTimeout = 500;

2)缓冲区设置

ReceivedBytesThreshold:指定触发 DataReceived 事件的字节阈值,即触发 DataReceived 事件的最小字节数。

serialPort.ReceivedBytesThreshold = 2;	//默认值 为 1

3)其余参数配置

sp.Encoding = Encoding.ASCII; 	// 编码格式
sp.NewLine = "\r\n";       		// 换行符定义

2. 获取所有可用 COM 端口

可以通过SerialPort.GetPortNames()方法获取系统中所有可用的串行端口名称:

// 获取所有可用 COM 端口
string[] ports = SerialPort.GetPortNames();
foreach (var port in ports)
{Console.WriteLine(port);
}

3. ErrorReceived事件

当串行通信中发生错误(如帧错误/缓冲区溢出)时,ErrorReceived事件会被触发:

serialPort.ErrorReceived += new SerialErrorReceivedEventHandler(serialPort_ErrorReceived);
private static void serialPort_ErrorReceived(object sender, SerialErrorReceivedEventArgs e)
{if ((e.EventType & SerialError.Frame) == SerialError.Frame){Console.WriteLine("Frame error detected.");}if ((e.EventType & SerialError.Overrun) == SerialError.Overrun){Console.WriteLine("Overrun error detected.");}if ((e.EventType & SerialError.RXParity) == SerialError.RXParity){Console.WriteLine("Parity error detected.");}
}
sp.ErrorReceived += (sender, e) => 
{Console.WriteLine($"错误类型:{e.EventType}");
};

4. 异常处理

使用try-catch块捕获和处理可能的异常,确保程序的稳定性:

try
{serialPort.Open();serialPort.WriteLine("Hello, Serial Port!");serialPort.Close();
}
catch (Exception ex)
{Console.WriteLine("Error: " + ex.Message);
}
// 常见异常类型
try 
{// 串口操作代码
}
catch (UnauthorizedAccessException ex)
{Console.WriteLine("端口访问被拒绝");
}
catch (TimeoutException ex) 
{Console.WriteLine("操作超时");
}
catch (IOException ex)
{Console.WriteLine("I/O错误");
}

5. 跨线程处理

为了能够实时响应串口接收到的数据,可以使用DataReceived事件。需要注意的是,该事件在单独的线程中触发,若要更新UI控件,涉及到跨线程,需要使用Invoke方法。

private void SerialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
{SerialPort sp = (SerialPort)sender;string received = sp.ReadExisting();// 数据接收后,通过委托更新UI(假设在 WinForms 中更新TextBox)this.Invoke(new Action(() =>{textBox.Text += received ;}));
}

6. 多线程处理

推荐使用生产者-消费者模式:

BlockingCollection<string> dataQueue = new BlockingCollection<string>();// 生产者线程
void DataReceivedHandler(...)
{dataQueue.Add(receivedData);
}// 消费者线程
Task.Run(() => 
{foreach (var data in dataQueue.GetConsumingEnumerable()){// 处理数据}
});

五、常见问题与注意事项

1. 注意事项

  • 参数一致性:确保双方设备的波特率、数据位、停止位、校验位一致。
  • 权限问题:在访问串口时,需要确保程序有相应的权限,否则可能会抛出异常。
  • 线程安全:在DataReceived事件中处理数据时,由于它是在单独的线程中触发的,若要更新UI控件,必须使用Invoke方法来确保线程安全
  • 异常处理:使用 try-catch 处理 Open()Read()Write() 可能抛出的异常。
  • 缓冲区管理:通过 DiscardInBufferDiscardOutBuffer 清空缓冲区,避免数据残留。
    • 避免重复打开同一端口,关闭前调用 sp.DiscardInBuffer() 清空缓存。
  • 硬件流控制
    在高速传输场景中启用 Handshake.RequestToSend,避免数据丢失。

2. 常见问题

  • 端口无法打开
    • 检查设备是否占用(如其他程序已连接)
    • 确认串口号是否正确(虚拟串口可能动态变化)
    • 异常处理:try...catch(IOException)捕获端口不存在错误
  • 数据接收不完整
    • 使用BytesToRead确保读取全部缓存数据
    • 添加延迟(如Thread.Sleep(50))等待完整帧
    • 硬件延迟:部分设备发送数据有间隔,需调整时序
  • 数据乱码
    • 发送/接收端波特率必须一致,否则数据乱码。
  • 字符编码问题
    • 若接收中文字符乱码,需设置:
    • serialPort.Encoding = Encoding.GetEncoding("GB2312")
    • serialPort.Encoding = Encoding.UTF8;

六、扩展

1. 跨平台方案(RJCP.SerialPortStream)

对于需要跨平台(Linux/macOS)的场景,推荐使用 RJCP.SerialPortStream 库(通过 NuGet 安装 RJCP.SerialPortStream):

using RJCP.IO.Ports;SerialPortStream serialPort = new SerialPortStream("COM3");
serialPort.BaudRate = 9600;
serialPort.Open();// 事件处理与读写方式与 SerialPort 类似
serialPort.DataReceived += (sender, e) => 
{byte[] data = new byte[serialPort.BytesToRead];serialPort.Read(data, 0, data.Length);Console.WriteLine(Encoding.UTF8.GetString(data));
};

2. 编码

使用串口通信的时候,会涉及到数据的编码格式,如果我们使用ASCII编码格式,但是接收的时候采用的是其他的编码格式,可能就会导致数据解析错误,因此在一些特定场景下我们需要规定好发送和接收数据的编码格式,这个时候就需要用到System.Text.Encoding 类中的编码解码的功能。
详见:C# System.Text.Encoding 使用详解

3. 清空缓冲区的方法

关于 DiscardInBuffer / DiscardOutBuffer 的使用,详见:C# SerialPort 类中清空缓存区的方法。

4. Handshake 设置

常用握手协议

  • Handshake.None:无握手。
  • Handshake.RequestToSend:RTS/CTS(请求发送/清除发送)。
  • Handshake.XOnXOff:软件流控制(XON/XOFF 字符)。
serialPort.Handshake = Handshake.RequestToSend;

详见:C# SerialPort 类中 Handshake 属性的作用

结语

回到目录页:C# 上位机知识汇总
希望以上内容可以帮助到大家,如文中有不对之处,还请批评指正。


参考资料:

  • 官方文档:SerialPort Class

相关文章:

C# SerialPort 使用详解

总目录 前言 在工业控制、物联网、嵌入式开发等领域&#xff0c;串口通信&#xff08;Serial Port Communication&#xff09;是连接串行设备&#xff08;如条码扫描器、GPS接收器等&#xff09;与计算机的重要手段。C# 提供了内置的 SerialPort 类&#xff0c;简化了串口开发…...

数据结构--二叉排序树

一、二叉排序树的定义 二叉排序树&#xff0c;又称二叉查找树。 性质&#xff1a; 左子树结点值<根结点值<右子树结点值&#xff08;进行中序遍历&#xff0c;可以得到一个递增的有序序列&#xff09; 二、查找操作 利用二叉排序树的性质&#xff0c;如果树空&#xff0c…...

FPGA的直方图均衡

文章目录 一、直方图均衡二、代码实现三、仿真 一、直方图均衡 直方图均衡&#xff08;Histogram Equalization&#xff09;是一种用于增强图像对比度的图像处理技术。它通过重新分配图像像素的灰度值&#xff0c;使得图像的灰度直方图在整个灰度范围内均匀分布&#xff0c;从而…...

使用Python将视频转化为gif

使用Python将视频转化为gif 一、前言二、准备三、测试 一、前言 最近想把喜欢的视频片段作成gif&#xff0c;就试着用Python做了下&#xff0c;感觉效果还行&#xff0c;这里做个记录。 二、准备 先下载安装对应的库&#xff0c;命令如下&#xff1a; pip install moviepy …...

基于javaweb的SpringBoot雪具商城系统设计与实现系统(源码+文档+部署讲解)

​ 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、小程序、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、…...

Harbor镜像仓库迁移与高可用集群搭建HTTPS实现实战指南

实验环境 Ubuntu22.04操作系统 registry节点 10.0.0.91 master节点 10.0.0.92 backup节点 10.0.0.93 在企业信息化建设的不同演进阶段&#xff0c;私有镜像仓库的选型策略存在显著差异。近期主导完成某企业级容器镜像仓库升级项目&#xff0c;成功实现Docker Registry至Ha…...

redis--JavaSpring客户端

目录 一、引言 二、配置 三、相关操作 四、总结 一、引言 本篇文章会将redis与spring项目进行结合&#xff0c;看看再spring项目中&#xff0c;redis是如何使用的 二、配置 三、相关操作 四、总结 在spring项目中的使用和在基础项目上的使用有差异&#xff0c;但是差异并不大…...

JavaWeb3

聚合函数&#xff1a;把某一列的数据计算。count,max,min,avg,sum select count(id) from wife;-- 统计个数&#xff0c;不计算null&#xff0c;统计常量表示个数 select count(*) from wife; select min(id) from wife; select avg(age) from wife; 分组查询 select name,c…...

SAP-ABAP:SAP数据集成全场景技术指南(BAPI、RFC、IDOC、BATCHJOB、ODATA、WEBSERVICE):从实时交互到批量处理

SAP数据集成全场景技术指南:从实时交互到批量处理 #mermaid-svg-hpPMerJYUerla0BJ {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-hpPMerJYUerla0BJ .error-icon{fill:#552222;}#mermaid-svg-hpPMerJYUerla0BJ .er…...

QT笔记----QCheckBox

文章目录 概要1、QCheckBox 的基本概念2、单个QCheckBox3、多个QCheckBox同时应用3.1、实现效果3.2、实现Demo 概要 在 Qt 应用程序开发中&#xff0c;QCheckBox 是一个常用的用户界面元素&#xff0c;它允许用户在两种状态&#xff08;选中和未选中&#xff09;之间进行切换&a…...

试试智能体工作流,自动化搞定运维故障排查

APO 1.5.0版本全新推出的智能体工作流功能&#xff0c;让运维经验不再零散&#xff01;只需将日常的运维操作和故障排查经验转化为标准化流程&#xff0c;就能一键复用&#xff0c;效率翻倍&#xff0c;从此告别重复劳动&#xff0c;把时间留给更有价值的创新工作。更贴心的是&…...

3.24[Q]Linux

我正在学习Linux&#xff0c;Linux设备管理是怎样的&#xff1f;详细解释&#xff0c;越细节越好 我正在学习Linux&#xff0c;在Linux设备管理中&#xff0c;什么是char device&#xff1f;以及block,usb device?详细解释&#xff0c;越细节越好 我正在学习Linux&#xff0…...

深度学习——图像相似度评价指标

这里写目录标题 PSNR&#xff08;Peak Signal-to-Noise Ratio&#xff0c;峰值信噪比&#xff09;定义公式代码 SSIMMS-SSIM (Multi Scale Structural Similarity Index Measure,多尺度结构相似性)CSS &#xff08;Contrast-Structure Similarity 对比结构相似度&#xff09;MA…...

CentOS安装sshpass工具-自动化SSH密码认证

sshpass是一个在Linux环境下用于自动化SSH密码认证的工具。 一、功能特点 自动化SSH登录&#xff1a;sshpass允许用户在命令行中直接传递密码&#xff0c;从而无需在SSH连接时手动输入密码。这对于自动化脚本和批处理任务非常有用&#xff0c;因为它可以在非交互式环境下完成…...

js 中 如何获取数组的交集【面试题】

一、数组元素为基本类型&#xff1a;Number、String、等基本类型时 1、使用 Set 和 filter&#xff08;适用于两个数组&#xff09; const intersection (arr1, arr2) > {const set new Set(arr2);return [...new Set(arr1)].filter(item > set.has(item)); };将第二…...

value-key 的作用

在 el-autocomplete 组件中&#xff0c;value-key 是一个非常重要的属性&#xff0c;它用于指定选项对象中作为值的字段名。当选项列表是一个包含多个属性的对象数组时&#xff0c;value-key 能帮助组件明确哪个属性是实际要使用的值。比如&#xff0c;选项列表为 [{id: 01, na…...

Spring MVC:从历史演变到实战入门

1. Java Web的发展历史与MVC模式 1.1 Model I与Model II的演进 Model I&#xff08;JSPJavaBean&#xff09; 作为早期Java Web开发的主流模式&#xff0c;其核心架构如下&#xff1a; graph LR A[客户端] --> B[JSP页面] B --> C{业务逻辑} C --> D[JavaBean] D -…...

Matlab设置表table的表头

用到matlab的table很好用。经常涉及放入数据&#xff0c;读取数据&#xff0c;下面总结常用的知识点。 1. 把不同数据类型放到同一个表中 想把时间类型和数值类型放到统一table中。困扰的点是&#xff0c;我已经知道了表头名称&#xff0c; 如何批量的为表头命名&#xff0c;…...

预测蓝桥杯16届嵌入式省赛客观题

以下是15道蓝桥杯嵌入式省赛客观题预测&#xff0c;每道题均包含**选项列表**、**答案**和**解析**&#xff0c;格式清晰便于快速查阅&#xff1a; 一、预测1 ### **一、STM32G4硬件基础与外设配置** 1. **STM32G431RBT6的Flash和RAM容量分别为&#xff1f;** **选项**&a…...

综合章节:游戏网络化、模组化与深度扩展

模块一&#xff1a;网络功能与玩家数据同步 目标&#xff1a;实现玩家得分上传、全球排行榜展示及云端数据同步。 # network_manager.py&#xff08;网络请求封装&#xff09; import requests import threadingclass NetworkManager:def __init__(self, base_url"http:…...

PostgreSQL:索引与查询优化

&#x1f9d1; 博主简介&#xff1a;CSDN博客专家&#xff0c;历代文学网&#xff08;PC端可以访问&#xff1a;https://literature.sinhy.com/#/?__c1000&#xff0c;移动端可微信小程序搜索“历代文学”&#xff09;总架构师&#xff0c;15年工作经验&#xff0c;精通Java编…...

Android Compose 框架的 ViewModel 委托深入剖析(二十)

Android Compose 框架的 ViewModel 委托深入剖析 一、引言 在 Android 开发中&#xff0c;数据的管理和状态的保存是至关重要的。ViewModel 作为 Android 架构组件的一部分&#xff0c;为我们提供了一种在配置更改&#xff08;如屏幕旋转&#xff09;时保存数据和管理 UI 状态…...

android|生成二维码qrcode(android)

1.build.gradle implementation com.google.zxing:core:3.4.1引入zxing库 只是生成的话引入core库就可以了 2.封装方法 import android.graphics.Bitmap; import android.graphics.Color;import com.google.zxing.BarcodeFormat; import com.google.zxing.EncodeHintType; imp…...

element-plus中el-empty空盒子组件和Collapse 折叠面板组件的使用

一.el-empty空盒子组件的使用 直接复制下面的代码&#xff1a; <el-empty description"description" /> 展示效果&#xff1a; 还可以自定义文字描述&#xff1a; <el-empty description"暂未选择患者"/> 二.Collapse 折叠面板组件的使用 复制…...

Windows 和 Linux 操作系统架构对比以及交叉编译

操作系统与架构兼容性详解 1. 可执行文件格式&#xff1a;PE vs ELF Windows: PE (Portable Executable) 格式 详细解释&#xff1a; PE 格式是 Windows 下的可执行文件标准 包含多个区段&#xff08;Sections&#xff09;&#xff0c;如代码段、数据段、资源段 文件头包含…...

【区块链安全 | 第一篇】密码学原理

文章目录 1.哈希函数1.1 哈希函数的性质1.2 常见哈希算法1.3 Merkle Tree&#xff08;默克尔树&#xff09;1.4 HMAC&#xff08;哈希消息认证码&#xff09; 2. 公钥密码学2.1 对称加密 vs 非对称加密2.2 RSA 算法2.3 ECC&#xff08;椭圆曲线密码学&#xff09;2.4 Diffie-He…...

3.23[A]linux

gedit 是 GNOME 桌面环境下的文本编辑器&#xff0c;类似于 Windows 中的记事本&#xff0c;但功能更强大&#xff0c;支持语法高亮、多文件编辑等特性。它是一个图形化界面的文本编辑器&#xff0c;适合在需要直观编辑文本文件的场景中使用。 gedit 通常用于编辑配置文件、源代…...

AI革命之下的前端将会如何发展?

一、AI 为前端开发带来的变革 &#xff08;一&#xff09;提升开发效率 传统的 Web 前端开发常常面临大量重复性工作&#xff0c;如编写简单表单、布局组件等&#xff0c;这些工作耗时费力且易出错&#xff0c;严重影响开发效率和项目进度。而 AI 的出现&#xff0c;通过自动…...

【2025】基于springboot+vue的农产品商城系统设计与实现(源码、万字文档、图文修改、调试答疑)

项目完整功能以演示视频为准 基于Spring Boot Vue的农产品商城系统设计与实现功能结构图如下&#xff1a; 课题背景 随着互联网的普及和电子商务的快速发展&#xff0c;农产品线上销售成为推动农业现代化和乡村振兴的重要力量。传统的农产品销售模式存在信息不对称、销售渠道单…...

沪深300股指期货的看涨看跌方式是怎样的?

沪深300指数代表了中国A股市场中300家大公司的整体表现。股指期货交易允许老板们预测指数未来的涨跌&#xff0c;并从中获利。 沪深300股指期货基础操作 首先&#xff0c;沪深300股指期货中的看涨操作&#xff1a;老板们可以通过买入沪深300股指期货合约&#xff0c;代码也就是…...

使用selenium来获取数据集

使用selenium来获取数据集 1、下载最新的chrome浏览器与chromedriver.exe 查看chrome的版本,打开谷歌浏览器,点击右上角的三个点,然后点击【帮助】, 点击【关于Google Chrome】 然后去下载同样为134版本号的chromedriver.exe, 网址:https://googlechromelabs.github.…...

MCP(大模型上下文协议)

以下是关于大模型MCP协议&#xff08;Model Context Protocol&#xff09;的详细介绍&#xff0c;综合其定义、技术架构、应用场景及行业影响&#xff1a; 一、定义与核心目标 **MCP&#xff08;Model Context Protocol&#xff0c;模型上下文协议&#xff09;**是由Anthropic…...

FPGA中串行执行方式之流水线(Pipeline)

FPGA中串行执行方式之流水线(Pipeline) 在FPGA设计中,​流水线(Pipeline)​ 是一种常见的优化技术,用于提高系统的吞吐量和性能。流水线通过将复杂的逻辑分解为多个阶段,每个阶段在一个时钟周期内完成一部分工作,并将中间结果传递到下一阶段。这种方式可以显著提高时钟…...

Python 3.8 Requests 爬虫教程(2025最新版)

遵守网站的爬虫规则、避免爬取敏感信息、保护个人隐私&#xff01; 一、环境配置与基础验证 # 验证 Python 版本&#xff08;需 ≥3.8&#xff09; import sys print(sys.version) # 应输出类似 3.8.12 的信息# 安装 requests 库&#xff08;若未安装&#xff09; # 命令行执…...

【深度学习】GAN生成对抗网络:原理、应用与发展

GAN生成对抗网络&#xff1a;原理、应用与发展 文章目录 GAN生成对抗网络&#xff1a;原理、应用与发展1. 引言2. GAN的基本原理2.1 核心思想2.2 数学表达2.3 训练过程 3. GAN的主要变体3.1 DCGAN (Deep Convolutional GAN)3.2 CGAN (Conditional GAN)3.3 CycleGAN3.4 StyleGAN…...

LINUX基础 [三] - 进程创建

目录 前言 进程创建的初次了解&#xff08;创建进程的原理&#xff09; 什么是fork函数&#xff1f; 初识fork函数 写时拷贝 fork函数存在的意义 fork调用失败的原因 进程终止 运行完毕结果不正确 main函数返回 库函数函数exit 系统调用接口_exit 进程异常终止 进…...

AI比人脑更强,因为被植入思维模型【24】替身决策思维模型

定义 替身决策思维模型是一种在面对复杂问题或决策情境时&#xff0c;通过将自己代入到不同的角色&#xff08;即“替身”&#xff09;中&#xff0c;从这些角色的视角出发去思考、分析和做出决策的思维方式。这种思维模型要求决策者暂时摆脱自身固有的思维定式和立场&#xf…...

数据清洗:基于python抽取jsonl文件数据字段

基于python抽取目录下所有“jsonl”格式文件。遍历文件内某个字段进行抽取并合并。 import os import json import time from tqdm import tqdm # 需要先安装&#xff1a;pip install tqdmdef process_files():# 设置目录路径dir_path r"D:\daku\关键词识别\1623-00000…...

spring后端处理各种请求

在Spring MVC中处理JSON请求和返回JSON消息的步骤如下&#xff1a; 1. 添加依赖 确保项目中包含处理JSON的库&#xff0c;如Jackson。 Maven配置&#xff08;pom.xml&#xff09;&#xff1a; <dependency><groupId>com.fasterxml.jackson.core</groupId>…...

企业级部署zabbix分布式监控系统

目录 一、Zabbix分布式监控系统介绍 1.什么是“Zabbix” 2.Zabbix分布式监控系统的特点 3.Zabbix分布式监控系统的原理 4.Zabbix分布式监控系统的运用 5. Zabbix分布式监控系统的部署顺序 二、搭建 1.设备硬件配置参考 2.zabbix分布式监控系统各节点设备名称和IP规划 …...

OkHttp 的证书设置

在 Android 开发中&#xff0c;通过 OkHttp 自定义 SSLSocketFactory 和 X509TrustManager 可以有效增强 HTTPS 通信的安全性&#xff0c;防止中间人攻击&#xff08;如抓包工具 Charles/Fiddler 的拦截&#xff09;。以下是实现防抓包的关键技术方案&#xff1a; 一、Okhttp设…...

ETL:数据清洗、规范化和聚合的重要性

在当今这个数据呈爆炸式增长的时代&#xff0c;数据已成为企业最为宝贵的资产之一。然而&#xff0c;数据的海量增长也伴随着诸多问题&#xff0c;如数据来源多样、结构复杂以及质量问题等&#xff0c;这些问题严重阻碍了数据的有效处理与深度分析。在此背景下&#xff0c;ETL&…...

蓝桥杯备考:图的遍历

这道题乍一看好像没什么不对的&#xff0c;但是&#xff01;但是&#xff01;结点最大可以到10的5次方&#xff01;&#xff01;&#xff01;我们递归的时间复杂度是很高的&#xff0c;我们正常遍历是肯定通过不了的&#xff0c;不信的话我们试一下 #include <iostream>…...

【多媒体交互】Unity Kinect实现UI控件的点击

在Unity中&#xff0c;通过Kinect实现UI控件的点击功能&#xff0c;主要涉及手部追踪、坐标映射和手势检测三个核心环节。 实现步骤 初始化Kinect与关节追踪 使用KinectManager获取用户ID和手部关节点&#xff08;如JointType.HandLeft&#xff09;的坐标。 long userId _…...

QinQ项展 VLAN 空间

随着以太网技术在网络中的大量部署&#xff0c;利用 VLAN 对用户进行隔离和标识受到很大限制。因为 IEEE802.1Q 中定义的 VLAN Tag 域只有 12 个比特&#xff0c;仅能表示 4096 个 VLAN&#xff0c;无法满足城域以太网中标识大量用户的需求&#xff0c;于是 QinQ 技术应运而生。…...

OBS虚拟背景深度解析:无需绿幕也能打造专业教学视频(附插件对比)

想要录制教学视频却苦于背景杂乱&#xff1f;本文将手把手教你用OBS实现专业级虚拟背景效果&#xff0c;无需绿幕也能轻松营造沉浸式教学场景。文末附6个提升画面质感的免费背景资源&#xff01; 一、虚拟背景的核心价值&#xff1a;从「教师宿舍」到「虚拟讲堂」的蜕变 我们调…...

26考研——图(6)

408答疑 文章目录 一、图的基本概念二、图的存储三、图的遍历四、图的应用五、图的代码实操六、参考资料鲍鱼科技课件26王道考研书 七、总结图的存储结构邻接矩阵邻接表 图的遍历图的相关概念完全图和连通图图的连通性 关键路径学习建议 一、图的基本概念 文章链接: link 二、…...

Redis常用数据类型深度解析:从理论到最佳实践

Redis常用数据类型深度解析&#xff1a;从理论到最佳实践 一、引言二、Redis数据类型全景图三、核心数据类型详解**1. String&#xff08;字符串&#xff09;****2. Hash&#xff08;哈希表&#xff09;****3. List&#xff08;列表&#xff09;****4. Set&#xff08;集合&…...

DeepSeek-V3 模型更新,加量不加价

DeepSeek V3-0324 是 DeepSeek V3 系列的重要升级版本&#xff0c;虽然被官方称为「小版本迭代」&#xff0c;但其在技术能力、开源策略和用户体验上均有显著提升。以下是主要新特性功能和核心变化&#xff1a; 推理能力 基准测试性能显著提升&#xff1a; MMLU-Pro&#xff1…...

Vue项目的 Sass 全局基础样式格式化方案,包含常见元素的样式重置

步骤 1&#xff1a;创建全局样式文件 在项目中创建文件&#xff1a;src/assets/scss/global.scss 内容如下&#xff1a; // 全局盒模型设定&#xff08;边框计入宽高&#xff09; *, *::before, *::after {box-sizing: border-box;margin: 0;padding: 0; }// 基础元素样式重置…...