ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

STM32+MAX30102心率血氧监测实战:从传感器原理到代码实现

2026/8/31 5:03:43 拓冰建站 浏览量
STM32+MAX30102心率血氧监测实战:从传感器原理到代码实现 简介本资源是一套完整的STM32嵌入式健康监测项目源码面向嵌入式初学者与课程设计实践者解决心率与血氧饱和度实时采集、本地OLED可视化显示及串口数据上位机传输的核心开发问题适用于智能手环、便携式健康终端等教学与原型开发场景。压缩包共249个文件含39个C源文件如OLED.c、stm32f10x_i2c.c等驱动模块、39个头文件.h、49个编译中间文件.d、50个目标文件.o以及Keil工程配置.uvprojx/.uvoptx、链接脚本.sct、调试配置.dbgconf等完整覆盖从传感器I²C通信、定时采样、算法滤波到UART协议封装的全流程实现包体大小为6.91MB。已有2497人学习下载提供可直接编译运行的Keil MDK工程含MAX30102寄存器配置详解、SSD1306 OLED动态刷新逻辑、心率/SpO₂双参数串口帧格式定义助读者快速掌握多外设协同开发与嵌入式数据链路构建能力。 很多人拿到MAX30102这颗传感器第一反应就是“心率血氧到底怎么算出来的”然后被网上各种滤波算法、FFT、滑动平均搞到头大。其实这颗传感器没有想象中那么玄乎本质上就是两路LED照射皮肤通过光电二极管接收反射光然后从PPG波形里提取特征。这期我直接用STM32F103C8T6最小系统板配合0.96寸OLED和MAX30102模块把完整的采集、计算、显示、串口上传流程全部走通。代码风格参考江科大那种通俗易懂的路子寄存器操作都写成函数方便直接移植。这个项目适合正在学STM32但觉得纯点灯没意思的朋友也适合想做穿戴式健康监测原型验证的工程师。它是典型的“传感器采集数据处理人机交互上位机通信”四合一工程麻雀虽小五脏俱全做完这一套I2C通信、定时器中断、状态机编程、串口协议设计这些嵌入式基本功都能练到。我自己当时做这块板子的时候踩了不少坑比如传感器I2C地址搞错、OLED引脚复用冲突、还有血氧数值怎么调都不稳定这些都会在下面实操部分展开讲。1. 项目整体设计与方案选型1.1 为什么选MAX30102而不是其他心率传感器市面上能测心率的传感器方案其实不少ADI的AD8232是模拟前端外部要自己搭运放电路和右腿驱动适合做ECG心电图但体积大、电路复杂。MAX30102是反射式PPG方案模块本身集成了LED驱动、光电二极管、ADC、滤波器和数字接口外部只需要一颗电阻和少量电容就能工作最高支持每秒3200次采样配合红光和红外光两路光源能同时算出血氧。这里有个关键点很多人会忽略MAX30102输出的是原始ADC数据不是现成的心率值。想要拿到BPM和SpO₂数值必须在单片机里自己做信号处理。这意味着它能锻炼你完整的算法落地能力而不只是调用一个现成的库。我选它的另外一个原因是模块便宜、资料多就算烧坏了也不心疼拿来练手正合适。1.2 STM32型号选择和资源分配我用的是STM32F103C8T6也就是大家常说的“蓝丸”核心板。选它不是因为性能有多强而是因为资料最全、引脚够用、价格便宜。这个项目的计算量其实不大核心是在中断里搬运I2C数据和做滑动平均滤波72MHz主频跑起来绰绰有余。引脚分配我建议这样PB6和PB7作为I2C1的SCL和SDA连接MAX30102和OLED共用一组总线PA9和PA10作为USART1的TX和RX用来往串口调试助手发数据。OLED的复位引脚可以随便接一个GPIO我用的是PB0。整个项目只用到这几个外设逻辑清晰后续扩展蓝牙模块或者按键也容易接线。项目核心的通信链路是MAX30102通过I2C把ADC原始值传给STM32STM32在内存里做滤波和特征提取再把心率血氧结果分别送向OLED显示和串口输出。1.3 通信拓扑与数据流设计MAX30102和OLED虽然都是I2C设备但它们的从机地址不一样挂在同一条总线上完全没问题。MAX30102的7位地址是0x57很多寄存器手册写的是8位地址0xAE实际发送时左移一位OLED屏的SSD1306驱动芯片常用地址是0x3C或0x3D我实测手里这块屏是0x3C。如果屏幕不亮或者设备扫描不到第一件事就是确认这两个地址。数据流分为三路第一路是MAX30102的中断引脚它会告诉我们FIFO里有没有新数据这时候STM32才去读避免一直占用I2C总线第二路是算法处理后的结果往OLED上刷第三路是同一份结果组帧后通过串口发出去。这三路并行工作互不阻塞。1.4 软件框架用状态机代替跑马灯式流程实际项目里我不建议用那种顺序执行的裸机代码比如先读传感器、再算算法、再显示、再发送这样一轮下来整个系统就被占死了。我采用的是主循环定时器标志位的状态机架构主循环里检查各个标志位谁置位了就处理谁。定时器2配置成50ms中断用来切换心率显示刷新和血氧刷新I2C读取则在MAX30102中断引脚触发时执行。这样做的好处非常明显任何一个环节卡住了其他环节不会跟着瘫痪符合真实产品的基本要求。而且这种框架后续想移植到FreeRTOS上也非常容易只需要把标志位换成信号量就行。2. 核心细节解析与实操要点2.1 MAX30102寄存器配置详解MAX30102的寄存器配置是整个项目的灵魂。网上很多代码直接复制过来用结果数据乱跳就是没配好寄存器。我先把关键的几个寄存器列出来再讲为什么要这么配。首先是最重要的模式配置寄存器地址0x09它控制传感器工作在什么模式下。0x02表示心率和血氧同时测量此时红光和红外LED会交替点亮0x03表示只测心率此时只有红外LED工作电流更省但拿不到血氧。本项目需要血氧所以配置成0x02。然后是SpO₂配置寄存器地址0x0A它的高三位控制LED脉冲宽度中间三位控制采样率低三位控制过采样率。我使用的是411us脉宽、200Hz采样率。为什么要选200Hz而不是更高的400Hz甚至800Hz因为心率信号的有效频率范围只有0.5到4Hz也就是每分钟30到240次200Hz采样已经完全够用还能减少数据量和功耗。ADC分辨率是18位过采样率设为1这样每个采样点都是独立的不会因为平均导致波形细节丢失。LED1和LED2的电流控制寄存器地址0x0C和0x0D也很关键。电流越大信号越强但功耗也高而且容易饱和。我的经验是先从6.4mA左右开始调观察波形幅值再逐步往上加。如果ADC读数经常超过60000说明电流太大要降下来。FIFO配置寄存器地址0x08里有一项叫FIFO_A_FULL它决定FIFO里存到多少条数据就触发中断。默认是17条就会置位中断标志。对200Hz采样率来说17条数据相当于85ms积累一次这个节奏和中断处理速度刚好匹配所以我保持默认。2.2 软件I2C和硬件I2C的选择STM32F103的硬件I2C模块在市场上口碑不太好主要原因是它的错误处理机制比较繁琐一遇到总线阻塞就要重新初始化。我在实际调试中发现用硬件I2C读MAX30102时偶尔会出现一直卡在等待事件标志位的情况后来干脆改用软件模拟I2C。软件I2C的时钟延迟函数控制时序完全由自己掌控调试时可以用示波器慢慢看对初学者更友好。GPIO配置成开漏输出加上外部上拉电阻这种用法和硬件I2C在电气特性上完全一样。我提供的代码里I2C底层是通用的硬件I2C和软件I2C的接口都做了兼容。如果你非要挑战硬件I2C记得在每次通信前检查总线状态出错时调用复位函数而不是干等着。2.3 OLED显示驱动的三个坑0.96寸OLED是这项目的显示单元驱动芯片是SSD1306内部有1KB显存通过I2C接口刷新。这里有几个坑必须提前讲。第一个坑是I2C地址。SSD1306的地址由SA0引脚决定接地时地址是0x3C接VCC时是0x3D。大多数模块默认是0x3C但不是绝对我用过一个国产屏地址居然是0x3D所以读不到的时候先换地址试试。第二个坑是OLED的刷新机制它不支持逐像素修改写入时是先写页地址和列地址再连续写数据。如果你频繁全屏刷新主循环会被拖慢所以我只在数据变化时才更新对应区域不搞全屏重绘。第三个坑是取模方式如果想要显示“心率”和“血氧”这样的中文先用取模软件生成数组注意选择“列行式”还是“行列式”选错了字会横七竖八。2.4 数据格式与数值范围预判MAX30102输出的是数字量范围从0到6553518位ADC结果存放在32位寄存器里低6位无效。当手指按在传感器上时红外通道的DC分量大概在30000到50000之间AC分量也就是脉冲波动可能只有几百到几千。如果你看到数值总是65535或者0大概率是传感器没接触好或者电流设置过大饱和了。心率BPM正常范围在50到120之间血氧SpO₂正常值在95%到99%之间。如果算出来心率是180、血氧是88不一定是算法算错了先看看手指有没有按稳、环境光是不是太强、传感器有没有和皮肤贴合。我第一次调试时把传感器放在桌上测结果数据乱飘就是因为没有模拟真实测量场景。3. 实操过程与核心环节实现3.1 硬件连接与地址确认焊接和连线之前先给整个系统画个连接表。这一节内容很琐碎但往往是最花时间的。我用的连接方式如下MAX30102模块STM32F103C8T6OLED模块VIN3.3VVCCGNDGNDGNDSCLPB6SCLSDAPB7SDAINTPA1——PB0RES(复位)这里要特别注意MAX30102的引脚标号在不同厂家模块上可能不一样。有些模块把VIN叫VCC有些把GND叫GND还有的模块自带电平转换芯片支持5V供电但STM32F103是3.3V逻辑所以一律用3.3V供电最稳。连线完成后先用一个最简单的I2C扫描程序确认两个设备都在总线上。扫描方法是依次向0x3C、0x3D、0x57、0xAE这些地址发送START信号并检查ACK。如果OLED和MAX30102都返回ACK说明硬件没问题可以继续往下走。3.2 MAX30102初始化代码逐段讲解我把初始化代码拆成几段来讲每一段对应一个功能模块方便移植到自己的工程里。void MAX30102_Init(void) { uint8_t temp; // 复位传感器 MAX30102_Write_Register(0x09, 0x40); delay_ms(100); // 读取PART_ID寄存器确认传感器活着 temp MAX30102_Read_Register(0xFE); while(temp ! 0x15) { delay_ms(100); temp MAX30102_Read_Register(0xFE); } // 设置为心率和血氧模式 MAX30102_Write_Register(0x09, 0x02); // SpO2配置411us脉宽200Hz采样率 MAX30102_Write_Register(0x0A, 0x43); // LED1电流6.4mA MAX30102_Write_Register(0x0C, 0x24); // LED2电流6.4mA MAX30102_Write_Register(0x0D, 0x24); // 使能FIFO几乎满中断 MAX30102_Write_Register(0x02, 0x00); MAX30102_Write_Register(0x07, 0x00); }第一部分是复位和ID检查。复位寄存器写0x40后传感器会重启这时候需要等待一小段时间。读0xFE寄存器正常应该返回0x15。这一步特别重要很多模块没焊好或者接触不良读出来全是0xFF如果不做这个检查后面所有操作都是白费。第二部分是工作模式。0x09寄存器写0x02之后传感器就进入了双LED交替采样模式。这时候你再用示波器看SDA线上的数据会发现它有规律的在红光和红外两个通道之间切换。第三部分是采样参数。0x0A寄存器写0x43其中高两位是00表示411us脉宽中间三位是100表示200Hz采样率低三位是011表示样品过采样率为4。这里我实际测试时发现把过采样率调高后波形确实更平滑但代价是有效采样率下降因为每次输出的都是多个子采样的平均值所以果断放弃改成1倍过采样。0x43对应的是过采样率4如果不想过采样改成0x40即可。第四部分是LED电流和中断。0x24换算成电流是6.4mA这个值对于肤色较深的人可能偏小对于肤色白的人又可能偏大。实际调试时可以把它当成一个可调参数波形太矮就加电流饱和就减电流。3.3 数据读取与FIFO操作MAX30102内部有一个32条深度的FIFO每个条目包含红光和红外两个通道的18位数据也就是共6字节。当FIFO里的数据条数达到FIFO_A_FULL设置的门槛时MAX30102的INT引脚会拉低通知单片机来取数据。读取FIFO数据寄存器地址0x07时每次读取3字节分别是高字节、中字节和低字节组合成一个32位整数。void MAX30102_Read_FIFO(uint32_t *red, uint32_t *ir) { uint8_t buffer[6]; // 先读六个字节 MAX30102_Read_Registers(0x07, buffer, 6); // 组合红光数据 *red ((uint32_t)(buffer[0] 16) | ((uint32_t)buffer[1] 8) | buffer[2]) 0x3FFFF; // 组合红外数据 *ir ((uint32_t)(buffer[3] 16) | ((uint32_t)buffer[4] 8) | buffer[5]) 0x3FFFF; }读取完成后把数据分别放到两个环形缓冲区里。环形缓冲区的大小我设置为250个点对应200Hz采样率下的1.25秒数据。这个长度对心率计算来说正好够用因为典型的心率周期在0.5到1.2秒之间1.25秒的窗口能覆盖至少一个完整周期。3.4 波形预处理与心率计算很多教程里直接拿原始数据算心率结果波形毛刺多、计算不稳定。实际上完整的PPG信号预处理分三步去直流、低通滤波、滑动平均。去直流的意思是减去信号的DC分量也就是长时间的平均值。我用的是移动平均法每50个点取一次均值然后把原始信号减去这个均值剩下的就是AC分量也就是心脏搏动带来的体积变化信号。接着做低通滤波把高频噪声干掉。这里我用了一个简单的一阶低通滤波器公式是y[n] y[n-1] alpha * (x[n] - y[n-1])alpha取0.3左右。别看它简单效果非常好指尖晃动引起的毛刺能被压掉一大半。心率计算的核心是找波峰。我用的方法是自适应阈值法先统计前一段时间的信号最大值和最小值算出中间线作为阈值然后把连续高于阈值的点都归为一个波峰记录波峰间隔再换算成每分钟心跳次数。这个方法比FFT简单太多计算量小代码量也不大。3.5 血氧饱和度计算原理与细节血氧饱和度计算的核心原理是朗伯-比尔定律的近似。含氧血红蛋白和还原血红蛋白对红光和红外光的吸收系数不一样在红光波段660nm还原血红蛋白吸收更强在红外波段880nm含氧血红蛋白吸收更强。通过比较两个波段的交流分量和直流分量的比值就可以估算SpO₂。计算Ratio of Ratios的公式是R (AC_red / DC_red) / (AC_ir / DC_ir)。SpO₂和R之间近似线性关系经验公式为SpO₂ 110 - 25 * R。但实际模块出厂前会做校准不同模块的系数可能略有差异所以代码里我把这个拟合斜率和截距做成了宏定义方便后期微调。我的经验是当R在0.4到1.0之间时这个公式算出来的值在90%到100%区间内可信度很高当R超出这个范围时多半是信号质量差宁可显示“--”也不要给一个错误数值误导使用者。3.6 串口数据帧协议设计串口部分我用的是USART1波特率1152008位数据位1位停止位无校验。直接发送原始数值的字符串虽然方便人看但上位机解析起来很麻烦所以我设计了一个二进制帧格式。帧头使用0xA5和0x5A两个字节紧接着是数据长度、心率高字节、心率低字节、血氧值、信号质量、校验和。上位机收到后先找帧头再按长度解析数据最后校验。校验用简单的累加和把帧头之后的所有字节加起来取低八位。这样可以快速过滤掉噪声数据也不会出现粘包问题。void Send_HeartRateData(uint16_t hr, uint8_t spo2, uint8_t quality) { uint8_t frame[8]; uint8_t checksum 0; frame[0] 0xA5; // 帧头1 frame[1] 0x5A; // 帧头2 frame[2] 0x04; // 数据长度 frame[3] (hr 8) 0xFF; frame[4] hr 0xFF; frame[5] spo2; frame[6] quality; for(uint8_t i 2; i 7; i) { checksum frame[i]; } frame[7] checksum; USART_SendArray(frame, 8); }这套协议最实用的地方在于调试时能明确知道数据是准的还是错的。信号质量字段我用0到3来表示0代表信号太差无法计算3代表信号优秀这样上位机可以根据质量值决定要不要信任这组数据而不是把乱跳的数据当真。4. 常见问题与排查技巧实录4.1 I2C扫描不到设备地址这个问题在评论区被问爆了绝大多数情况不是代码问题而是硬件连接问题。先确认VCC是不是真的3.3V很多面包板电源轨接触不良万用表量一下最靠谱。再确认SCL和SDA是不是接反了别笑我接手过的项目里至少有三个是这个问题。最后确认模块上的上拉电阻是否焊好有些高度集成模块用的是内部上拉有些需要外部上拉电阻如果总线上没有上拉通信直接失败。软件层面的排查方法是用一个循环扫描函数把0x00到0x7F的所有地址都尝试发送START加设备地址看哪个地址返回ACK。扫描到了说明通信链路正常再查看模块数据手册确认这个地址对应哪个设备。我这套代码里有专门实现扫描函数串口打印出来就能看到设备地址。4.2 OLED白屏或花屏OLED白屏大概率是复位引脚没处理好。SSD1306在上电后需要拉低复位引脚再拉高且时间间隔要大于10微秒。如果你的复位引脚悬空或者接到3.3V上屏幕状态就不可控。花屏的原因通常是初始化代码不完整或者写显存方式不对。SSD1306有个内存寻址模式设置如果设置错误写入的像素位置会错乱。我的代码里初始化时专门设置成页寻址模式然后定义了一个函数用来更新指定区域的显存这样就不会花屏了。如果屏幕能亮但显示乱码检查取模方式。取模软件里的“列行式”和“行列式”选项一定要和驱动代码里的写像素顺序对应。我把两种方式都试过之后总结出来的规律是列行式适合水平扫描显示行列式适合垂直扫描显示。4.3 心率值跳动剧烈心率值跳动剧烈主要有三种原因。第一种是传感器没有贴合皮肤中间有空隙环境光直接进入光电二极管造成信号基线漂移严重。解决办法是用指套或者创可贴把传感器固定在手指上并且让传感器接触面避开手指关节处。第二种是预处理不够原始信号里的基线漂移没有被滤掉。我在代码里增加了一个高通滤波器截止频率约0.5Hz专门抑制呼吸造成的低频漂移效果立竿见影。第三种是波峰检测阈值不对信号强的时候一个波峰被分成两个波峰信号弱的时候两个波峰被合并成一个。自适应的阈值算法能解决大部分情况但如果你发现特定人身上还是不稳可以在代码里增加一个“最小间隔”限制比如两个波峰间隔不能小于300ms这样就把高频毛刺排除掉了。4.4 血氧值偏低或一直显示99%血氧值偏低最常见的原因是环境光干扰。MAX30102对红外光敏感度很高如果传感器没有完全遮光环境光会混入信号导致AC分量失真。用深色不透明的硅胶套把传感器周围遮住环境光干扰会小很多。另一种情况是血氧一直显示99%不动。这是因为血氧计算的R值变化范围很小DC和AC都被处理得太平滑了导致R值几乎恒定。解决办法是把滤波器的alpha调大一点让AC分量保留更多动态细节。我测试下来alpha在0.2到0.4之间比较合适太大噪声多太小波形太死。最后要说一个很多人忽略的点血氧计算至少需要一个完整的心率周期数据所以测量时要有耐心保持手指静止至少5秒钟。如果刚上电就去看血氧数值前面几秒大概率是偏低的因为FIFO里还没攒够完整周期的数据算法拿不准确的信息硬算结果肯定不对。4.5 串口数据乱码或接收不到串口乱码九成是波特率不对。STM32的USART波特率由APB时钟和波特率寄存器决定如果系统时钟配置错误实际波特率和期望值会有偏差。我建议先开一个最简单的程序只循环发送0x55用示波器看波形宽度来确认波特率准确。接收不到数据时除了检查TX引脚是否接到了USB转TTL的RX上之外还要确认共地。很多新手只连了TX和RX没连GND结果信号根本没有参考地必然收不到。另外SSCOM和XCOM这类调试助手在打开串口时会把DTR和RTS信号拉低如果STM32的复位电路刚好和这两个信号相连会导致单片机自动复位表现就是刚打开串口程序就重启了。解决办法是在调试助手设置里把DTR和RTS取消勾选。4.6 MAX30102读数一直为零或全满读数全零通常是LED电流太小信号完全淹没在噪声里。把LED电流寄存器从0x24往上加比如改成0x40对应10.2mA看看波形有没有起来。读数全满接近65535则是LED电流太大或者传感器饱和。降低电流、增加和皮肤之间的距离就能解决。要注意的是MAX30102的检测距离只有几毫米如果手指没有轻压在玻璃窗上信号肯定不正常。另外一些模块上有一层保护膜出厂时没有撕掉这层膜会严重衰减光信号导致波形非常微弱看起来就像读数一直偏低。5. 工程优化与后续扩展建议5.1 采样率与实时性的权衡优化200Hz采样率对这个演示项目来说完全够用但如果你想做更精准的心率变异性分析需要把采样率提高到400Hz甚至800Hz。提高采样率后FIFO消耗速度变快中断触发频率也变高此时要注意主循环里不要做耗时操作比如全屏刷新OLED或者串口发送长字符串。我测试过800Hz采样下200个点的滑动窗口只有0.25秒波形细节更多但心率计算稳定性反而下降因为窗口里可能只有半个完整周期导致周期检测出错。所以采样率不是越高越好得根据算法窗口大小来定。如果后续要加入蓝牙传输建议在单片机端先把特征值算好只把心率、血氧、波形特征点传出去而不是把所有原始ADC数据都发出去。原始数据一秒800个点每个点4字节蓝牙串口根本扛不住数据传输会成为一个新的瓶颈。5.2 低功耗优化思路要是做可穿戴验证机功耗是个绕不开的话题。MAX30102本身支持关断模式不测量时把模式寄存器写成0x00静态电流能降到微安级别。STM32F103有几个低功耗模式睡眠模式下CPU时钟停止外部中断可以唤醒正好配合MAX30102的中断引脚用。我实测过一套优化方案一秒内只开启200ms的采样窗口其他时间进入睡眠平均电流能从2mA降到0.5mA左右。代价是实时性变差心率显示会滞后但对运动手环这种应用来说完全能接受。5.3 和上位机联动的更多玩法串口数据传上去之后上位机可以做很多事情。最简单的方案是用Python的pyserial库读取串口然后用matplotlib实时画心率波形。进阶一点可以用Qt写一个带曲线显示和数据存储的上位机把心率血氧数据保存到CSV里。再往后还能接数据库做历史趋势分析。这套代码里的帧格式已经预留了信号质量字段上位机可以直接用它做数据筛选把信号质量差的数据剔除掉再画图曲线会平滑很多。5.4 标准库和HAL库的兼容说明我收到很多私信问标准库和HAL库能不能直接套用。完全可以。核心算法部分完全不依赖任何库纯粹是C语言数组操作直接拷贝到HAL库工程里就能跑。区别只在底层I2C和串口读写部分HAL库的I2C通信函数是HAL_I2C_Mem_Read和HAL_I2C_Mem_Write标准库是I2C_SendData和I2C_ReceiveData接口不一样但逻辑一样替换一下即可。我建议你先把标准库版本跑通理解整个数据流之后再考虑移植到HAL库或者其他型号的芯片上否则前面基础原理没搞清楚后面排错会很痛苦。6. 调试经验总结与个人体会这个项目做完我最深的一个体会是MAX30102的很多所谓“玄学问题”本质上是物理层面没有处理好。传感器对光路极其敏感手指按压力度、环境光遮挡、传感器表面清洁度都会直接影响ADC原始数据的质量。算法再好输入信号烂输出也照样是垃圾。我第一次调血氧的时候就是一直怀疑滤波参数不对结果折腾两天发现是传感器玻璃窗上有一层指纹油用酒精棉擦干净之后波形立刻变得清晰干净。所以遇到数据异常先看原始波形再做软件层面的调整。另一个体会是关于代码结构。这个项目虽然功能简单但涉及的模块不少驱动层、数据层、算法层、应用层。如果全部堆在一个main函数里排查起来会非常痛苦。我花了额外的功夫把代码按模块分文件驱动层放i2c和传感器驱动数据层放环形缓冲区算法层放滤波和特征提取应用层放OLED和串口展示。每个模块的接口都很清晰后续加功能基本就是在应用层加逻辑不用动底层。最后这项目完全可以作为毕业设计或者求职作品的基础框架。往上面加个蓝牙模块就是智能手环原型加个GPS模块就是户外运动监测设备加个云平台就是远程健康监测终端。传感器数据的采集、处理、展示、传输这套闭环思路是嵌入式开发里复用频率最高的能力把一个项目做透比抄十个项目都管用。本文还有配套的精品资源点击获取