news 2026/9/30 11:52:03

STM32 进阶封神之路(二十):ADC 实战全攻略 —— 光敏 + 烟雾传感器采集 + 阈值报警(库函数 + 代码落地)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
STM32 进阶封神之路(二十):ADC 实战全攻略 —— 光敏 + 烟雾传感器采集 + 阈值报警(库函数 + 代码落地)

STM32 进阶封神之路(二十):ADC 实战全攻略 —— 光敏 + 烟雾传感器采集 + 阈值报警(库函数 + 代码落地)

上一篇我们吃透了 ADC 的底层原理、核心参数和初始化流程,这一篇聚焦实战落地 —— 基于 STM32F103,结合光敏电阻(光照检测)和 MQ2 烟雾传感器(气体浓度检测),从硬件连接、代码解析、多通道采集,到中断优化、阈值报警,手把手带你实现 “模拟信号采集→数字转换→外设联动” 的完整闭环,所有代码基于提供的adc.h扩展,可直接编译运行!

本文覆盖 “单通道采集→多通道切换→中断非阻塞采集→阈值报警” 全场景,同时解析实战中的关键细节和避坑要点,让你不仅 “会配置 ADC”,更能 “灵活应用 ADC” 到传感器数据采集项目中!

一、实战准备:硬件环境与核心需求

1. 硬件清单

  • 主控:STM32F103C8T6 最小系统板;
  • 传感器:光敏电阻模块(电压型)、MQ2 烟雾传感器模块(电压型);
  • 外设:LED(指示光照状态)、蜂鸣器(烟雾报警);
  • 辅助硬件:10KΩ 下拉电阻(光敏电阻分压)、USB-TTL 模块(串口打印)、杜邦线、面包板。

2. 核心实战需求

  • 单通道采集:通过 ADC1_CH5(PA5)采集光敏电阻电压,转换为光照强度;
  • 多通道采集:切换至 ADC1_CH11(PC1)采集 MQ2 烟雾传感器电压,转换为烟雾浓度;
  • 阈值联动:光照过暗时 LED 点亮,烟雾浓度超标时蜂鸣器报警;
  • 数据输出:串口打印采集的 ADC 值和对应电压值,实时监控状态;
  • 优化拓展:实现 ADC 中断非阻塞采集,避免占用主循环资源。

3. 关键硬件连接(核心!接线错误导致采集失败)

(1)传感器与 STM32 连接

表格

模块传感器引脚STM32 引脚连接说明
光敏电阻模块VCC3.3V传感器供电(避免 5V,防止 ADC 引脚过载)
光敏电阻模块GNDGND共地(采集稳定的前提)
光敏电阻模块AO(模拟输出)PA5(ADC1_CH5)模拟信号输入,需配置为模拟输入模式
MQ2 烟雾传感器VCC5VMQ2 需 5V 供电才能正常工作
MQ2 烟雾传感器GNDGND共地
MQ2 烟雾传感器AO(模拟输出)PC1(ADC1_CH11)模拟信号输入,需配置为模拟输入模式
(2)外设与 STM32 连接

表格

外设引脚STM32 引脚连接说明
LED正极(串 1KΩ 电阻)PB0推挽输出,低电平点亮
LED负极GND
蜂鸣器VCC3.3V有源蜂鸣器供电
蜂鸣器GNDPB1推挽输出,低电平触发报警
(3)分压电路说明(光敏电阻)

光敏电阻的阻值随光照强度变化(光照越强,阻值越小),需通过分压电路将阻值变化转换为电压变化,才能被 ADC 采集:

  • 电路结构:3.3V → 光敏电阻 → PA5 → 10KΩ 下拉电阻 → GND;
  • 电压变化:光照越强→光敏电阻阻值越小→PA5 引脚电压越高→ADC 采样值越大;
  • 关键注意:必须串联下拉电阻,否则 PA5 引脚悬空,无法采集稳定电压。

二、核心代码解析:从配置到采集全流程

基于提供的adc.h代码,补充外设初始化、中断配置、主函数逻辑,形成完整可运行代码:

1. 头文件与全局变量定义

c

运行

#include "adc.h" #include "stm32f10x.h" #include <stdio.h> // ADC采样值全局变量 uint16_t ADC_LIGHT_VALUE = 0; // 光敏电阻采样值 uint16_t ADC_MQ2_VALUE = 0; // MQ2烟雾传感器采样值 // 阈值定义(可根据实际硬件调整) #define Light_threshold 2000 // 光照阈值(采样值≤2000→光照过暗) #define MQ2_threshold 3000 // 烟雾阈值(采样值≥3000→浓度超标) // 串口发送函数(printf重定向用) void USART1_SendByte(uint8_t data) { while(USART_GetFlagStatus(USART1, USART_FLAG_TXE) == RESET); USART_SendData(USART1, data); } // printf重定向 int fputc(int ch, FILE *f) { USART1_SendByte((uint8_t)ch); return ch; } // 串口初始化(115200bps 8N1,用于打印采集数据) void USART1_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; USART_InitTypeDef USART_InitStruct; NVIC_InitTypeDef NVIC_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_USART1, ENABLE); // PA9(TX)复用推挽输出 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_9; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_AF_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOA, &GPIO_InitStruct); // PA10(RX)浮空输入 GPIO_InitStruct.GPIO_Pin = GPIO_Pin_10; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStruct); USART_InitStruct.USART_BaudRate = 115200; USART_InitStruct.USART_WordLength = USART_WordLength_8b; USART_InitStruct.USART_StopBits = USART_StopBits_1; USART_InitStruct.USART_Parity = USART_Parity_No; USART_InitStruct.USART_HardwareFlowControl = USART_HardwareFlowControl_None; USART_InitStruct.USART_Mode = USART_Mode_Tx | USART_Mode_Rx; USART_Init(USART1, &USART_InitStruct); USART_Cmd(USART1, ENABLE); }

2. 外设初始化(LED + 蜂鸣器)

c

运行

// LED初始化(PB0,推挽输出) void LED_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_SetBits(GPIOB, GPIO_Pin_0); // 初始熄灭 } // 蜂鸣器初始化(PB1,推挽输出) void Beep_Init(void) { GPIO_InitTypeDef GPIO_InitStruct; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1; GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(GPIOB, &GPIO_InitStruct); GPIO_SetBits(GPIOB, GPIO_Pin_1); // 初始关闭(高电平) } // LED控制函数(提供给Light_Handle调用) void LED4_On(void) { GPIO_ResetBits(GPIOB, GPIO_Pin_0); // 低电平点亮 } void LED4_Off(void) { GPIO_SetBits(GPIOB, GPIO_Pin_0); // 高电平熄灭 } // 蜂鸣器控制函数(提供给MQ2_Handle调用) void Beep_ON(void) { GPIO_ResetBits(GPIOB, GPIO_Pin_1); // 低电平触发 } void Beep_OFF(void) { GPIO_SetBits(GPIOB, GPIO_Pin_1); // 高电平关闭 }

3. ADC 核心配置函数解析(ADC_Config)

提供的ADC_Config函数已完成 ADC 初始化核心流程,重点解析关键细节:

c

运行

void ADC_Config(void) { Light_GPIO(); // 初始化光敏电阻GPIO(PA5模拟输入) MQ2_GPIO(); // 初始化MQ2 GPIO(PC1模拟输入) // 1. 开启ADC1时钟(APB2总线) RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE); // 2. ADC时钟分频(APB2=72MHz→ADC时钟=12MHz,≤14MHz上限) RCC_ADCCLKConfig(RCC_PCLK2_Div6); // 3. 定义ADC初始化结构体 ADC_InitTypeDef ADC_InitStruct={0}; // 4. 结构体参数配置(关键!决定ADC工作模式) ADC_InitStruct.ADC_ContinuousConvMode = DISABLE; // 单次转换模式(启动一次,转换一次) ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right; // 右对齐(12位数据存储在bit0~bit11) ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None; // 软件触发(手动启动转换) ADC_InitStruct.ADC_Mode = ADC_Mode_Independent; // ADC1独立工作模式 ADC_InitStruct.ADC_NbrOfChannel = 1; // 单次转换1个通道 ADC_InitStruct.ADC_ScanConvMode = DISABLE; // 非扫描模式(单通道无需扫描) // 5. 写入配置参数到ADC1 ADC_Init(ADC1,&ADC_InitStruct); // 6. 使能ADC1 ADC_Cmd(ADC1,ENABLE); // 7. ADC校准(提高采集精度,不可省略) ADC_ResetCalibration(ADC1); // 复位校准寄存器 while(ADC_GetResetCalibrationStatus(ADC1)); // 等待复位完成 ADC_StartCalibration(ADC1); // 启动校准 while(ADC_GetCalibrationStatus(ADC1)); // 等待校准完成 }

4. 单通道采集函数解析

(1)光敏电阻采集(ADC_Read_Light)

c

运行

void ADC_Read_Light(void) { // 1. 配置采集通道:ADC1_CH5(PA5),转换顺序1,采样时间28.5个时钟周期 ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_28Cycles5); // - 采样时间选择:28.5个周期兼顾精度和速度,避免过短导致采样不稳定 // 2. 软件启动ADC转换 ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 3. 等待转换完成(查询EOC标志位) while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)==RESET); // 4. 读取转换结果(12位采样值,范围0~4095) ADC_LIGHT_VALUE=ADC_GetConversionValue(ADC1); // 5. 清除转换完成标志位(读取ADC_DR后自动清除,此处手动清除更稳妥) ADC_ClearFlag(ADC1, ADC_FLAG_EOC); // 6. 串口打印采样值和对应电压值(转换公式:电压=采样值×3.3V/4096) float light_voltage = (ADC_LIGHT_VALUE / 4096.0) * 3.3; printf("光照强度 - ADC值:%d,电压:%.2fV\r\n", ADC_LIGHT_VALUE, light_voltage); // 7. 光照阈值判断,控制LED Light_Handle(); }
(2)MQ2 烟雾传感器采集(ADC_Read_MQ2)

c

运行

void ADC_Read_MQ2(void) { // 1. 切换通道:ADC1_CH11(PC1),其他参数与光敏电阻一致 ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_28Cycles5); // 2. 启动转换 ADC_SoftwareStartConvCmd(ADC1, ENABLE); // 3. 等待转换完成 while(ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC)==RESET); // 4. 读取采样值 ADC_MQ2_VALUE=ADC_GetConversionValue(ADC1); // 5. 清除标志位 ADC_ClearFlag(ADC1, ADC_FLAG_EOC); // 6. 串口打印 float mq2_voltage = (ADC_MQ2_VALUE / 4096.0) * 3.3; printf("烟雾浓度 - ADC值:%d,电压:%.2fV\r\n", ADC_MQ2_VALUE, mq2_voltage); // 7. 烟雾阈值判断,控制蜂鸣器 MQ2_Handle(); }

5. 阈值处理函数(Light_Handle+MQ2_Handle)

c

运行

// 光照阈值处理:ADC值≤2000→光照过暗→LED点亮 void Light_Handle(void) { if(ADC_LIGHT_VALUE <= Light_threshold) { LED4_On(); printf("光照过暗,LED已点亮\r\n"); } else { LED4_Off(); printf("光照充足,LED已熄灭\r\n"); } } // 烟雾阈值处理:ADC值≥3000→浓度超标→蜂鸣器报警 void MQ2_Handle(void) { if(ADC_MQ2_VALUE >= MQ2_threshold) { Beep_ON(); printf("烟雾浓度超标!蜂鸣器报警\r\n"); } else { Beep_OFF(); printf("烟雾浓度正常,蜂鸣器关闭\r\n"); } }

6. 主函数:实现循环采集与多通道切换

c

运行

int main(void) { // 初始化外设:串口(打印)→ LED→ 蜂鸣器→ ADC USART1_Init(); LED_Init(); Beep_Init(); ADC_Config(); printf("ADC传感器采集系统初始化成功!\r\n"); printf("阈值配置:光照过暗≤%d(ADC值),烟雾超标≥%d(ADC值)\r\n", Light_threshold, MQ2_threshold); printf("=======================================\r\n\r\n"); while(1) { // 采集光敏电阻数据(间隔1秒) ADC_Read_Light(); delay_ms(1000); // 采集MQ2烟雾传感器数据(间隔1秒) ADC_Read_MQ2(); delay_ms(1000); printf("=======================================\r\n\r\n"); } } // 简单延时函数(控制采集间隔) void delay_ms(uint32_t ms) { uint32_t i, j; for(i = 0; i < ms; i++) { for(j = 0; j < 1000; j++); } }

三、进阶优化:ADC 中断非阻塞采集(避免主循环阻塞)

上述代码采用 “查询式采集”,采集过程中主循环会阻塞等待转换完成。优化为 “中断式采集” 后,ADC 转换完成后触发中断,主循环可并行执行其他任务,效率更高:

1. 中断配置扩展(添加到ADC_Config函数末尾)

c

运行

// ADC中断配置(转换完成触发中断) void ADC_Interrupt_Config(void) { NVIC_InitTypeDef NVIC_InitStruct; // 使能ADC1转换完成中断 ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE); // 配置NVIC中断优先级 NVIC_InitStruct.NVIC_IRQChannel = ADC1_2_IRQn; // ADC1和ADC2共享中断通道 NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 1; NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0; NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStruct); }

2. 中断服务函数(处理转换结果)

c

运行

// 定义当前采集通道标志 typedef enum { ADC_CHANNEL_LIGHT = 0, ADC_CHANNEL_MQ2 } ADC_Channel_TypeDef; ADC_Channel_TypeDef current_channel = ADC_CHANNEL_LIGHT; // ADC1/2中断服务函数 void ADC1_2_IRQHandler(void) { float voltage; // 检查ADC1转换完成中断标志 if(ADC_GetITStatus(ADC1, ADC_IT_EOC) != RESET) { if(current_channel == ADC_CHANNEL_LIGHT) { // 读取光敏电阻采样值 ADC_LIGHT_VALUE = ADC_GetConversionValue(ADC1); voltage = (ADC_LIGHT_VALUE / 4096.0) * 3.3; printf("光照强度(中断)- ADC值:%d,电压:%.2fV\r\n", ADC_LIGHT_VALUE, voltage); Light_Handle(); // 切换到MQ2通道,下一次中断采集烟雾数据 ADC_RegularChannelConfig(ADC1, ADC_Channel_11, 1, ADC_SampleTime_28Cycles5); current_channel = ADC_CHANNEL_MQ2; } else { // 读取MQ2采样值 ADC_MQ2_VALUE = ADC_GetConversionValue(ADC1); voltage = (ADC_MQ2_VALUE / 4096.0) * 3.3; printf("烟雾浓度(中断)- ADC值:%d,电压:%.2fV\r\n", ADC_MQ2_VALUE, voltage); MQ2_Handle(); // 切换回光敏电阻通道 ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_28Cycles5); current_channel = ADC_CHANNEL_LIGHT; } // 清除中断标志位 ADC_ClearITPendingBit(ADC1, ADC_IT_EOC); // 启动下一次转换(连续采集) ADC_SoftwareStartConvCmd(ADC1, ENABLE); } }

3. 中断模式主函数

c

运行

int main(void) { USART1_Init(); LED_Init(); Beep_Init(); ADC_Config(); ADC_Interrupt_Config(); // 初始化ADC中断 printf("ADC中断采集系统初始化成功!\r\n"); printf("=======================================\r\n\r\n"); // 启动第一次转换(光敏电阻通道) ADC_RegularChannelConfig(ADC1, ADC_Channel_5, 1, ADC_SampleTime_28Cycles5); ADC_SoftwareStartConvCmd(ADC1, ENABLE); while(1) { // 主循环可并行执行其他任务(如LED流水灯、串口通信) // 此处仅做示例,无其他任务 } }

四、实验现象与数据验证

1. 正常环境下的串口输出(查询式采集)

plaintext

ADC传感器采集系统初始化成功! 阈值配置:光照过暗≤2000(ADC值),烟雾超标≥3000(ADC值) ======================================= 光照强度 - ADC值:3500,电压:2.88V 光照充足,LED已熄灭 烟雾浓度 - ADC值:1500,电压:1.23V 烟雾浓度正常,蜂鸣器关闭 ======================================= 光照强度 - ADC值:3480,电压:2.86V 光照充足,LED已熄灭 烟雾浓度 - ADC值:1520,电压:1.25V 烟雾浓度正常,蜂鸣器关闭 =======================================

2. 特殊场景验证

(1)光照过暗场景

用手遮挡光敏电阻,串口输出:

plaintext

光照强度 - ADC值:1800,电压:1.48V 光照过暗,LED已点亮
  • 现象:LED 点亮,符合阈值判断逻辑。
(2)烟雾超标场景

向 MQ2 传感器吹气(模拟烟雾),串口输出:

plaintext

烟雾浓度 - ADC值:3200,电压:2.62V 烟雾浓度超标!蜂鸣器报警
  • 现象:蜂鸣器持续报警,移开传感器后恢复正常。

3. 中断模式输出特点

  • 无需手动调用采集函数,中断自动触发,主循环无阻塞;
  • 采集速度更快,数据更新更及时,适合高频采集场景。

五、ADC 实战避坑指南(10 + 高频错误)

1. 采集值为 0 或 4095(满量程),无变化

  • 原因 1:GPIO 模式配置错误(未设为模拟输入模式);解决:确保Light_GPIO和MQ2_GPIO中GPIO_Mode = GPIO_Mode_AIN,而非普通输入模式;
  • 原因 2:传感器接线错误(VCC/GND 接反或未接);解决:重新检查传感器供电和共地,确保 VCC 接 3.3V(光敏)/5V(MQ2),GND 共地;
  • 原因 3:分压电路缺失(光敏电阻未串联下拉电阻);解决:在光敏电阻和 GND 之间串联 10KΩ 下拉电阻,否则 PA5 引脚悬空,采集值固定为 0 或 4095。

2. 采样值波动过大(跳变超过 100)

  • 原因 1:采样时间过短(未给电容充足充电时间);解决:将采样时间从ADC_SampleTime_1Cycles5改为ADC_SampleTime_28Cycles5或更长;
  • 原因 2:电源纹波过大(传感器供电不稳定);解决:在传感器 VCC 引脚旁并联 0.1μF 陶瓷电容,滤除高频纹波;
  • 原因 3:环境干扰(传感器靠近电源模块或高频信号线);解决:重新布局面包板,传感器远离 5V 电源和 USB 线。

3. 多通道采集时数据混淆(光照值与烟雾值颠倒)

  • 原因:通道配置错误(ADC_Channel_5与ADC_Channel_11混淆);解决:确保ADC_Read_Light配置ADC_Channel_5(PA5),ADC_Read_MQ2配置ADC_Channel_11(PC1),对应传感器接线正确。

4. 中断采集时中断不响应

  • 原因 1:未使能 ADC 中断(ADC_ITConfig未调用);解决:在ADC_Interrupt_Config中调用ADC_ITConfig(ADC1, ADC_IT_EOC, ENABLE);
  • 原因 2:NVIC 未配置 ADC 中断通道;解决:配置NVIC_IRQChannel = ADC1_2_IRQn(ADC1 和 ADC2 共享中断通道);
  • 原因 3:未清除中断标志位;解决:在中断服务函数中调用ADC_ClearITPendingBit(ADC1, ADC_IT_EOC)。

5. 采样值与实际电压不符(误差超过 0.2V)

  • 原因 1:未进行 ADC 校准;解决:确保ADC_Config中校准步骤完整(复位校准→启动校准→等待完成);
  • 原因 2:参考电压不稳定(VDDA 未滤波);解决:在 STM32 VDDA 引脚(若有)旁并联 1μF 电解电容,提高参考电压稳定性;
  • 原因 3:数据对齐方式错误(左对齐未修正);解决:若改为左对齐,需将采样值右移 4 位(ADC_GetConversionValue(ADC1) >> 4)再计算电压。

六、总结:ADC 实战核心要点与进阶方向

1. 核心要点回顾

  • ADC 实战核心流程:GPIO 模拟输入配置→ADC 时钟分频→模式配置→校准→通道配置→启动转换→读取值→数据处理;
  • 关键函数:ADC_RegularChannelConfig(通道配置)、ADC_SoftwareStartConvCmd(启动转换)、ADC_GetConversionValue(读取采样值);
  • 多通道采集:通过切换ADC_Channel_x实现,无需重新初始化 ADC;
  • 避坑核心:GPIO 模式正确、采样时间充足、校准不可省略、共地良好、分压电路完整。

2. 进阶学习方向

  • 数据滤波:通过滑动平均算法(连续采集 5 次取平均值)减小采样波动;
  • 多通道 DMA 采集:使用 DMA 直接传输 ADC 采样值到内存,彻底解放 CPU;
  • 内部通道采集:采集 STM32 内置温度传感器(ADC1_CH16)和参考电压(ADC1_CH17);
  • 低功耗采集:结合 ADC 休眠模式,定时唤醒采集,降低系统功耗;
  • 高精度采集:外接基准电压芯片(如 LM4040),替代 VDDA 作为参考电压,提高采集精度。

掌握 ADC 实战后,你已具备嵌入式系统 “模拟信号采集” 的核心能力,可应用于温湿度传感器(模拟型)、压力传感器、音频采集等场景。下一篇我们将学习 SPI 通信,实现 STM32 与 W25Q64 闪存芯片的数据存储,进一步拓展嵌入式系统的存储能力!

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

TinyMCE vs 其他富文本编辑器:在Vue-vite项目中的性能对比与选型建议

TinyMCE vs 其他富文本编辑器&#xff1a;在Vue-vite项目中的性能对比与选型建议 当Vue3项目采用vite构建工具时&#xff0c;富文本编辑器的选型直接影响开发效率和用户体验。TinyMCE、Quill和CKEditor作为三大主流方案&#xff0c;在加载速度、包体积和功能扩展性上各有优劣。…

作者头像 李华
网站建设 2026/8/23 9:49:17

24.两两交换链表中的节点(LeetCode)

题目分析&#xff1a; 为链表建立一个虚拟头节点&#xff0c;然后对接下来的两个节点进行位置交换。设置一个指针变量 cur让其指向虚拟头节点 循环遍历的终止条件为cur->next!NULL 并且cur->next->next!NULL 每次循环时&#xff0c;先定义一个指针变量 temp保存 cu…

作者头像 李华
网站建设 2026/8/23 9:49:17

计算机毕业设计之springboot校园失物招领平台的设计与实现

近年来&#xff0c;科技飞速发展&#xff0c;在经济全球化的背景之下&#xff0c;互联网技术将进一步提高社会综合发展的效率和速度&#xff0c;互联网技术也会涉及到各个领域&#xff0c;而校园失物招领平台在网络背景下有着无法忽视的作用。信息管理系统的开发是一个不断优化…

作者头像 李华
网站建设 2026/8/23 9:49:18

管理干货:企业绩效考核全流程资料包(含指标库/激励制度/面谈模板

建立科学的绩效管理体系是现代企业提升组织绩效的关键。通过整理一份包含11个核心模块及多行业维度的绩效管理数据&#xff0c;我们可以清晰地设定从“制定目标”到“落地反馈”的闭环逻辑。 获取指南&#xff1a; https://pan.quark.cn/s/c9f0ccc78003 以下是对这批管理资料…

作者头像 李华