
简介这是一份基于STM32的智能鱼缸设计完整项目资料面向电子信息、自动化、物联网等专业学生及嵌入式开发入门者适合毕业设计、课程设计或项目演示。项目包含全部源码与详细文档涵盖传感器数据采集、水温控制、自动喂食、远程监控等典型智能硬件功能经过测试运行可作为从技术方案到代码落地的参照。压缩包共1714个文件大小约61.29MB主要由393个C源码、310个H头文件、195个O目标文件构成并附带39个Python辅助脚本、73张PNG图片及4个GIF演示MD/RST文档便于阅读Keil工程文件、bin/hex/axf固件输出和MAP/LST文件可直接查看编译与链接细节。项目说明显示答辩评审分达95分并获导师认可已有175人学习目录结构清晰便于在现有基础上做二次功能扩展也能为STM32外设驱动、LVGL界面移植等环节提供直接参考适合答辩前的快速理解与二次开发。1. 从能养鱼到能自己决定怎么养鱼养鱼这件事在工程上其实是个典型的嵌入式闭环系统简单说就是采集环境数据、按规则判断、驱动执行设备再回去校准结果。STM32 在其中扮演的是决策核心CPU 以固定节拍读取水温、浑浊度、水位这些传感器信息再用 PWM 调整加热棒或者水泵的出力整个过程不需要人为干预。这套智能鱼缸设计资料并不只是给了套源码而是把从传感器选型、最小系统板引脚分配、定时器与 ADC 外设初始化到 LCD 界面状态刷新这一整条链路都串了起来。适合谁去看如果你是正在做 STM32 相关课设、准备电赛项目或者刚开始接触嵌入式裸机开发又想看到一个相对完整的外设组合这套资料里的System.bin固件、Smart_Fish_Tank.bin烧录镜像以及带有详细注释的工程文件能让你在现有代码上直接改功能而不是从 LED 闪烁开始重复造轮子。真正要注意的是项目用的是标准外设库而非 HAL 库这意味着中断回调、寄存器操作和时钟树配置都走得比较底层看懂了这套代码换到任何 Cortex-M 内核平台都能平移思路。2. 硬件选型与系统架构先算功耗、再定引脚最后才谈写代码STM32 系列在鱼缸这种慢变系统里的优势不是算力强而是低功耗模式丰富、定时器资源多、ADC 通道够用。比如你希望温度采样误差不超过正负 0.5 摄氏度就需要选择内置 12 位 ADC 且有足够参考电压精度的型号同时加热棒这种非线性负载要用定时器的 PWM 输出控制占空比不能靠 GPIO 高低电平硬切。我在拆这套项目时发现它把系统分成了四层感知层温度、水位、光照、浑浊度、决策层STM32 主控内的逻辑判断、执行层加热棒、水泵、增氧机、补光灯、交互层LCD 显示与按键输入。评估一个智能系统好不好用不能只看它能干什么还要看它在异常情况下怎么退避。比如传感器断线、水位过低时加热棒继续工作会导致干烧这是鱼缸场景里最容易出问题的地方。这套项目中给这类异常留了独立检测路径水位信号通过比较器输出数字电平接入 STM32 的 EXTI 引脚一旦低于阈值就触发外部中断在中断服务函数里立即禁用 PWM 输出。下面用一个表格把典型外设与引脚功能顺一下。外设模块接口类型STM32 外设资源典型功能备注DS18B20 水温探头单总线 GPIOGPIO 普通输入实时水温采集需要 4.7k 上拉电阻水位传感器数字电平EXTI 外部中断低水位报警 / 干烧保护比较器输出浑浊度传感器模拟电压ADC 独立通道水质浑浊度判断电压输出范围 0~4.5V加热棒继电器低电平触发定时器 PWM 或 GPIO水温加热控制用光耦隔离水泵 / 增氧机Motor driver定时器 PWM 互补输出水循环与增氧需考虑启动电流从 PCB 布局角度我一般会建议把模拟电源和数字电源用 0 欧电阻单点连接避免水泵电机启停时的地弹干扰 ADC 采样。如果是自己打板注意 STM32 晶振电容计算这块像项目里用的 8MHz 晶振负载电容取 18pF 到 22pF 都可以关键要看晶振本身规格书的 CL 参数直接用公式 CL (C1*C2)/(C1C2) Cstray 来算Cstray 通常在 2~5pF 之间。原理图里下载的接线图和 SDK 包里没有包含这点建议拿到资料后对照参考设计核对一遍。2.1 最小系统板评估为什么不用开发板直接怼很多初学者喜欢直接用正点原子或者野火的开发板来做鱼缸项目这当然能跑通但有两个问题第一开发板上的外设电路比如 USB 转串口、LCD 接口、LED会额外消耗电流和引脚而且它们占据的引脚位置往往与传感器需要的引脚冲突第二开发板的布局并不适合直接放进鱼缸外壳你需要重新设计转接板。所以这套智能鱼缸设计选择了最小系统板加外围模块的方式通过排针把 GPIO 引出来。那么最小系统板需要哪些必要条件首先是供电鱼缸环境里 220V 转 5V 的电源模块会给水族设备供电STM32 需要 3.3V所以板子上要有 AMS1117 或者 RT9013 这类 LDO其次是复位电路和启动模式配置BOOT0 必须接下拉电阻到地才能让芯片从 Flash 启动最后是 SWD 调试接口至少留出 SWDIO、SWCLK、GND 三个引脚方便用 ST-Link 烧录和调试。在这套源码里时钟配置是用标准库函数SystemInit()配合stm32f10x.h头文件完成的。串口调试信息用 UART1重定向了fputc()到串口这样直接调用printf()就能在串口助手看到运行日志。如果你拿到代码后在别的板子上跑不通过先检查晶振频率和启动文件是否匹配比如库编写时假定 72MHz而你的板上焊接的是 12MHz 晶振那SystemCoreClock就会被算成 108MHz时序全部错位。常见做法是在system_stm32f10x.c中把PLL_M、PLL_N这些参数按实际晶振改过来。2.2 引脚复用冲突排查GPIO 不是想怎么配就怎么配操作 STM32 的 GPIO 看起来简单实际项目里一半以上的坑来自重映射冲突。比如定时器 2 的 PWM 输出默认引脚是 PA0~PA3但 PA0 同时是 ADC1 的通道 0如果你既要用定时器 2 输出 PWM 控制加热棒又要在同一引脚接温度传感器的模拟输出那 ADC 转换结果必然抖动。解决方法是把定时器重映射到 PB 或者 PC 口配置GPIO_PinRemapConfig(GPIO_Remap1_SWJ_JTAGDisable, ENABLE)这类函数注意 HAL 库和标准库的函数名不同在这套资料的代码中对应的是GPIO_PinRemapConfig()。另外一个容易忽略的问题是 5V 容忍引脚。STM32F103 的 PA、PB、PC 大部分是 FT5V tolerant引脚可以直接接 5V 逻辑电平传感器但 ADC 引脚如 PA0~PA7 是 3.3V 容忍如果浑浊度传感器输出 4.2V 或者 4.5V 的满量程电压直连会有烧毁风险。稳妥的办法是加一个电阻分压网络比如 10k 和 20k 电阻串联接地把 4.5V 分压到 3V再进 ADC。因为这套项目中已经带了三路 ADC 初始化代码把浑浊度传感器接在 ADC 通道 2PA2 脚时需要注意这个引脚同时支持 TIM5_CH3 的输出功能如果你同时打开了定时器 5 的 PWM那就会出现电位互相干扰表现为数值乱跳且刷新率不稳定。后面涉及按键扫描和继电器控制时建议把隔离做彻底。水泵电机启动瞬间电流能达到额定电流 5~10 倍如果控制信号和功率回路只通过一根地线相连ADC 采样值会被抬高或者出现周期性毛刺。在这类低成本方案中用 TLP521 或 PC817 光耦把 STM32 的 GPIO 与继电器驱动三极管完全隔离再接续流二极管可以避免板子死机或者程序跑飞。3. 传感器驱动与参数平滑从原始值到可用数据的过滤链路传感器部分最怕的不是数值不准而是数值波动导致系统频繁启停。水温用 DS18B20它是单总线协议时序要求严格而且它本身需要至少 750ms 完成一次 12 位温度转换。直接连续读会导致芯片内部忙返回 85 度或者 0 度这种错误值。在这套项目里它用了状态机的方式去调度 DS18B20 的读取流程先发复位脉冲等待存在应答再发 ROM 指令跳过序列号然后发转换命令等待转换完成最后读取暂存器中的两个字节。代码实现比较标准但是值得改进的是它的主循环没有加时间片保护如果传感器拔出或者总线被拉低程序会卡在while等待应答的位置。uint8_t DS18B20_ReadBit(void) { uint8_t bit_val 0; DS18B20_DQ_OUT_LOW(); delay_us(2); DS18B20_DQ_OUT_HIGH(); delay_us(15); bit_val DS18B20_DQ_IN(); delay_us(50); return bit_val; }上面的函数逻辑是主控把总线拉低 2 微秒后释放再延时 15 微秒采样因为 DS18B20 的时序要求主机读位时必须在 15 微秒窗口内读取数据有效区域。这里的delay_us()用的是 SysTick 延时所以精度比较好不受编译器优化级别影响。如果你在 Keil 工程里做-O2优化编译发现温度读数一直是 0 或者 85大概率是delay_us()被优化成了空循环解决方法是给延时函数里的局部变量加上volatile关键字或者在函数声明处加__attribute__((optimize(O0)))。水位检测则不用 ADC因为水导电后探针间电阻会明显下降通过比较器设置阈值后直接输出高低电平从而省去在代码里做复杂判断。比较器本身有回差设计电压滞回大约 30mV这样水面轻微波动不会导致 GPIO 频繁跳变。读到 EXTI 下降沿后程序置位标志位主循环里处理低水位逻辑而不是在中断函数里做整个动作这是嵌入式编程中常见的中断置标志、主循环做处理模式。传感器类型输出形式处理方式采样周期缓存策略水温 DS18B2012 位温度值读取后做滑动平均5s缓存 8 次读数浑浊度0~3.3V 模拟电压ADC 采集 卡尔曼滤波轻量版200ms缓存 16 个采样点水位数字电平状态沿检测事件触发无光照传感器模拟电压或数字 I2CADC 采样阈值比较500ms缓存 4 次取最大3.1.1 温度控制中的 PID 参数整定思路水温控制是鱼缸系统中最能体现嵌入式算法能力的地方很多人直接用滞回控制结果加热棒继电器一小时动作几十次触点寿命短温度过冲超过 2 度。改用 PID 后只需要控制 PWM 的占空比就能让加热棒温度平滑稳定。但是鱼缸水体热容量大系统滞后严重所以 PID 参数不能照搬网上电机的调参表格。我的方法是先用 Ziegler-Nichols 的临界比例法把积分和微分去掉只保留比例项把增益调大直到温度出现等幅振荡记下此时的临界增益 Ku 和振荡周期 Tu再按公式计算 P、I、D 的参数。这个项目代码里没直接给出 PID 函数但给出了温度采集和 PWM 输出的完整接口所以补一个位置式 PID 是很容易的。需要注意积分饱和问题加热停止后如果水温仍高于目标值积分项会持续累加负误差导致下次加热时总输出被拉低出现不加热的现象。解决办法是在代码里对积分限幅并且采用增量式 PID 来规避。增量式的输出是当前输出在上一次基础上的变化量不需要清空积分抗积分饱和能力更强。由于鱼缸控制周期在 1 到 2 秒对运算速度要求很低STM32F103 跑 72MHz 完全有余量关键是把 PID 计算放在定时器中断里保证固定周期。float pid_calc(PID_Typedef* pid, float target, float current) { float error target - current; pid-integral error; if (pid-integral pid-out_max) pid-integral pid-out_max; if (pid-integral pid-out_min) pid-integral pid-out_min; float output pid-kp * error pid-ki * pid-integral pid-kd * (error - pid-last_error); pid-last_error error; if (output pid-out_max) output pid-out_max; if (output pid-out_min) output pid-out_min; return output; }这段 PID 函数中out_max和out_min需要映射到 PWM 的占空比范围。如果定时器设置为 8 位计数器也就是 ARR 值为 255那out_max可以设置为 200out_min设置为 0预留一定的余量。ki的取值决定稳态误差消除速度但过大会造成振荡我一般先把kp调好再按ki kp / 60起步kd kp * 4起步然后在实际水温曲线里微调。注意加热棒第一次上电时水温低、误差大输出会达到满占空比这是正常现象但要用软件限制最长连续加热时间防止鱼缸在极端低温环境中加热棒表面结垢。3.1.2 定时器与 ADC 采样同步问题鱼缸里的传感器采样有一个特殊点浑浊度传感器容易受气泡干扰。水泵增氧产生的气泡如果经过传感器探头输出电压会瞬间跳变造成 ADC 读数异常。这种情况下单靠滑动平均滤波是不够的因为异常值会污染整个滑动窗口导致报警延迟或误报。更可靠的做法是把 ADC 采样时机固定在水泵关断后的 50ms或者每次采样前先延时让气泡过去再读值。定时器 3 在这个系统里充当了采样节拍发生器。它的更新中断频率被配置为 10Hz每次中断触发时依次调用一次温度采集、ADC 采集和状态刷新。用一根时间基准去驱动整个传感器系统而不是在主循环里用HAL_Delay()穿插可以避免代码调试时出现的时序问题。STM32 的 ADC 支持注入组和规则组规则组可以配置多个通道按顺序扫描在这个系统里由于三路 ADC 是不同类型、不同采样周期的传感器分开触发比统一扫描更合理所以我建议规则组只放浑浊度和光照两路温度单独用单总线采样周期 5 秒避免高频读单总线影响主循环响应按键。4. 交互界面与主控状态机不止是显示数据还要能被人理解智能鱼缸的人机交互在大多数 DIY 项目中往往被放在最后考虑但经验是他们恰恰是答辩时评委最关注的部分。这套资料里包含了两个文件lv_demo_printer_img_scan_example.c和lv_demo_printer_img_btn_bg_1.c说明显示部分用了 LVGL 图形库的 demo 适配。LVGL 在 STM32F103 上移植时最麻烦的是内存问题因为每增加一个控件都要占用 RAM 做对象结构体而 F103 的 SRAM 通常只有 20KB 到 64KB。如果直接在主循环里动态分配内存频繁创建和删除控件后堆碎片会让系统崩溃。实际项目中比较稳的做法是预编译 UI 界面即在初始化阶段创建所有控件并隐藏不需要的部分通过修改控件的可见性来做界面切换而不是销毁重建。按键输入用 GPIO 中断加扫描响应优先级高但不要在中断回调里调用 LVGL 的lv_btn_set_state()这种耗时函数正确姿势是使用lv_timer_handler()在事件循环里统一处理。这个文件名的printer_img_scan看起来是 LVGL 的 demo 例子你可以在这个基础上把鱼缸的温度曲线重绘成折线图。void UI_Update(void) { lv_label_set_text_fmt(label_temperature, Temp: %.1f C, g_current_temp); lv_bar_set_value(bar_water_level, g_water_level_percent, LV_ANIM_ON); if (g_alarm_flag LOW_WATER_ALARM) { lv_obj_clear_flag(label_alarm, LV_OBJ_FLAG_HIDDEN); lv_label_set_text(label_alarm, LOW WATER LEVEL!); } else { lv_obj_add_flag(label_alarm, LV_OBJ_FLAG_HIDDEN); } }这个刷新函数典型地展示了把传感器变量映射到 UI 控件的过程。g_current_temp和g_water_level_percent是全局变量由传感器采集函数更新UI 刷新函数只做读操作。LVGL 的刷新频率没有必要太高20Hz 即每秒刷新 20 次已经足够顺滑过高反而加重 CPU 负载。在 F103 这种平台上建议把LV_TICK_CUSTOM配置为 0使用专门的定时器中断来提供时钟节拍避免与系统延时冲突。主控逻辑建议用状态机来实现而不是简单的 if-else 嵌套。鱼缸系统的工作模式可以分为几个状态INIT上电初始化、NORMAL正常工作、HEATING加热中、LOW_WATER低水位停机、MANUAL手动模式。每个状态的事件转换条件要清晰定义。比如在LOW_WATER状态下即便水温低于目标值加热 PWM 也必须保持在 0 输出只有水位恢复正常并按键确认后才能退出这个状态。这种设计保证了系统在任何异常情况下都不会对设备产生破坏性操作。状态触发事件动作退出条件INIT系统上电初始化外设、读取 Flash 配置、LCD 显示 logo初始化完成NORMAL无事件采集传感器、刷新屏幕、检查是否需要加热收到按键事件HEATING水温低于目标-0.5°C开启 PWM 占空比输出水温达到目标0.2°CLOW_WATEREXTI 下降沿关闭加热和水泵、显示告警信息水位正常且按键确认MANUAL按键长按用户手动控制水泵/灯光超时 60s 自动退出在实现状态机的过程中推荐用函数指针数组或者 switch-case 加状态枚举。前者扩展性好后者代码直观项目代码量不大用 switch-case 就够了。注意所有状态机的跳转都要经过统一的state_change()函数处理在这个函数里做进入和退出动作比如离开HEATING时把 PWM 占空比清 0进入LOW_WATER时置位蜂鸣器这样就不会遗漏状态边界条件。4.1 串口日志与调试命令裸机开发也有 Debug 入口很多初学者在 STM32 上做调试只靠点灯但灯只能表明程序跑到哪里看不出变量值的变化。这套项目把 UART1 作为调试串口通过重定向printf()到串口助手可以在电脑上实时观察温度、水位、PWM 占空比这些关键参数。这里有一个使用细节标准库的printf()默认会检查stdout是否指向串口需要在初始化里调用setvbuf(stdout, NULL, _IONBF, 0)关闭缓冲否则输出不全。除了周期日志我通常还会加一个简单的命令解析功能比如输入字符t立即返回当前温度输入pwm 100手动设置加热占空比。这样在调参的时候直接在串口助手下发命令不用烧录代码就能验证控制效果。实现方案是开启 UART 接收中断把收到的字节存入环形缓冲区主循环里逐字节解析遇到换行符再执行命令。注意命令解析和传感器采集都在同一个循环里跑不要让解析逻辑阻塞采集逻辑环形缓冲区的设计用头尾指针加计数变量即可。如果是调试 SPI 或者 I2C 外设使用逻辑分析仪比示波器更方便可以同时抓多个通道观察时序关系。调试 LVGL 显示时如果界面出现花屏先检查 SDRAM 初始化是否完成再刷一个纯色背景测试如果纯色正常说明显存地址没问题问题在图层叠加或颜色格式配置上。4.2 掉电保存与参数配置EEPROM 模拟还是外挂 Flash鱼缸的控制参数目标温度、加热回差值、灯光开关时间需要在掉电后保存否则每次上电都要重新设置。STM32F103 内部有 Flash可以用自带的 EEPROM 模拟功能通过操作 Flash 扇区来保存数据但擦写次数有限大约一万次。如果用外部 I2C EEPROM(比如 AT24C02)则性能和寿命都更好但增加成本和布线面积。这套项目里没有明确给出参数存储这块所以你自己扩展时建议设计一个简单的协议用结构体打包参数加上帧头帧尾和 CRC8 校验存放在固定地址。typedef struct { uint16_t magic; float target_temp; uint8_t hysteresis; uint8_t light_on_hour; uint8_t light_on_min; uint8_t pump_speed_level; uint8_t crc; } SystemConfig; #define CONFIG_FLASH_ADDR 0x0800FC00 SystemConfig g_config; void Config_Save(void) { g_config.magic 0xA5A5; g_config.crc Calc_CRC8((uint8_t*)g_config, sizeof(SystemConfig) - 1); FLASH_Unlock(); FLASH_ErasePage(CONFIG_FLASH_ADDR); uint32_t* p (uint32_t*)g_config; for (uint8_t i 0; i sizeof(SystemConfig) / 4; i) { FLASH_ProgramWord(CONFIG_FLASH_ADDR 4 * i, p[i]); } FLASH_Lock(); }0x0800FC00是 F103 的最后 1KB 地址空间用于存放参数足够。写 Flash 前必须擦除整页F103 的页大小是 1KB 或 2KB 取决于型号如果结构体很小就直接把整页擦掉重写。这段代码里的Calc_CRC8可以用查表法做效率高且占用空间小。要注意的是Flash 编程前必须读出来比较如果内容相同就不要擦写否则每次上电都做一次擦写会大幅缩短 Flash 寿命。读取配置时若magic不等于0xA5A5说明 Flash 为空或数据损坏此时填充默认参数。5. 从裸机到实用四个改善体验的进阶调试技巧裸机框架把系统跑通只是第一步让它长时间稳定运行、功耗更低、操作更顺手有时比加功能更重要。基于对这套代码的阅读和实际运行的体会归纳四个可以直接修改的改进点不需要改变整体架构就能落地。5.1 用空闲中断完美处理不定长串口指令标准库的 UART 接收中断是收到一个字节进一次中断如果要做setpwm 120这样的字符串命令解析必须凑够固定长度才能判定一帧结束这导致灵活性差。用 USART 的空闲中断IDLE配合 DMA 接收可以实现不定长数据帧的自动接收。初始化时使能USART_IT_IDLE当串口线上超过一个字节时间没有新数据时触发中断此时 DMA 已经把所有数据搬到了缓冲区只需要在中断里读取 DMA 剩余计数器就能算出本次收到的字节数。这种方式在事件上报、GPS 解析等场景是通用技巧。void USART1_IRQHandler(void) { if (USART_GetITStatus(USART1, USART_IT_IDLE)) { USART_ReceiveData(USART1); rx_len BUFFER_SIZE - DMA_GetCurrDataCounter(DMA1_Channel5); rx_complete_flag 1; DMA_ClearFlag(DMA1_FLAG_GL5); } }代码里先读一次USART_ReceiveData清除 IDLE 标志再去 DMA 的当前数据计数寄存器反推接收长度。如果 DMA 缓冲区不够大超过缓冲区长度的数据会被截断解决办法是把缓冲区开大一点或者启动循环 DMA 加双缓冲。这套项目里的串口接收是单字节中断模式改装成上述方案后调试效率会明显提升。5.2 低功耗模式把静态电流从 20mA 降到 5mA 以内鱼缸系统需要 24 小时运行功耗不是测量精度问题而是电费和发热问题。STM32 的三种低功耗模式中Sleep 模式只停 CPU外设还能干活Stop 模式停掉所有时钟可通过 EXTI 唤醒Standby 模式几乎完全关断。鱼缸里传感器需要周期唤醒所以更适合 Stop 模式加 RTC 闹钟唤醒每 5 秒醒来采集一次数据和刷新显示然后重新进入 Stop。实现时注意 ADC 和看门狗在 Stop 模式下会停止工作如果你开了 IWDG独立看门狗需要在进入 Stop 模式前刷新喂狗否则醒来后直接复位。另一个细节是进入 Stop 模式之前关闭所有 LED 指示灯和外设时钟用__WFI()指令等待事件。按键和外部传感器中断都能唤醒芯片如果主控板是电池供电建议把 LCD 背光控制到单独的 GPIO休眠时拉低背光省下几十毫安电流。5.3 异常重试与自动恢复机制传感器在长期运行中难免接触不良DS18B20 单总线没有 CRC 校验的话偶尔读到乱数据会成为控制系统的噪声源。可以在读取温度后追加一个合理性检查比如当前读数和上次读数差超过 8 度就丢弃本次值并记录错误计数连续 5 次异常则把传感器状态置为OFFLINE报警但不影响其他功能。对于 I2C 外设如果通信无应答先软复位外设再重试两次最后才报错。这个重试机制可以抽象成一个通用的I2C_ReadWithRetry()封装避免主逻辑代码重复。重启策略要谨慎如果是看门狗复位或硬件错误复位本身可能导致继电器重复吸合对加热棒就有风险。所以软件复位重启前必须执行安全动作比如清掉定时器 PWM 输出关闭继电器。建议加一个复位原因检测函数通过读取RCC-CSR寄存器区分是上电复位、外部复位还是看门狗复位。5.4 自动喂食与定时任务的扩展接口这套项目源码里的定时器预留已经足够你可以额外接一个舵机模块利用定时器的另一个通道输出 50Hz 的 PWM 信号通过修改比较寄存器控制舵机角度实现定时开仓喂食。定时任务的调度建议用一个软件定时器数组每个元素保存触发时间和回调函数指针SysTick 中断中循环检查是否超时。这种方式比在多个外设中断里各写一套延时判断要清晰得多扩展时直接往数组里增加配置项即可。最后一个值得留意的细节是鱼缸控制板会放在潮湿环境中PCB 要做三防漆处理并且所有对外接插件都要选用防水端子。实际运行过程中水泵和水体之间的漏电流会造成地电位抬升极端情况下 STM32 复位或程序跑飞看门狗不是万能的它只复位 CPU不恢复外设状态。稳妥的做法是上电初始化时总是把继电器和电机输出置为关闭状态等待系统完全初始化完成并检查传感器正常后再开启这样能避免上电瞬间设备的误动作。本文还有配套的精品资源点击获取