STM32串口高频率数据收发中的ORE中断处理与优化策略

STM32L431串口中断服务函数优化:避免ORE标志导致的无限中断 本文深入剖析了STM32L431串口通信中因ORE(溢出错误)标志未清除导致的无限中断问题。文章从原理出发,详解了ORE的产生机制与中断服务函数(ISR)的关联,并提供了优化的ISR代码框架与系统级预防策略,帮助开发者构建稳定高效的串口驱动,尤其适用于RTOS环境。 阅读详情

1. 从一次“卡死”经历说起:我的STM32串口调试血泪史

大家好,我是老李,一个在嵌入式领域摸爬滚打了十多年的工程师。今天想和大家聊聊STM32串口开发中一个非常典型,但又极易被新手忽略的“坑”——高频率数据收发下的系统卡死问题。这事儿我印象太深了,几年前带一个新人做项目,就栽在这上面,整个系统跑着跑着就“僵”在那里,按键没反应,灯也不闪,跟死机了一样。当时查了很久,最后定位到问题,就是串口溢出错误(ORE)中断没处理好。

你可能也遇到过类似的情况:你的STM32和上位机、或者另一个单片机之间,需要以较高的频率(比如几十Hz甚至上百Hz)通过串口交换数据。一开始跑得好好的,但几分钟、十几分钟后,设备突然就“罢工”了,程序像卡在了某个地方。重启之后,又能正常工作一段时间,然后再次卡死。这种问题在调试时非常恼人,因为它不是立即复现的,具有一定的隐蔽性。

其实,这种“卡死”现象,十有八九和串口接收溢出有关。当数据来的太快,你的中断服务程序来不及处理时,STM32的串口硬件就会触发一个叫做ORE(Overrun Error) 的错误。如果你在代码里没有专门去检测和处理这个错误,那么ORE标志位会一直挂着,导致后续的接收中断再也无法正常进入,从现象上看,就是串口接收功能“死”了,如果程序逻辑严重依赖接收数据,那整个系统卡死也就不奇怪了。

原始文章的作者提到,他的项目是50Hz的频率收发14字节的数据包。这个数据量看似不大,但已经足以在某些情况下触发ORE。这给我们提了个醒:不要小看任何持续的数据流,中断服务程序的处理速度、是否有被更高优先级中断打断、甚至编译器优化等级,都可能成为压垮骆驼的最后一根稻草。接下来,我们就深入“虎穴”,看看ORE到底是怎么产生的,又该如何把它“驯服”。

2. 深入内核:STM32串口ORE中断的产生机制

要解决问题,首先得明白问题是怎么来的。我们把STM32的串口想象成一个传达室,它有一个小小的接待窗口(接收数据寄存器RDR),外面连着一条数据流水线(接收移位寄存器)。

2.1 数据接收的流水线

当串口接收到一个字节的数据时,硬件会经历以下几步:

  1. 数据位一个一个地从RX引脚移入接收移位寄存器。
  2. 一个字节收齐后,硬件会自动将这个字节从移位寄存器搬运到接收数据寄存器(RDR/DR)。
  3. 数据进入RDR后,硬件会自动置位一个标志位:RXNE(接收数据寄存器非空)。这个标志位就是告诉我们:“传达室的窗口里有一封信(数据),快来取!”

如果我们使能了接收中断(RXNEIE),那么RXNE标志就会触发一个中断请求,CPU就会跳转到串口中断服务函数(ISR)里。我们在ISR里调用USART_ReceiveData读取DR寄存器,这个读取动作就像从窗口取走那封信。一旦读取,硬件就会自动清除RXNE标志,表示窗口空了,可以接待下一封信。

2.2 ORE是如何发生的?

理想很丰满,但现实是流水线可能“堵车”。假设一种极端情况:上一封信(数据A)已经放进了RDR(RXNE=1),发出了“快来取”的通知。但是,我们的CPU正忙于处理一个更紧急的任务(比如一个高优先级的定时器中断),或者当前的串口中断服务程序写得特别冗长,导致没能立刻响应这个通知。

就在这个空档期,下一个字节(数据B)已经通过移位寄存器接收完毕了。这时候硬件发现:糟糕,RDR窗口里的上一封信(数据A)还没被取走呢!新来的数据B没地方放了。硬件会怎么处理?它会丢弃这个新来的数据B,同时,它会设置另一个重要的标志位:ORE(Overrun Error,溢出错误)。

这里有一个非常关键的点,也是很多资料没讲透的:ORE标志一旦被置位,它就会像一道“闸门”一样,锁住RXNE标志的自动更新。 也就是说,即使之后你终于忙完了,去RDR里把数据A读走了,但由于ORE还挂着,硬件不会再自动将后续接收到的数据C、D、E...搬进RDR,也不会再产生新的RXNE中断。从软件角度看,串口接收功能就此“静默”了。如果你的程序逻辑在等待接收特定数据包,就会永远等下去,表现为“卡死”。

2.3 手册中的关键线索

正如原始文章作者从《STM32参考手册》中挖出的宝藏信息所示,在使能接收中断(RXNEIE)时,溢出中断(OREIE)通常也被连带使能了。这意味着,ORE事件不仅能产生错误标志,也能产生中断请求。但是,在标准库或HAL库的默认初始化流程中,我们往往只关注RXNE中断,而忽略了同样需要处理的ORE中断。这就为系统埋下了不稳定的种子。

标志位 全称</
STM32串口中断ORE问题记录 首先感谢“今天也迟到”提供的思路,原文博客如下: https://blog.youkuaiyun.com/qq_34401994/article/details/76359581 背景:STM32F030芯片,485串口使用MDA+中断方式收发数据。 问题:串口在收发数据过程中,偶发性的收不到数据,且无法自恢复,必须重启MCU。 问题分析: 在调试过程中发现,未能正确接收数据的状态下,DMA_GetCurrD... 阅读详情

相关推荐

STM32串口接收中断卡死无法接收数据问题及解决办法(已解决)

问题现象:STM32L432单片机MCU程序串口1,接收中断方式,发送采用查询方式。当使用SSCOM定时发送数据给MCU时,正常情况下,MCU收到什么就会回什么数据。如果使用100ms发送,MCU长时间测试都正常。如果使用1ms或者5ms发送数据给MCU,会出现MCU出现异常,MCU无法再接收到数据,接收中断也进不去。发送数据也无效。通过设置断点,发现接收中断设置不成功的原因是gState值HAL...

无语僧 2万+

STM32串口频繁收发至其卡死的解决方案

STM32串口频繁收发至其卡死的解决方案

weixin_41515163的博客 2万+

嵌入式开发实战:如何用STM32的环形缓冲区优化串口通信(附代码解析)

本文详细介绍了在STM32嵌入式开发中,如何利用环形缓冲区优化串口通信,解决数据丢失和程序阻塞问题。通过分析传统中断处理的缺陷,阐述了环形缓冲区的生产-消费模型原理,并提供了两种核心实现方案及与HAL库集成的代码示例,有效提升系统稳定性和通信效率。

nice1的博客 696

从零构建:STM32 DMA串口通信的底层原理与实战优化

本文深入解析STM32 DMA串口通信的底层原理与实战优化,涵盖DMA控制器架构、寄存器配置及高性能实现方案。通过DMA技术显著降低CPU负载,提升数据传输效率,特别适用于工业传感器数据采集等高频场景。文章还提供了增强型printf实现和双缓冲技术等优化策略,助力开发者构建高效嵌入式系统。

weixin_29185199的博客 629

STM32F407 UART4串口DMA实战:告别频繁中断,用空闲中断+DMA搞定不定长数据收发

本文详细介绍了STM32F407 UART4串口DMA实战方案,通过空闲中断+DMA技术高效处理不定长数据收发,显著降低CPU占用率。文章涵盖硬件配置、代码实现、常见问题调试及RTOS集成等关键内容,为嵌入式开发者提供了一套完整的避坑指南和性能优化策略。

weixin_33690367的博客 641

告别数据丢失!STM32 HAL库串口接收用环形FIFO,实战避坑指南(附完整代码)

本文详细介绍了STM32 HAL库中串口通信使用环形FIFO缓冲区解决数据丢失问题的工程实践。通过分析传统接收方式的缺陷,提出环形FIFO的设计原理与实现方法,包括缓冲区大小选择、HAL库集成实现及高级优化技巧,并附完整代码示例,帮助开发者提升串口通信的稳定性和效率。

weixin_30788619的博客 401

告别标准库!用STM32CubeMX HAL库搞定陶晶驰串口屏数据接收(附完整中断回调代码)

本文详细介绍了如何使用STM32CubeMX HAL库高效接收陶晶驰串口屏数据,包括从标准库到HAL库的思维转换、CubeMX串口配置要点、中断接收与数据帧解析实战。通过完整的中断回调代码示例,帮助开发者快速掌握HAL库下的串口通信技术,提升与陶晶驰屏的交互效率。

weixin_30785593的博客 405

STM32硬件串口不够用?软件模拟串口实现与避坑指南

在嵌入式开发中,串口通信是连接传感器、无线模块和上位机调试的核心接口。其原理基于异步串行协议,通过约定波特率、数据位和停止位实现设备间数据交换。当MCU硬件串口资源不足时,软件模拟串口技术提供了一种灵活、低成本的解决方案。该技术利用通用GPIO引脚,通过软件精确控制时序来模拟收发功能,其核心价值在于扩展通信接口而不增加硬件成本。实现方案包括阻塞轮询、外部中断结合延时以及更稳定的定时器驱动状态机,其中定时器方案能有效保证时序精度。应用场景多见于对成本敏感、需快速验证或接口需求超过硬件限制的嵌入式项目,例如连接

weixin_30781775的博客 399

告别轮询!用HAL库的HAL_UARTEx_ReceiveToIdle_DMA高效处理STM32串口数据流

本文深入解析了HAL库中的HAL_UARTEx_ReceiveToIdle_DMA函数,该函数整合了DMA传输和IDLE中断检测,为STM32开发者提供了一种高效处理不定长串口数据流的解决方案。文章详细介绍了其工作原理、使用技巧和性能优化方法,帮助开发者构建更健壮的串口通信框架,适用于工业控制、物联网等嵌入式应用场景。

weixin_30701575的博客 414

STM32独立按键中断处理:从轮询到EXTI的实战与优化

在嵌入式系统中,中断机制是处理异步事件的核心技术,它允许CPU在外部事件发生时暂停当前任务,转而执行特定的服务程序,从而显著提升系统响应效率与实时性。其原理基于硬件信号触发和中断控制器(如NVIC)的优先级仲裁,通过保存和恢复现场实现任务的无缝切换。这一技术价值在于解放了CPU,使其从低效的轮询等待中解脱,能够更流畅地执行多任务。在嵌入式开发中,中断广泛应用于处理GPIO输入、定时器事件、串口通信等场景。本文聚焦于STM32的独立按键处理,深入探讨如何利用外部中断(EXTI)替代传统的轮询方式。通过分析**

weixin_34253126的博客 403

STM32串口DMA收发实战:高效接收策略与CPU占用优化指南

在嵌入式开发中,串口通信是设备间数据交互的基石,但传统的阻塞式或中断驱动收发方式在高频、多字节场景下会显著增加CPU负担,甚至导致数据丢失。直接存储器访问(DMA)技术通过硬件通道实现外设与内存间的数据搬运,无需CPU逐字节干预,从原理上解决了中断频繁触发带来的效率瓶颈。本文以STM32为例,系统阐述DMA的基本传输机制、CubeMX配置流程,并重点解析空闲中断配合DMA实现不定长数据接收的完整方案,同时对发送时序控制、常见调试陷阱与性能边界给出工程实践建议,帮助开发者降低串口通信的资源占用,提升系统实时性

weixin_42520909的博客 126

基于STM32的虚拟示波器与CAN通信系统设计与实现

USART是一种全双工异步通信接口,广泛应用于调试信息打印、PC通信及简单传感器数据上传。其核心参数包括波特率、数据位、停止位和校验方式。正确配置这些参数是确保通信稳定的基础。以STM32F4系列为例,在使用HAL库进行初始化时,需通过结构体设置关键参数:// 波特率// 数据位8位// 停止位1位// 无校验// 收发模式// 无硬件流控考虑到STM32侧资源有限,且需兼顾CAN与UART两种传输媒介的特点,设计一种紧凑型二进制协议格式,兼顾通用性与扩展性。

weixin_35749545的博客 1164

【电弧故障检测算法全解析,电弧串扰问题分析和解决算法】

本文系统分析了电弧故障检测算法及串扰问题解决方案。电弧检测主要采用时频域分析和机器学习方法,通过提取高频噪声、波形畸变等特征实现故障识别。针对电弧串扰问题,提出了自适应滤波、盲源分离和时频联合分析等算法。研究给出了Python和C语言的算法实现示例,包括高频能量检测、过零率计算和陷波滤波器设计。最后指出算法优化方向:实时性提升可采用滑动窗口FFT和硬件加速;抗干扰增强需结合硬件滤波;机器学习扩展可引入随机森林等分类器。该研究为电弧故障检测系统开发提供了完整的技术路线。

syttt的专栏 891

CANFD升级踩坑实录:DBC转换时DLC大于8的信号怎么处理?

本文详细探讨了CANFD升级过程中DLC大于8的信号处理问题,提供了工程化解决方案和AutoSar BSW层配置要点。通过分析CAN与CANFD的DLC本质差异,提出信号拆分重组、DLC重映射和协议层适配三种策略,并给出验证与测试方案,帮助开发者避免数据截断和通信故障。

weixin_42521843的博客 232

R语言环境下Bibliometrix与Biblioshiny的安装与配置指南

本文提供了在R语言环境下安装与配置Bibliometrix和Biblioshiny的详细指南。内容涵盖R与RStudio的安装、Bibliometrix包的安装避坑方法,以及如何启动Biblioshiny图形界面进行文献计量分析。重点解决了安装过程中的常见网络与依赖问题,帮助科研人员快速搭建高效的文献分析环境。

jwt8token的博客 1147

Xilinx Chip2Chip IP核实战:Aurora PHY通信配置与仿真避坑指南

本文深入解析Xilinx Chip2Chip IP核与Aurora PHY的通信配置与仿真优化,提供实战避坑指南。通过AXI协议转换桥实现FPGA间高速数据传输,详细讲解Aurora PHY参数设置、仿真加速技巧及常见问题解决方案,帮助工程师快速部署稳定高效的芯片间通信系统。

g5h6i7j的博客 1007

Ubuntu零基础教学-史上最详Ubuntu20.04安装教程,超级详细,强烈建议收藏!

官网地址:https://www.vmware.com/ 1、VMware Workstation Pro 15.5.1在Windows 10的安装不再介绍了,一路下一步即可。 2、下面详细介绍在VMware 虚拟机里安装Ubuntu 20.04 LTS的步骤

**My Coding Family** 2万+

ResNet改进(7):添加 SK注意力机制

实现 SK 注意力机制。

2401_82355416的博客 732

【GeoDa实用技巧100例】024:geoda计算全局(局部)莫兰指数Moran‘s I,LISA聚类地图,显著性地图

【GeoDa实用技巧100例】024:geoda计算全局(局部)莫兰指数Moran's I,单变量莫兰指数,双变量莫兰指数计算,LISA聚类地图,显著性地图,Geoda双变量莫兰指数是一种强大的地理空间数据分析工具。

智慧空间实验室 6052

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

上一篇: Simulink子系统实战:如何用In/Out模块搭建高效模型接口(附MATLAB数据导入技巧)
下一篇: 避坑指南:QGraphicsView性能优化五大技巧(附抗锯齿/滚动条/刷新策略对比)
ruby5
博客等级 码龄15年 29粉丝 893原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值