【STM32】综合练习——智能风扇系统
目录
0 前言
1 硬件准备
2 功能介绍
3 前置配置
3.1 时钟配置
3.2 文件配置
4 功能实现
4.1 按键功能
4.2 屏幕功能
4.3 调速功能
4.4 倒计时功能
4.5 摇头功能
4.6 测距待机功能
0 前言
由于时间关系,暂停详细更新,本文章中,只会记录重要代码,关于cubmx的配置以及引脚配置,请自行下载文件配置
【免费】基于STM32的多功能风扇资源-CSDN文库
1 硬件准备
STM32F103C8T6 * 1
面包板 * 1
OLED显示屏(SSD131590) * 1
RGB三色全彩LED模块 * 1
SG90舵机 * 1
HC-SR04超声波模块 * 1
130直流电机 * 1
风扇头 * 1
L298N电机驱动模块 * 1
直插2脚微动按键 * 2
USB转TTL模块-CH340模块 * 1
ST-LINK V2 * 1
杜邦线 (公对公、公对母、母对母)
跳线
2 功能介绍
(1)完成手动调节(按键)调节风扇三档转速(档位转速分别为30%、50%、80%)
(2)实现按键定时功能(短按一次时间加5秒,长按后倒计时开始,倒计时结束后风扇停止转动)
(3)实现风速不同档位显示,一档风速亮白灯,二档风速亮蓝灯,三档风速亮红灯,并通过OLED屏幕显示当前灯的颜色和定时时间(用英文和数字)
(4)实现通过串口显示当前风速
(5)以超声波为总开关控制系统运作(在20厘米内系统才可工作)
(6)利用舵机实现风扇摇头功能,并通过按键进行控制
3 前置配置
3.1 时钟配置
设置高速外部时钟:晶振

设置时钟频率为72Mhz

3.2 文件配置
修改文件名称以及选择IDE:MDK-ARM

为每一个外设单独生成一对.c/.h文件(模块化,方便管理)

4 功能实现
4.1 按键功能
在interrupt.c中使用回调函数判断定时器2,进行按键扫描(按键具体的功能不在此文件中)
// interrupt.cif(htim == &htim2) // button{keys[0].clickState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6); // left BUTTONkeys[1].clickState = HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5); // right BUTTONfor(int i=0; i<=1; i++){switch(keys[i].stage){case 0:{//judge clickif(keys[i].clickState == 0) keys[i].stage = 1; //go next stage}break;case 1:{if(keys[i].clickState == 0){// is true click// clear timekeys[i].pressTime = 0;// go next stagekeys[i].stage = 2;}}break;case 2:{if(keys[i].clickState == 1) // release click{//judge click which button and its typeif(keys[i].pressTime < 30){// short clickchooseButton(i, click);} else {// long clickchooseButton(i, longClick);}// reset stage keys[i].stage = 0;} else { // still click// time ++keys[i].pressTime++;}}break;}}}
按键具体的功能被拆分在了buttonFunciton.c中
从上到下依次为:
按键1的单击(调速)、按键1的长按(摇头)
按键2的单击(计时器加5)、按键2的长按(倒计时开始)
#include "buttonFunction.h"// to judge which button is press down
void chooseButton(uint8_t key, uint8_t type){switch(key){case 0: // button 1{if(type == 0){// click —— Toggle Speed Mode and Oled Update//WindSpeedspeedLevel++;speedLevel %= 4;SetWindSpeed();UsartSpeed();HomePage();} else if (type == 1){// long click —— Toggle Shaking ModeisShake = !isShake;if(isShake){HAL_TIM_Base_Start_IT(&htim1);shakeIsBegin = 1;} else {HAL_TIM_Base_Stop_IT(&htim1);shakeIsBegin = 0;}}}break;case 1: // button 2{if(type == 0){// click —— Count Down Number Add and Oled UpdatetimeCount += 5;HomePage();} else if (type == 1){// long click —— Count Down Startif(timeCount > 0){HAL_TIM_Base_Start_IT(&htim4);isBegin = 1;}}}break;}
}
4.2 屏幕功能
OLED使用Keysking的模块文件,这里就不展示了,使用方法见【STM32入门教程-2024】第14集 如何在OLED屏幕上挥毫_哔哩哔哩_bilibili
// page.c
#include "page.h"// ——————————————Init—————————————————
void PageInit(void){HAL_Delay(20); // 单片机启动比OLED上电快,需要延迟等待一下OLED_Init(); // 初始化OLED
}// ——————————————View——————————————————
void CopyrightPage(void) {OLED_NewFrame();OLED_DrawImage(5,1, &logoImg, OLED_COLOR_NORMAL);OLED_PrintString(85, 4, "创客", &font16x16, OLED_COLOR_NORMAL);OLED_PrintString(85, 24, "中心", &font16x16, OLED_COLOR_NORMAL);OLED_PrintString(85, 44, "出品", &font16x16, OLED_COLOR_NORMAL);OLED_ShowFrame();
}void HomePage(void){OLED_NewFrame();HomePageTitle();HomePageSpeedLight();if(timeCount > 0){HomePageCountDown();}OLED_ShowFrame();
}void SleepPage(void){OLED_NewFrame();OLED_PrintString(32, 10, "待机中...", &font16x16, OLED_COLOR_NORMAL);OLED_PrintString(4, 35, "~(p≧ w≦ q)~", &font12x12, OLED_COLOR_NORMAL);OLED_ShowFrame();
}// ————————————Component————————————————// Home Title
void HomePageTitle(void){OLED_PrintString(32, 10, "智能の扇", &font16x16, OLED_COLOR_NORMAL);
}// Home Body
void HomePageSpeedLight(void){StopAllLight();switch(speedLevel){case 0:{OLED_PrintString(50, 30, "STOP", &font16x16, OLED_COLOR_NORMAL);}break;case 1:{OLED_PrintString(46, 30, "WHITE", &font16x16, OLED_COLOR_NORMAL);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);}break;case 2:{OLED_PrintString(50, 30, "BLUE", &font16x16, OLED_COLOR_NORMAL);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET);}break;case 3:{OLED_PrintString(54, 30, "RED", &font16x16, OLED_COLOR_NORMAL);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET);}break;}
}// Home Bottom
void HomePageCountDown(void){char arr[40];sprintf(arr, "%d", timeCount);if(timeCount >= 10000){OLED_PrintString(46, 50, arr, &font16x16, OLED_COLOR_NORMAL);} else if(timeCount >= 1000){OLED_PrintString(50, 50, arr, &font16x16, OLED_COLOR_NORMAL);} else if(timeCount >= 100){OLED_PrintString(54, 50, arr, &font16x16, OLED_COLOR_NORMAL);} else if(timeCount >= 10){OLED_PrintString(58, 50, arr, &font16x16, OLED_COLOR_NORMAL);} else {OLED_PrintString(62, 50, arr, &font16x16, OLED_COLOR_NORMAL);}
}// Stop All Light
void StopAllLight(void){HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET);
}
// page.h
#ifndef __PAGE_H__
#define __PAGE_H__#include "main.h"
#include "string.h"
#include "oled.h"
#include "stdio.h"
#include "stdbool.h"// ——————————————Internal Api————————————————
// view
void PageInit(void);
void CopyrightPage(void);
void HomePage(void);
void SleepPage(void);// Component
void HomePageTitle(void);
void HomePageSpeedLight(void);
void HomePageCountDown(void);
void StopAllLight(void);
// ——————————————External Api————————————————
// windSpeed
extern uint8_t speedLevel;
extern uint8_t tempSpeedLevel;
// countDown
extern uint16_t timeCount;
// ——————————————————————————————————————————
#endif
4.3 调速功能
// windSpeed.c
#include "windSpeed.h"void SetWindSpeed(void){switch(speedLevel){case 0:{__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, StopSpeed);}break;case 1:{__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, LowSpeed);}break;case 2:{__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, MidSpeed);}break;case 3:{__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, HighSpeed);}break;}
}void UsartSpeed(void){sprintf(arr, "当前档位为:%d", speedLevel);HAL_UART_Transmit(&huart1, (uint8_t *)arr, sizeof(arr), HAL_MAX_DELAY);}
// windSpeed.h
#ifndef __WINDSPEED_H__
#define __WINDSPEED_H__#include "main.h"
#include "tim.h"
#include "usart.h"
#include <stdio.h>// ————————————Internal Api——————————————————#define StopSpeed 0
#define LowSpeed 300
#define MidSpeed 500
#define HighSpeed 800
uint8_t speedLevel = 0;
uint8_t tempSpeedLevel = 10;
void SetWindSpeed(void);
void UsartSpeed(void);
char arr[99];// ————————————External Api——————————————————// 0// ——————————————————————————————————————————#endif
4.4 倒计时功能
// interrupt.cif(htim == &htim4){ // Time Count Downif(timeCount > 1){timeCount--;} else {timeCount--;speedLevel = 0;SetWindSpeed();HAL_TIM_Base_Stop_IT(&htim4);isBegin = 0;HAL_TIM_Base_Stop_IT(&htim1);shakeIsBegin = 0;UsartSpeed();}HomePage();}
倒计时功能主要在interrupt中实现,此处只声明了个全局变量
// countDown.c
#include "countDown.h"
// countDown.h
#ifndef __COUNTDOWN_H__
#define __COUNTDOWN_H__#include "main.h"
#include "stdbool.h"
// ————————————Internal Api——————————————————uint16_t timeCount;
bool isBegin = 0;// ————————————External Api——————————————————// 0// ——————————————————————————————————————————#endif
4.5 摇头功能
舵机教程:【STM32】动画讲解输入捕获 并实现超声波测距_哔哩哔哩_bilibili
// shake.c
#include "shake.h"int shakeNumber = 1500; //500——2500 duty
bool shakeMode = 0;void shakeApi(void){if(shakeMode == 0){// forwardif(shakeNumber < 2500){shakeNumber += shakeSpeed;} else {shakeMode = 1;}__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, shakeNumber);} else {// reverseif(shakeNumber > 500){shakeNumber -= shakeSpeed;} else {shakeMode = 0;}__HAL_TIM_SET_COMPARE(&htim1, TIM_CHANNEL_1, shakeNumber);}}
// shake.h
#ifndef __SHAKE_H__
#define __SHAKE_H__#include "main.h"
#include "tim.h"
#include "stdbool.h"// ————————————Internal Api——————————————————#define shakeSpeed 10 // 5(slow) 10(normal) 20(fast) 100(very fast)
void shakeApi(void);
bool shakeIsBegin = 0;// ————————————External Api——————————————————// 0// ——————————————————————————————————————————#endif
启用中断:
// interrupt.c
if(htim == &htim1){ // ShakeshakeApi();
}
4.6 测距待机功能
为了使系统正常工作时(20cm以内) ,能继续进行上一次的数据(如倒计时从上一次离开开始,继续倒计时),这里并没有直接修改存储该数据的变量,而是直接将所有功能暂停(具体实现见StopAll函数),恢复时再读取存储数据的变量
// ultrasound.c
#include "ultrasound.h"void TriggerUltrasound(void){// Send trigger signalHAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_SET);
// HAL_Delay(1);for(uint32_t i=0; i<11; i++);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_12, GPIO_PIN_RESET);// Reset counter__HAL_TIM_SET_COUNTER(&htim3, 0);// WaitHAL_Delay(50);
}void MeasurementDistance(void){timeCountBefore = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_1);timeCountAfter = HAL_TIM_ReadCapturedValue(&htim3, TIM_CHANNEL_2);distance = (timeCountAfter - timeCountBefore) * 0.034 / 2;
}void StopAll(void){// stop all lightStopAllLight();// stop wideSpeed__HAL_TIM_SET_COMPARE(&htim2, TIM_CHANNEL_1, 0);// stop count downHAL_TIM_Base_Stop_IT(&htim4);// stop shakeHAL_TIM_Base_Stop_IT(&htim1);// sleep pageSleepPage();
}void StartAll(void){// start count downif(timeCount > 0 && isBegin){HAL_TIM_Base_Start_IT(&htim4);}// start shakeif(shakeIsBegin){HAL_TIM_Base_Start_IT(&htim1);}// start wideSpeedSetWindSpeed();// home page - start all lightHomePage();
}
// ultrasound.h
#ifndef __ULTRASOUND_H__
#define __ULTRASOUND_H__#include "main.h"
#include "tim.h"
#include "stdbool.h"// ————————————Internal Api——————————————————uint16_t timeCountBefore;
uint16_t timeCountAfter;
float distance;
void TriggerUltrasound(void);
void MeasurementDistance(void);
void StopAll(void);
void StartAll(void);// ————————————External Api——————————————————// page - light
extern void HomePage(void);
extern void SleepPage(void);
extern void StopAllLight(void);
// windSpeed
extern uint8_t speedLevel;
extern void SetWindSpeed(void);
// count down
extern uint16_t timeCount;
extern bool isBegin;
// shake
extern bool shakeIsBegin;
// ——————————————————————————————————————————#endif
输入捕获中断:
测距思想:一个通道读上升沿,一组的另一个通道读下降沿,并且在读到下降沿的时候进行中断
教程:【STM32】动画讲解输入捕获 并实现超声波测距_哔哩哔哩_bilibili
// interrupt.c
void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim){if(htim == &htim3 && htim -> Channel == HAL_TIM_ACTIVE_CHANNEL_2){ // ultrasound// Measurement Ultrasound DistanceMeasurementDistance();
// sprintf(aeee, "%f", distance);
// HAL_UART_Transmit(&huart1, (uint8_t *)aeee, sizeof(aeee), HAL_MAX_DELAY);if(distance > 22){// sleepStopAll();} else if(distance >= 0 && distance <= 22){// normalStartAll();}}}相关文章:
【STM32】综合练习——智能风扇系统
目录 0 前言 1 硬件准备 2 功能介绍 3 前置配置 3.1 时钟配置 3.2 文件配置 4 功能实现 4.1 按键功能 4.2 屏幕功能 4.3 调速功能 4.4 倒计时功能 4.5 摇头功能 4.6 测距待机功能 0 前言 由于时间关系,暂停详细更新,本文章中,…...
MyBatis 动态 SQL 使用详解
🌟 一、什么是动态 SQL? 动态 SQL 是指根据传入参数,动态拼接生成 SQL 语句,不需要写多个 SQL 方法。MyBatis 提供了 <if>、<choose>、<foreach>、<where> 等标签来实现这类操作 ✅ 二、动态 SQL 的优点…...
【重装系统】大白菜自制U盘装机,备份C盘数据,解决电脑启动黑屏/蓝屏
1. 准备 U 盘 U 盘容量至少 8G,备份 U 盘的数据(后期会格式化) 2. 从微软官网下载操作系统镜像 https://www.microsoft.com/zh-cn/software-download/windows11 3. 下载安装大白菜 https://www.alipan.com/s/33RVnKayUfY 4. 插入 U 盘&#…...
vue实现目录锚点且滚动到指定区域时锚点自动回显——双向锚点
最近在用vue写官网,别问我为什么用vue写官网,问就是不会jq。。。。vue都出现11年了。。。 左侧目录:点击时,右侧区域可以自动滚动到指定的位置。 右侧区域手动滚动时,左侧锚点可以自动切换到对应的目录上 从而实现…...
python——正则表达式
一、简介 在 Python 中,正则表达式主要通过 re 模块实现,用于字符串的匹配、查找、替换等操作。 二、Python的re模块 使用前需要导入: import re 三、常用方法 方法描述re.match(pattern, string)从字符串开头匹配,返回第一个匹…...
Flutter Invalid constant value.
0x00 问题 参数传入变量,报错! 代码 const Padding(padding: EdgeInsets.all(20),child: GradientProgressIndicator(value: _progress), ),_progress 参数报错:Invalid constant value. 0x01 原因 这种情况,多发生于ÿ…...
libev实现Io复用及定时器事件服务器
客户端和服务器都绑定在了enp2s0网卡,需要SERVER_IP和SERVER_PORT改为其ip,注意不能是127.0.0.1,因为这个是lo虚拟网口。 安装libev sudo apt-get install libev-dev客户端: #include <iostream> #include <string>…...
【精品PPT】2025固态电池知识体系及最佳实践PPT合集(36份).zip
精品推荐,2025固态电池知识体系及最佳实践PPT合集,共36份。供大家学习参考。 1、中科院化学所郭玉国研究员:固态金属锂电池及其关键材料.pdf 2、中科院物理所-李泓固态电池.pdf 3、全固态电池技术研究进展.pdf 4、全固态电池生产工艺.pdf 5、…...
如何计算设备电池工作时长?
目录 【mAh(毫安时)计算方法】 【Wh(瓦时)计算方法】 【为什么仅用电流(mA)和时间(h)就能计算电池使用时长(mAh)?】 1. mAh 的本质是“电荷量…...
抽象类及其特性
目录 1、概念2、语法3、特性4、作用 1、概念 在面向对象中,所有对象都是通过类来描述的,但是并不是所有的类都可以用来描述对象。比如下述例子中的 Animal 类,Dog 类和 Cat 类是 Animal 类的子类,可以分别描述小狗和小猫…...
【教程】xrdp修改远程桌面环境为xfce4
转载请注明出处:小锋学长生活大爆炸[xfxuezhagn.cn] 如果本文帮助到了你,欢迎[点赞、收藏、关注]哦~ 目录 xfce4 vs GNOME对比 配置教程 1. 安装 xfce4 桌面环境 2. 安装 xrdp 3. 配置 xrdp 使用 xfce4 4. 重启 xrdp 服务 5. 配置防火墙ÿ…...
利用python从零实现Byte Pair Encoding(BPE):NLP 中的“变形金刚”
BPE:NLP 界的“变形金刚”,从零开始的奇幻之旅 在自然语言处理(NLP)的世界里,有一个古老而神秘的传说,讲述着一种强大的魔法——Byte Pair Encoding(BPE)。它能够将普通的文本“变形…...
部署redis cluster
一。在所有的主机里面设置密码和文件地址 vi /etc/redis/6379.conf 注释:登陆则要使用auth 123456才可以进入redis 配置文件地址和超时时间 二。创建集群:上面主机为master,下面为slave,master和slave会随机分配 先写主节点&…...
Android 11 (API 30) 及更高版本中,查询的特定应用商店包,无需动态请求权限处理
在 Android 11 (API 30) 及更高版本中,通过在 AndroidManifest.xml 中添加 <queries> 元素声明需要查询的特定应用商店包名后: 1. 不需要额外请求权限 (如 QUERY_ALL_PACKAGES )即可查询这些应用的安装状态 2. 这是 Googl…...
基于springboot钻孔数据管理系统的设计与实现(源码+lw+部署文档+讲解),源码可白嫖!
摘要 本钻孔数据管理系统采用B/S架构,数据库是MySQL,网站的搭建与开发采用了先进的Java语言、Hadoop、数据可视化技术进行编写,使用了Spring Boot框架。该系统从两个对象:由管理员和用户来对系统进行设计构建。用户主要功能包括&…...
SpringBoot和微服务学习记录Day2
微服务 微服务将单体应用分割成更小的的独立服务,部署在不同的服务器上。服务间的关联通过暴露的api接口来实现 优点:高内聚低耦合,一个模块有问题不影响整个应用,增加可靠性,更新技术方便 缺点:增加运维…...
4.9复习记
1.地宫取宝--记忆化搜索,可以先写void dfs,然后在改成ll 形式的,边界条件return 0/1; 记忆化数组与dfs元素保持一致,记得记忆化剪枝 这个题特殊在value可能是0,不取的时候应该记为-1 https://mpbeta.cs…...
LinuxSocket套接字编程
1.介绍函数使用 1.创建套接字 int socket(int domain, int type, int protocol); domain:指定协议族,如AF_INET(IPv4)或AF_INET6(IPv6)。 type:指定套接字类型,如SOCK_DGRAM&#…...
动态科技感html导航网站源码
源码介绍 动态科技感html导航网站源码,这个设计完美呈现了科幻电影中的未来科技界面效果,适合展示技术类项目或作为个人作品集的入口页面,自适应手机。 修改卡片中的链接指向你实际的HTML文件可以根据需要调整卡片内容、图标和颜色要添加更…...
Java进阶版线程池(超详细 )
线程池 线程池工具类 Executors Executors 是 Java 提供的一个工具类,它包含了多个静态方法,能够方便地创建不同类型的线程池。 newFixedThreadPool 创建一个固定大小的线程池,线程池中的线程数量固定,当有新任务提…...
每日算法:洛谷U535992 J-C 小梦的宝石收集(双指针、二分)
题目描述 小梦有 n 颗能量宝石,其中第 i 颗的能量为 ai,但这些能量宝石十分不稳定,随时有可能发生崩坏,导致他们全部消失! 小梦想要留住宝石们,不希望他们发生崩坏,同时他发现:如…...
YOLOv11训练中精准率召回率与mAP@0.5的动态变化分析
目标检测模型的训练过程涉及多个关键性能指标和损失函数的变化,这些数据能够直观反映模型的收敛速度、最终精度以及改进效果。本文旨在通过绘制YOLOv11模型在训练过程中的精准率(Precision)、召回率(Recall)、mAP0.5 、…...
Java常用工具算法-6--秘钥托管云服务AWS KMS
前言: 之前我们介绍了一些常用的加密算法(如:对称加密AES,非对称加密RSA,ECC等),不论是哪一种都需要涉及到秘钥的管理。通常的做法都是把秘钥放到配置文件中进行配置,但是对于一些高…...
11. Langchain输出解析(Output Parsers):从自由文本到结构化数据
引言:从"自由发挥"到"规整输出" 2025年某金融机构的合同分析系统升级前,AI生成的合同摘要需人工二次处理达47分钟/份。引入LangChain结构化解析后,处理时间缩短至3分钟。本文将详解如何用LangChain的解析器,…...
docker stack常用命令
1、Docker Stack介绍 Docker Stack管理swarm堆栈与Swarm协调器配合使用,是Docker Swarm环境中用于管理一组相关服务的工具。它使得在Swarm集群中部署、管理和扩展一组相互关联的服务变得简单。主要用于定义和编排容器化应用的多个服务。以下是Docker Stack的一些关…...
python reportlab模块----操作PDF文件
reportlab模块----操作PDF文件 一. 安装模块二. reportlab相关介绍三. 扩展canvas类四. 水平写入完整代码五. 垂直写入完整代码 一. 安装模块 pip install reportlab二. reportlab相关介绍 # 1. letter 生成A4纸张尺寸 from reportlab.lib.pagesizes import letter print(let…...
解锁基因密码之重测序(从测序到分析)
在生命科学的奇妙世界中,基因恰似一本记录着生命奥秘的“天书”,它承载着生物体生长、发育、衰老乃至疾病等一切生命现象的关键信息。而重测序技术,则是开启基因“天书”奥秘的一把神奇钥匙。 试想,你手中有一本经典书籍的通用版…...
TQTT_KU5P开发板教程---QSFP25G光口回环测试
文档实现功能介绍 本文档通过一个叫做ibert的IP,实现25G光口回环测试例子。工程新建方法请参考文档《流水灯》,其中只是将文件名进行修改。 Vivado 起始页(或 file-->Project-->New 创建新工程(Create New Project) 向导起始页面 点…...
JVM虚拟机篇(七):JVM垃圾回收器全面解析与G1深度探秘及四种引用详解
JVM垃圾回收器全面解析与G1深度探秘及四种引用详解 JVM虚拟机(七):JVM垃圾回收器全面解析与G1深度探秘及四种引用详解一、JVM有哪些垃圾回收器1. Serial回收器2. ParNew回收器3. Parallel Scavenge回收器4. Serial Old回收器5. Parallel Old回…...
柑橘病虫害图像分类数据集OrangeFruitDaatset-8600
文章目录 1. 前言2. 数据类别介绍3. 数据集地址 1. 前言 柑橘,作为水果界的 “宠儿”,不仅以其酸甜可口的味道深受大众喜爱,更是在全球水果产业中占据着举足轻重的地位。无论是早餐中的一杯橙汁,还是下午茶里的柑橘甜点ÿ…...
