news 2026/9/7 15:11:34

STM32实战:基于FreeRTOS的智能仓储环境监测系统开发详解

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32实战:基于FreeRTOS的智能仓储环境监测系统开发详解

简介:本资源是一套基于STM32F103C8T6的智能仓储环境监测系统完整工程实现,面向嵌入式初学者、课程设计学生及物联网实践开发者,解决小型仓储场景下温湿度、光照、烟雾等多参数实时感知与闭环调控问题。项目融合Proteus仿真与真实硬件逻辑,支持本地按键交互、OLED可视化及ESP8266远程监控,具备加热、散热、通风、声光报警等完整执行链路。压缩包含335个文件,涵盖56个编译中间文件(.o)、55个源码备份(.zbak)、55个配置文件(.crf)、38个头文件(.h)、36个C源文件(.c)及Keil工程(.uvprojx)、Hex固件、启动汇编与链接脚本等核心开发资产,总大小16.99MB。已有79人学习下载,提供可直接编译运行的完整代码结构、模块化驱动(ADC、I2C、TIM、RCC等)、阈值设定逻辑实现及无线通信接口封装,便于理解嵌入式系统软硬协同设计全流程。 做嵌入式开发这几年,我陆陆续续做过不少基于STM32的小项目,但真正让我觉得“做了一个完整产品”而不是“点亮一颗LED”的,是这个智能仓储环境监测系统。它不是一个DEMO,而是一套能实际放进仓库里跑起来、能持续记录数据、能联动风机和加热器、还能出报表的完整设备。如果你的工作或毕业设计正好需要做类似的环境监测类项目,这篇文章应该能帮你省下至少两三个月的踩坑时间。

这套系统的核心功能一句话就能讲清楚:围绕STM32做主控,采集仓库里的温湿度、烟雾浓度、光照强度,通过LCD实时显示,支持本地按键设定阈值,超限时自动控制风机、加热器、补光灯,同时把数据通过ESP8266上报到上位机或云平台。硬件上有传感器、执行器、显示器、通信模块,软件上有嵌入式驱动、状态机、协议解析、任务调度,算是把嵌入式开发里最常见的知识点都串起来了。不管你是想学STM32实战的初学者,还是准备参加电赛/做毕设的学生,这套方案都值得完整看一遍。

1. 系统整体设计与方案选型

1.1 设计思路:先想清楚要采集什么、控制什么

我一般接到一个项目不会先画电路板,而是先把系统拆成几个功能块:感知层、控制层、执行层、交互层、通信层。感知层就是各种传感器,负责“摸环境”;控制层就是STM32主控,负责“做决策”;执行层是继电器、风扇、加热器这些“干活的东西”;交互层是屏幕、按键,负责“让人知道状态”;通信层负责“把数据传到别的地方”。这种分层思维对后面的代码组织、硬件接线、问题排查都有好处。

具体到这个项目,仓库环境监测最核心的参数有三个:温湿度(影响货物存储条件,比如电子元器件怕潮、纸制品怕火)、烟雾浓度(火灾预警)、光照强度(避免阳光直射某些敏感物资,也用于智能补光)。执行端的逻辑也很直白:温度过高开风扇,湿度过大开除湿器或加热器,烟雾超标声光报警并打开排烟风机,光照不足自动补光。这套逻辑在代码里就是几个if判断,但对应的硬件接线和驱动设计,才是工作量的大头。

1.2 主控选型:为什么选STM32F103C8T6

主控我选了STM32F103C8T6,这颗芯片在嵌入式圈子里几乎人手一颗。有人可能会问,现在STM32F4、H7都出来了,为什么不选更强的?原因很简单:这个项目的负载完全用不到F4级别的算力,而F103的资源恰好覆盖所有需求。它有64KB Flash、20KB RAM,三个USART、两个I2C、两个SPI、一个ADC,12个通道,足够驱动两个传感器(I2C的SHT30和模拟量的MQ135)、一个OLED显示屏(I2C或SPI)、一个ESP8266(USART1)、一个按键模块(GPIO)、两个继电器(GPIO)和一路蜂鸣器(PWM)。

从性价比角度说,C8T6的国产替代版(比如GD32F103、MM32F103)现在几块钱就能拿到,资料却和ST原厂互通,拿来做产品验证或者学生项目都极其合适。而且F103系列的资料多、例程全,遇到任何奇怪问题,基本都能在网上找到别人的解决方案,这对开发效率的提升是实打实的。

1.3 传感器与执行器选型

传感器选型是我在这个项目里比较纠结的部分,因为传感器直接决定了数据的可靠程度。先说说温湿度。DHT11太粗糙(精度±2度,湿度±5%),做仓库监测这种需要连续记录数据的场景不太够看;我最后选了SHT30,I2C接口,精度±0.3度、湿度±2%RH,价格也就几块钱,同系列的SHT31、SHT35可以通过替换焊盘兼容。如果你手头只有DHT11,也不是不能用,但数据曲线会丑很多。

烟雾传感器用的MQ135,这是一个经典的气体传感器,对烟雾、甲醛、苯都有响应,输出模拟电压。它的特点是便宜、灵敏度可调,缺点是需要预热、非线性和温漂。后面我会详细讲怎么标定。光照传感器用的BH1750,也是I2C接口,直接输出勒克斯(Lux),不用自己做复杂的换算。

执行器方面,我用了两个5V继电器模块,一个控制排风扇,一个控制加热器/除湿器,另外加了一个无源蜂鸣器做声光报警。继电器模块用光耦隔离,STLINK或调试器供电建议和继电器电源分开,不然电机一启动,单片机可能直接复位。这里踩过坑,后面会细说。

2. 硬件电路与接线细节

2.1 STM32最小系统与调试接口

很多新手刚开始喜欢买一块现成的开发板,这没错,但如果你要做实际部署,开发板占地方又贵,到最后还是要画一块自己的板子。这个项目我用的是自己打的PCB,核心电路就那几个部分:电源(5V转3.3V)、晶振(8M)、复位电路、SWD调试口、BOOT配置

调试口我强烈建议引出SWD而不是JLINK的20针接口,只用SWIO、SWCLK、GND三个脚就能下载和调试,省IO还省空间。但这里有一个坑必须提醒:如果SWD引脚被复用成其他功能,或者程序里不小心禁用了JTAG/SWD,下过一次程序后,第二次可能就下载不进去了。网上搜“STM32禁用JTAG”会出现一堆帖子,基本都是这个问题。解决办法是按住复位键的同时点下载,在下载瞬间松开复位,或者用串口ISP方式先擦除Flash再重新烧录。我当初第一次碰到这问题的时候折腾了整整一晚,后来才明白是GPIO初始化时把SWD引脚给改了。

2.2 传感器与执行器接线方式

整个系统的接线我整理了一个表,方便你对照着做:

模块接口类型STM32引脚供电备注
SHT30温湿度I2CPB6(SCL), PB7(SDA)3.3V上拉电阻4.7k
BH1750光照I2CPB6(SCL), PB7(SDA)3.3V可软件设置地址
MQ135烟雾ADCPA15V输出经分压接ADC
OLED 0.96寸I2CPB6(SCL), PB7(SDA)3.3V和传感器共用I2C
ESP8266USART1PA9(TX), PA10(RX)3.3V注意电平匹配
继电器1(风扇)GPIOPA45V光耦隔离
继电器2(加热)GPIOPA55V光耦隔离
蜂鸣器PWM/GPIOPA63.3V低电平触发
按键GPIOPA0, PA23.3V上拉输入

这里有一个很容易忽略的点:SHT30、BH1750、OLED都挂在同一组I2C总线上,地址必须错开。SHT30默认地址是0x44,BH1750是0x23,OLED是0x3C,这三个地址没有冲突,可以放心挂在一起。如果后面要加其他I2C设备,需要先查一下地址,避免冲突。

电源方面,我的做法是外部输入直流12V,经过一个MP1584降压模块降到5V,然后再用LDO(AMS1117-3.3)降到3.3V给MCU和传感器供电。继电器模块和蜂鸣器直接吃5V。需要特别注意的是,MQ135的加热电阻功率不小,发热明显,工作电流有150mA左右,如果从AMS1117取电,3.3V那一路会被拖垮,所以MQ135的5V供电要单独从降压模块走。

2.3 PCB布局经验

PCB布局上吃过几次亏,这里讲一下最关键的几条。第一,模拟地和数字地要单点连接,MQ135输出的模拟信号线尽量短,不要走直角,避免和继电器驱动线并行走长距离。第二,继电器和蜂鸣器这类感性负载,必须在两端并联续流二极管(1N4007)或RC吸收电路,否则关断瞬间的反向电动势会把单片机的GPIO打坏。第三,ESP8266的供电不能直接从MCU的3.3V引脚拉,因为WiFi发射瞬间电流能到300mA以上,电压跌落会导致模块反复重启。我给ESP8266单独放了一个AMS1117-3.3,并且并联了两个100uF的电解电容,实测稳定很多。

3. 软件架构与核心代码实现

3.1 开发环境:STM32CubeMX + HAL库 + Keil

现在做STM32开发,我强烈建议直接用STM32CubeMX生成初始化代码,再配合HAL库写业务逻辑,不要自己手动去翻寄存器了。当然,我理解还是有人喜欢标准外设库(标准库),觉得网上教程多、代码透明。但客观说,ST官方现在已经不更新标准库了,新出的芯片根本不支持。如果你是做产品而不是学单片机原理,直接上HAL库才是正路。

CubeMX里需要做的配置如下:

  • RCC:HSE外部晶振8MHz
  • SYS:Debug Serial Wire(SWD)
  • I2C1:Standard Mode,100kHz
  • ADC1:IN1单通道,连续转换模式,开启DMA循环请求
  • USART1:115200-8-N-1,使能空闲中断(IDLE)
  • USART2:115200,用于调试打印
  • TIM2:1ms定时中断,作为系统时间基准
  • FreeRTOS:CMSIS_V1接口,创建数据采集、显示刷新、通信上报三个任务

这个配置下来,CubeMX生成的代码已经帮你处理好了时钟树、GPIO初始化、DMA中断这些底层杂事,后续主要工作就集中在业务逻辑上。

3.2 ADC多通道DMA采集:别让传感器数据采集卡死CPU

这个项目里,ADC采集我用了两个通道:PA0采集MQ135烟雾电压,PA1采集一个NTC热敏电阻分压作为备用测温。一开始我直接用阻塞方式轮询ADC,发现只要采集一启动,主循环就卡住几百微秒,显示刷新、按键扫描全都不流畅。后来改成ADC多通道+DMA循环采样,效果立竿见影。

具体配置流程是这样的:在CubeMX里把ADC1的两个通道的采样时间拉长到239.5周期,开启Scan Conversion Mode和Continuous Conversion Mode,然后使能DMA的Circular模式,数据宽度都是Half Word(16位),内存地址递增。DMA的Buffer长度设为2,对应两个通道。

因为DMA是循环模式,硬件会持续把ADC转换结果搬运到内存数组里,CPU完全不用介入。需要读数据时,直接从数组里取最新值就行。比如:

uint16_t adc_buf[2] = {0}; // 在while循环里读最新数据 uint16_t mq135_raw = adc_buf[0]; uint16_t ntc_raw = adc_buf[1];

注意,在CubeMX里CIRCULAR模式的DMA,HAL库会自动维护一个半传输和全传输中断,你可以利用这两个中断做双缓冲,但我这个数据量很小,直接循环读数组就够了,不需要额外处理。

3.3 串口空闲中断:接收ESP8266回传的不定长数据

串口接收不定长数据,是STM32开发里非常经典的问题。以前用标准库的时候,很多人都是一次接收一个字节到数组里,然后靠定时器或自定义协议判断一帧数据结束了没有。现在用HAL库配合空闲中断(IDLE Interrupt)可以非常优雅地解决。

思路是这样的:串口接收每产生一个字节中断,DMA就把数据搬到接收缓冲区,而空闲中断是当串口线在一段时间内没有数据传输时触发的,刚好代表“一帧数据从开始到结束”。我在USART1上使能了空闲中断,然后在中断回调函数里处理一帧完整数据:

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size) { if (huart->Instance == USART1) { esp_rx_len = Size; memcpy(esp_rx_buf, esp_dma_buf, Size); esp_rx_ok = 1; HAL_UARTEx_ReceiveToIdle_DMA(&huart1, esp_dma_buf, ESP_RX_MAX_LEN); } }

这个方案的核心是,我先开启一次HAL_UARTEx_ReceiveToIdle_DMA,之后所有收到的数据会通过DMA自动存到缓冲区,空闲中断一次就回调一次,Size参数就是这一帧数据的大小。处理完一帧之后,再重新开启下一次接收。

实测下来,这个方案接收ESP8266发来的不定长AT指令回包非常稳定,不会丢帧,也不会把两帧粘在一起。如果你还在用HAL_UART_Receive_IT一个字节一个字节地接,建议赶紧换掉。

3.4 传感器驱动编写:SHT30的CRC校验与MQ135的标定

传感器驱动这块,SHT30虽然I2C协议简单,但ST官方的HAL库函数有一点需要注意:SHT30读取的6个字节数据最后两位是CRC校验,很多教程里都是直接忽略校验只拿前4个字节。虽然大多数时候数据是准的,但在电磁环境复杂的仓储现场,偶尔会出现一个跳变的错误值,这时候CRC校验就很有意义了。

SHT30的CRC校验用的是CRC-8多项式0x31,HAL库自带HAL_CRC,但直接计算有点麻烦,我写了一个轻量的软件CRC:

uint8_t sht30_crc8(uint8_t *data, uint8_t len) { uint8_t crc = 0xFF; for (uint8_t i = 0; i < len; i++) { crc ^= data[i]; for (uint8_t j = 0; j < 8; j++) { if (crc & 0x80) crc = (crc << 1) ^ 0x31; else crc <<= 1; } } return crc; }

MQ135的标定是个大课题。它的输出是0~5V的模拟电压,气体浓度越高电压越大,但这个关系不是线性的。网上能搜到MQ135的灵敏度特性曲线是横轴为浓度、纵轴为电阻比的曲线,实际工程里很少做精确标定,更常用的方法是用阈值判断烟雾是否超标。我在程序里先采集洁净空气中的基准电压(比如预热10分钟后读取到1.2V),然后设定一个偏移量(比如0.5V),当电压超过基准+偏移时判定为烟雾报警。这种“相对阈值法”虽然测不出绝对浓度,但作为火灾预警完全够用。

这里要特别提醒,MQ135上电后需要预热5分钟左右,输出才会稳定,所以程序里要加一个开机初始化延时,否则刚开机那两秒钟读取的数据会虚高,导致误报警。

3.5 FreeRTOS任务划分:采集、显示、上报互不阻塞

这个项目的软件架构如果全写在一个while循环里也能跑,但逻辑会变得很难维护。比如,OLED刷新需要几十毫秒,如果在这个时间里去读ADC、发串口,就会出现数据延迟或丢包。所以我用了FreeRTOS,把系统拆成几个独立任务:

任务名优先级周期功能
SensorTask3500ms读取SHT30/BH1750/MQ135
DisplayTask21000ms刷新OLED显示
AlertTask4事件驱动超限报警与继电器控制
CommTask12000ms通过ESP8266上报数据

任务之间通过FreeRTOS队列传递数据。SensorTask把采集结果打包成一个结构体,发送到队列;DisplayTask和CommTask分别从队列中读取数据并处理。这样采集任务不会等待显示和通信,实时性有了保证。

串口打印和显示抢资源的问题也顺便解决了,因为每个任务都有自己的数据源,不需要用同一个全局变量。这里有一条经验:FreeRTOS里任务函数的局部变量尽量用静态或动态分配,不要在任务栈里放大数组,比如char buf[512],很容易把任务栈压爆。我每个任务的栈大小都设成了256字(Word),实测足够。

4. 数据通信与上位机方案

4.1 ESP8266使用体验与TCP上报

ESP8266现在几乎是STM32联网的标准搭档,唯一的麻烦是它的AT指令模块型号众多,固件版本也乱。我用的ESP-01S,经典模块,GPIO口就两个,适合做纯透传。第一次用的时候先接USB转TTL在PC上测试,确认AT固件支持AT+CIPSTARTAT+CIPSEND,再接到STM32上。

因为STM32的USART1是3.3V电平,ESP8266也是3.3V电平,理论上可以直连。但ESP-01S的WiFi天线和走线容易引入干扰,我实际使用中碰到过不少次通信异常,最后检查发现是电源纹波太大。ESP8266的供电必须干净,我的做法是单独用一个AMS1117-3.3给它供电,并在模块附近加一个470uF电解电容和0.1uF瓷片电容组合,实测掉线率降低了很多。

STM32和ESP8266之间我用的是透传模式,STM32往USART1发JSON格式字符串,ESP8266直接转发到TCP服务器。JSON格式如下:

{"dev":"W001","t":25.6,"h":58.4,"smoke":1.35,"lux":230}

服务器端我写了一个简单的Python TCP服务脚本,监听指定端口,收到数据后存MySQL并推送Web端展示。如果你不想自己写服务器,可以接巴法云、OneNET这类物联网平台,用MQTT协议上报,ESP8266刷MQTT固件就能直接连。不过如果用MQTT,STM32这边的代码需要做相应的MQTT协议打包,比TCP透传要多一点工作量。

4.2 上位机与数据可视化

做数据可视化,最省事的就是用Node-RED或者Grafana。我在本地Windows机器上装了Node-RED,弄一个MQTT Broker(Mosquitto),然后ESP8266通过MQTT发布主题warehouse/sensor,Node-RED订阅这个主题,把数据转存到InfluxDB,再用Grafana画曲线。全程都是开源工具,不花钱,效果却很像商业系统。

这里有个小的坑:ESP8266的MQTT库(PubSubClient)默认的KeepAlive是15秒,如果WiFi信号不稳定,很容易在两次心跳之间掉线,导致Server端显示“Connection Lost”。把KeepAlive调大到60秒,或者干脆在程序里加一个重连机制,掉线后自动重新连接。

4.3 报警推送:微信还是邮件?

报警推送是这个系统里比较受关注的一块。最简单粗暴的实现是让ESP8266直接通过HTTP GET请求第三方推送接口(比如Server酱、企业微信机器人)发消息到微信。这个方案的优点是实现起来只用一个HTTP请求,但缺点是依赖第三方服务,稳定性看运气。

更稳妥的方案是自建MQTT服务器,利用MQTT的遗嘱消息(Last Will and Testament)来检测设备离线。当STM32突然断电或者网络断开时,MQTT Broker会代替设备发布一条遗嘱主题,服务器端收到后立刻发报警邮件或短信。这个机制在工业级场景里比较常用,也值得在智能仓储这类项目里借鉴。

5. 常见问题与排查技巧实录

5.1 STM32延时函数卡死

这个问题的搜索结果非常多,说明大家都遇到过。我用HAL库的时候,习惯用HAL_Delay(),但这个函数在某些情况下会卡死,尤其是中断里调用HAL_Delay()的时候。原因是HAL_Delay依赖HAL_IncTick()来维护一个全局变量uwTick,而这个函数是在SysTick中断里被调用的。如果在高优先级中断里调用HAL_Delay,SysTick中断又恰好被阻塞,uwTick不再递增,延时函数就永远等不到目标值。

解决办法有两个:一是不要在中断里调用HAL_Delay,改成标志位+超时轮询;二是用DWT的Cycle Counter来做高精度延时,完全不依赖SysTick。DWT是Cortex-M3内核自带的调试单元,可以像定时器一样数CPU周期数,实现微秒级延时:

void delay_us(uint32_t us) { DWT->CYCCNT = 0; DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; uint32_t start = DWT->CYCCNT; uint32_t ticks = us * (SystemCoreClock / 1000000); while (DWT->CYCCNT - start < ticks); }

这段代码在F103上实测很稳,我后来把显示刷新和传感器读操作里的所有延时都换成了DWT版本。

5.2 ADC采样数值跳变

数值跳变是ADC应用里最典型的坑。我一开始直接用PA1读MQ135,发现数据在1.0V~1.5V之间来回跳,完全没法用。检查了硬件和软件,最终定位为两个问题:

第一,ADC参考电压不够稳定。STM32的VREF+内部连到VDDA,如果VDDA上有高频噪声,ADC结果肯定会抖。我在VDDA和VSSA之间加了LC滤波,效果立竿见影。

第二,采样时间不够长。MQ135的内阻有几十千欧,如果ADC采样时间太短,采样电容还没充满就开始转换了,误差会非常大。我在CubeMX里把采样时间从1.5周期改成了239.5周期,效果很明显。

另外,ADC结果还应该做软件滤波。我用了中位值平均滤波:连续采样10次,去掉最大最小值再求平均。处理之后的数据曲线平滑很多,也不会太迟钝。

5.3 OLED显示花屏与闪烁

0.96寸OLED在I2C模式下,偶尔会出现花屏,特别是在电机、继电器动作瞬间。排查了很久发现是电源瞬间跌落导致OLED内部控制器复位,但MCU没有复位,两边状态不一致了。解决办法是给OLED供电也加一个100uF电容,然后软件上每隔一段时间重新初始化一次OLED,比如每小时强制刷新一次初始化序列。虽然治标不治本,但能保证画面始终是正常的。

还有一个小技巧是,用I2C的OLED显示大数据量内容时,如果单次刷屏间隔太短,容易造成I2C总线拥堵。我的做法是把显示任务周期设为800ms~1s,每次只更新变化的部分(比如只刷新温湿度的数字区域),画面明显流畅了。

5.4 ESP8266通信不稳定一例

有一次客户反馈设备经常连不上服务器,我远程排查发现ESP8266经常处于“AT+CWJAP连接失败”的状态。后来过去现场才发现,仓库里有一台大功率对讲机,一发射就干扰WiFi。这个跟硬件不好没关系,纯粹是现场环境问题。解决办法是在ESP8266的电源脚上加强滤波、把天线位置抬高,并增加自动重连逻辑:每次上电先连WiFi,如果5秒没连上就重启ESP8266,再试。

另外,AT指令模式下的ESP8266有一个常见的坑:模块上电后会先输出一长串乱码式启动信息,如果你在MCU侧等待“ready”字符串再发指令,很容易因为时序问题失败。我的程序里直接用一个状态机:如果200ms内收到任何包含“OK”或“ready”的字符串,就认为模块已启动;如果收到“ERROR”或超时,就发送“AT+RST”重启模块。

6. 项目延展:从“能跑”到“好用”

6.1 增加更多传感器与执行器

这个系统的框架其实可以很容易扩展。比如仓储里要测VOC或二氧化碳,可以挂SGP30或SCD30;要测水浸,可以接一个水浸传感器到GPIO;要监测门禁状态,加一个干簧管就行了。因为主控的IO和I2C总线都有富余,我后来还加了一个GPS模块做位置定位(用于户外移动仓储箱),也是挂USART2上,和调试串口共用,只是调试时切换一下引脚复用。

6.2 本地存储:SD卡和Flash轮询记录

仓储数据讲究可追溯,光靠Grafana上的云端数据不够,断网时还需要本地存储。这块我实现了两个方案:一个是SD卡,通过SPI接口读写,文件系统用FatFS,每小时生成一个CSV文件,方便后用Excel分析;另一个是在STM32内部Flash里做一个环形缓冲区,保存最近24小时的关键数据,掉电不丢失。内部Flash方案更简单,不需要外挂硬件,但容量有限,只能存关键告警数据而不是全量数据。

6.3 低功耗与电池供电

如果你需要在没有外部电源的仓库里部署,低功耗设计就绕不开。STM32F103有STOP模式,可以把整体功耗降到微安级别。我的做法是:MCU默认进入STOP模式,靠RTC闹钟每5分钟唤醒一次,唤醒后采集数据、发送报文、再回STOP。传感器这边,SHT30本身有单次测量模式,也支持掉电模式,MQ135的加热电阻功耗大,只能从硬件上通过MOS管开关控制,测量时再通电。这样整体下来平均功耗能控制在10mA以内,用18650电池加太阳能板就能维持数周。

7. 写在最后的几点实战心得

做完这个项目之后,我最大的体会是:STM32项目真正做到最后,难的不是单片机本身,而是传感器数据怎么采集干净、通信怎么稳定、现场问题怎么排查。如果你正在做一个类似的项目,建议你在前期就把电源设计、传感器标定、通信协议结构想清楚,这几个地方一旦出问题,后面改起来成本非常高。

最后再分享一个小技巧:调试阶段不要直接上FreeRTOS,先在裸机while循环里把所有外设调通,再切换到RTOS。这样能大幅降低出bug排查的复杂度。等你把裸机版本跑通了,再引入任务划分、队列通信,整个系统会清晰很多。

这套系统到现在我已经迭代了三版,从最初的面包板飞线,到现在两层PCB加外壳,已经在朋友的一个小型零配件仓库里稳定运行了三个多月,只出现过两次ESP8266掉线自动重连的情况,其余时间都运行正常。它的硬件成本加起来不到两百块,却解决了一个需要专人每天跑几趟仓库去查看温湿度、检查烟雾报警的痛点。我觉得这种“花小钱解决真实问题”的嵌入式项目,才是STM32最具魅力的应用场景。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/4 13:03:15

云从科技校招软件测试笔试题全解析:从AI测试到用例设计

1. 考题全景&#xff1a;先看清云从这份卷子在筛什么人 云从科技2020校招的软件测试笔试题&#xff0c;放在当时和现在来看都挺有代表性的。近几年AI视觉赛道扩张快&#xff0c;云从作为“AI四小龙”里偏B端和G端落地的一家公司&#xff0c;测试岗位的笔试题不是单纯背概念就能…

作者头像 李华
网站建设 2026/9/6 11:53:20

142、阻抗控制:力位混合控制的机器人交互

142、阻抗控制:力位混合控制的机器人交互 调试台上那台六轴机械臂又抖了。不是那种高频震颤,是那种低频的、带着闷响的、像人打寒颤一样的抖动。我盯着示波器上力传感器那条曲线,它正在以2赫兹左右的频率来回甩,幅度还不小。旁边实习生问了一句:“老师,是不是增益调太大…

作者头像 李华
网站建设 2026/9/3 17:51:09

React生态常用库指南:路由、状态、UI层选型实战

React 本身并不是一个全家桶框架。它只接管视图层&#xff0c;路由、状态、请求、表单、样式、测试&#xff0c;甚至移动端适配&#xff0c;都要靠周边库拼出来。很多开发者在学到组件、Props、Hooks 之后&#xff0c;进入真实项目时会突然发现选择太多&#xff1a;同一个功能至…

作者头像 李华
网站建设 2026/9/4 10:22:28

DBeaver数据导入提速实战:线程与批次调优完整指南

DBeaver数据导入提速实战:线程与批次调优完整指南 【免费下载链接】dbeaver Free universal database tool and SQL client 项目地址: https://gitcode.com/GitHub_Trending/db/dbeaver 周五晚上十一点,你在 DBeaver 里盯着数据导入的进度条,几十万行的表已经爬了半个多…

作者头像 李华
网站建设 2026/9/4 22:13:43

基于Spring Boot的柑橘类水果管理系统设计与实现

简介&#xff1a;本资源是一款面向农业信息化管理场景的Java企业级应用源码&#xff0c;适用于水果种植企业、生鲜供应链公司及高校课程设计开发者&#xff0c;聚焦柑橘类水果从生产、库存到销售的全流程数字化管理。压缩包共554个文件&#xff0c;总大小39.79MB&#xff0c;涵…

作者头像 李华
网站建设 2026/9/6 9:24:46

Bulma 入门实战:662KB 的 CSS 文件,从引入到换色 10 分钟跑通

Bulma 入门实战&#xff1a;662KB 的 CSS 文件&#xff0c;从引入到换色 10 分钟跑通 【免费下载链接】bulma Modern CSS framework based on Flexbox 项目地址: https://gitcode.com/GitHub_Trending/bu/bulma 新建项目想给页面套一套现成的样式&#xff0c;又不想被一…

作者头像 李华