-
当直播间里的"央视主播李梓萌"向你推荐能治百病的"神药"时,你可能正在遭遇一场精心设计的AI诈骗!近日,北京市场监管部门破获全国首例AI伪造名人带货案,涉案公司利用AI换脸技术假冒央视主持人,将普通糖果包装成包治百病的"深海多烯鱼油",在直播间大肆行骗。这场"李鬼"冒充"李逵"的闹剧,给整个直播行业敲响了警钟。令人细思极恐的是,这个拥有88万粉丝的直播间里,AI生成的"李梓萌"形象栩栩如生,配合着"治疗头晕头痛、手麻脚麻"等违规医疗宣传,让不少消费者上当受骗。更讽刺的是,这些售价不菲的"神药"经查实仅为普通食品,与宣传疗效相差十万八千里。这场高科技骗局不仅侵犯了名人肖像权,更暴露出直播带货监管的新盲区。但魔高一尺道高一丈,物联网技术正在构筑反诈"天网"。区块链就像产品的"电子身份证",扫码即可追溯真实生产信息;AI人脸识别能实时比对主播面容特征,让"山寨名人"无所遁形;智能合约则像24小时在岗的"电子警察",自动拦截夸大宣传的内容。这些技术组合拳,正在形成打击虚假直播的"科技防线"。在这场AI与反AI的较量中,每个环节都需要升级防御。直播平台要配备"AI侦探系统",0.1秒内识破换脸把戏;监管部门要建立"物联网天眼",全网追踪可疑直播间;消费者更要擦亮眼睛,记住"天上不会掉特效药"。这起案件的成功查处,标志着我国对AI黑色产业链的打击进入新阶段——用更智能的技术,守护更清朗的网络空间。
-
一粒玉米种子,如何能获赔5000余万元?2025年4月25日,最高人民法院知识产权法庭,有关行业代表、北京市有关公用企业员工、媒体记者和高校知识产权专业研究生等近30人共同旁听了一起案件的宣判。据悉,恒某公司对玉米植物新品种“NP01154”享有独占许可权,其主张金某公司生产、销售的七个杂交玉米审定品种均系未经许可使用“NP01154”品种作为亲本生产而来,请求判决停止侵权、赔偿损失。最高人民法院日前宣判的这起案件,敲响了种业知识产权保护的洪钟。然而,维权路上,“证明难、周期长、成本高”犹如三座大山,让许多育种者举步维艰。当侵权手段“花样翻新”,科技创新同样为守护“农业芯片”亮出利剑——物联网技术,正通过为每一粒种子打造独一无二的“数字身份证”,从根本上重塑种业维权生态。过去,证明一粒种子或一棵苗的“我是我”是维权第一难关。如同新闻中“金如意”山楂案,即便特征吻合,侵权方仍可质疑样品来源,申请重新鉴定,拉长诉讼周期。倘若从育种伊始,盈电智控物联网技术便介入,情况将截然不同。利用区块链不可篡改、可全程追溯的特性,结合RFID电子标签或二维码,品种的亲本信息、育种地点、生长环境数据、扩繁过程等关键信息,从“田间”到“仓库”都被实时记录并固化下来,形成一份权威的“数字档案”。这份“数字身份证”,在侵权发生时将成为法庭上的“铁证”。维权者无需再艰难地自证清白,只需调取区块链上的存证记录,侵权种子从何而来,与授权品种的关联性一目了然。这不仅彻底颠覆了“对照样品来源不明”的质疑空间,更让法官能够依据高度可信的电子证据,快速完成“同一性”认定,显著减轻品种权人的举证负担,让维权周期大幅缩短。最高法提出“降低维权成本、减轻举证难度”,盈电智控物联网技术的落地正是对这一理念的科技呼应。当种业创新的每一步都被数字阳光清晰记录,侵权的“阴影”便无处藏身。为种子赋码,为创新护航,物联网这张无形的“天网”,正与司法保护的“法网”紧密交织,共同守护中国碗里的中国粮,让“种业振兴”的根基更加稳固。
-
在物联网和数字化管理时代,近场通信技术已成为连接物理世界与数字世界的关键桥梁。从商品溯源、资产盘点到会议签到、生产管理,NFC标签因其便捷、低成本和高安全性被广泛应用。然而,传统的单点读取模式在面对成百上千的标签时,效率低下、易出错、人力成本高的问题暴露无遗。批量读取技术正是破解这一困境,释放NFC数据采集全部潜力的金钥匙。 一、为何需要批量读取?传统方式的瓶颈传统的手持设备逐个读取标签(“嘀”一个处理一个)的方式主要存在以下瓶颈:效率极低:处理大量标签时,耗时呈线性增长,无法满足快速盘点和入库等场景需求。人工成本高:完全依赖人工操作,重复性劳动强度大,且容易因疲劳导致遗漏。数据不同步:读取的数据往往存储在设备本地,需要额外步骤上传至系统,无法实现实时化处理。易出错:手动操作难免存在重复读取或漏读的风险,数据准确性难以保障。批量读取技术旨在实现自动化、无人值守、高速并发的数据采集,彻底扭转上述局面。 二、技术核心:NFC批量读取是如何工作的?NFC通信基于RFID技术(通常是ISO 14443 Type A/B标准),其默认模式是“一对一”的对话。要实现“一对多”的批量读取,核心在于解决防冲突算法。1. 防冲突算法当读写器的射频能量场中同时存在多个标签时,它们会同时被激活并尝试响应,导致信号相互干扰(冲突),读写器无法识别任何数据。防冲突算法就像一位聪明的裁判,它的工作流程如下:初始化:读写器发出一个查询命令,进入识别区域。选择与静默:算法通过一系列指令(如基于UID的位仲裁),每次只“选择”一个标签进行通信。未被选中的标签则暂时保持“静默”状态。顺序读取:读写器与选中的标签完成数据交换后,会将其置为“休眠”状态,然后唤醒下一个标签。这个过程循环往复,直到区域内所有活跃标签都被读取完毕。2. 批量读取的两种模式静态批量读取:将一堆标签(例如一箱商品)一次性放置在读写器的天线上或非常靠近的区域。读写器启动扫描,在数秒内即可按顺序读取所有标签信息。这是最常见的模式,适用于仓库收发货、文件归档等。动态批量读取(通道门形式):在传送带或出入口通道上安装固定的读写器和天线,当贴有NFC标签的物品依次通过这个“门”时,系统会自动批量读取所有经过的物品信息。适用于物流分拣、生产线管理、无人零售结算等。 三、实现批量读取的核心组件硬件:专用批量读取读写器多天线端口:工业级批量读写器通常配备多个天线接口(如4个、8个甚至更多),可以通过扩展天线覆盖更大的物理区域(例如整个货架门、传送带两侧)。高功率输出:提供更强的射频场,能够同时激活更多标签,并增加读取距离(批量读取距离通常在5-40cm,远高于手机NFC的1-4cm)。多种通信接口:提供USB、以太网、Wi-Fi、蓝牙等接口,便于与PC、工控机或移动设备连接,实时上传数据。软件:核心驱动力驱动程序/SDK:硬件厂商会提供软件开发工具包,允许开发者调用底层的批量读取API。数据处理逻辑:软件需要处理读写器返回的标签数据流,包括去重、过滤、格式转换、错误校验等。集成与业务逻辑:将读取到的数据与后台系统对接,触发相应的业务流,如生成盘点报告、更新库存状态、发起调拨单等。 四、典型应用场景库存盘点与仓储管理:员工无需开箱,直接用读写器扫描整箱货物,瞬间完成数量清点和信息核对。物流与供应链在分拣中心,包裹在传送带上通过装有读写器的通道门,实现自动化的出入库记录和路径分拣。资产清查:快速扫描整个房间或货架上的资产标签,几分钟内完成原本需要数小时的盘点工作。智能档案管理:快速读取档案盒上的一批标签,瞬间定位所需档案,或完成借阅归还登记。零售与零售:在无人商店中,顾客将选购的商品放入智能购物篮,篮子底部的读写器可一次性读取所有商品并自动结算。总结NFC标签批量读取技术绝非简单的硬件堆砌,而是一套融合了射频工程、软件开发和业务流程优化的系统解决方案。它成功地将NFC技术从“手工作坊”带入了“工业自动化”时代,极大地释放了数据采集的潜力。对于寻求数字化转型的企业而言,理解和掌握这项技术,意味着在效率提升和成本控制的竞争中,掌握了又一把利刃。(图片来源于网络 侵删)
-
在工业4.0和物联网(IoT)浪潮的推动下,企业对资产、生产流程和物流管理的精细化、智能化提出了更高要求。传统的识别技术如条码、二维码、低频(LF)/高频(HF)RFID虽各具优势,但在某些苛刻的工业场景中仍存在读取距离短、易受干扰、无法批量处理等局限。而工业级NFC远距离读写器的出现,完美地弥补了这些短板,以其独特的综合优势,正成为驱动工业智能化升级的关键技术之一。 一、什么是工业级NFC远距离读写器?首先,需要厘清一个概念。传统NFC(近场通信)以其高安全性、便捷性著称,但通信距离通常仅在10厘米以内。而“远距离NFC”并非改变了NFC协议本身,而是特指遵循NFC频段(13.56MHz)的工业级RFID读写器,它能够读取兼容NFC标准的标签,并将读取距离大幅提升至几十厘米甚至超过一米。工业级则意味着该设备专为严苛环境设计,具备防尘、防水、抗金属干扰、宽温工作、高抗冲击和振动等特性,能够稳定运行于车间、仓库、户外等场景。 二、工业级NFC远距离读写器的核心应用优势与传统技术相比,工业级NFC远距离读写器的优势是全方位的:1. 卓越的环境适应性与可靠性工业环境充满挑战:油污、粉尘、高温、潮湿、电磁干扰无处不在。工业级NFC读写器坚固的外壳和内部设计确保了其在此类环境下的长期稳定运行。其采用的13.56MHz频率相比超高频(UHF)RFID,在靠近金属或液体表面时性能衰减更小,识别更稳定可靠,有效避免了RFID在金属资产管理中最头疼的“盲区”问题。2. “中距离”读取的独特价值相较于传统NFC的“贴身刷卡”,几十厘米至一米的读取距离实现了革命性的效率提升。操作员无需精确对准标签,只需手持设备或通过固定式读写器,在有效范围内即可快速批量采集数据。这完美平衡了操作便捷性与自动化程度:替代条码/二维码:无需肉眼对准扫描,可非接触、批量读取,效率更高。对比UHF RFID:读取距离可控,不易串读,在需要精准定位(如工具柜、智能货架)的场景中更具优势。3. 极高的数据安全性与交互性NFC技术内置加密与身份认证机制,数据安全性远高于条码和普通RFID。同时,NFC标签支持读写功能和能量(能量采集),这意味着:数据可更新:可以在标签的整个生命周期内反复写入数据,如记录设备维护、更新物流状态,使其成为移动的微型数据库。与手机无缝兼容:任何具备NFC功能的智能手机都能成为备用读写器,便于一线员工进行巡检、盘点、信息查询等操作,极大降低了部署和培训成本,实现了人与机器的无缝交互。4. 强大的批量数据处理与自动化能力固定式安装的工业级远距离NFC读写器可以7x24小时不间断工作。当贴有NFC标签的资产、产品、托盘经过门口、通道或特定节点时,系统能自动、批量地完成信息采集,并将数据实时上传至后台管理系统,实现全流程的自动化追溯与可视化管控,杜绝人为错误,提升运营透明度。5. 易于集成与部署基于国际通用的ISO/IEC 15693、14443等标准,工业级NFC读写器拥有开放的接口(如RS-232/485、以太网、Wi-Fi)和成熟的SDK,可以轻松与现有的自动化设备、PLC和软件平台集成,快速构建完整的物联网解决方案。 三、实际应用场景工业级NFC远距离读写器技术在多个领域有关键应用:智能制造业与产线管控:在自动化生产线上,读写器可远距离读取工件托盘或产品上的RFID标签,实时追踪生产进度、校验工艺参数、管理生产流程,提高生产效率和良品率。物流与仓储管理:在仓库货物进出RFID管控中,读写器能快速识别数米外叉车上的货物或整托盘的资产,实现高效的入库、出库、盘点操作,大幅提升物流效率。资产追踪与管理:对大型工厂、数据中心或实验室内的贵重设备、工具和资产进行粘贴RFID标签,通过固定式或手持式远距离读写器定期盘点,实现资产的精准定位和生命周期管理。智能书架与文档管理:在图书馆或档案室,集成在书架中的读写器可以非接触式批量快速识别书籍或文件的位置和信息,实现高效的借还、盘点和管理。门禁控制与身份认证:虽然传统门禁读卡距离短,但某些特殊区域(如停车场管理、无障碍通道)需要一定距离的车辆或人员身份识别,远距离读写器在此类应用中具备优势。 总结工业级NFC远距离读写器并非简单的技术升级,而是一次应用范式的革命。它成功地将NFC技术的便捷性、安全性与工业场景对距离、可靠性、效率和集成度的严苛要求相结合,为企业提供了前所未有的数据采集与管理能力。它不仅是连接物理世界与数字世界的可靠桥梁,更是企业降本增效、实现数字化转型、打造透明化、智能化工厂的战略性工具。选择工业级NFC远距离读写器,即是选择迈向未来智造的关键一步。(图片来源于网络 侵删)
-
近场通信(NFC)技术以其便捷、安全的特点,早已融入我们的日常生活,从手机支付到门禁卡,无不依赖其在10厘米以内的有效读取距离。这一短距离特性是其安全设计的基石。然而,在某些特定的工业和物流应用场景中,用户常常提出一个需求:能否远距离读取NFC标签?答案是:传统的被动式NFC标签无法实现真正的“远距离”读取,但通过一系列技术变通和方案创新,我们可以显著扩展其通信范围,以满足更多元化的需求。 一、为什么传统NFC读取距离如此之近? 要理解如何延长距离,首先需明白其限制的来源:物理原理:耦合方式NFC 14443采用电感耦合原理。读卡器天线产生交变磁场,标签天线通过电磁感应获取能量并产生回应。这种磁场强度随距离的三次方急剧衰减(~1/r³)。距离稍远,标签就无法获得足够的能量来启动芯片工作。协议与标准限制ISO/IEC 14443标准严格定义了通信的场强、调制方式、数据速率等参数。这些参数都是为了在10厘米以内的极近场域实现稳定、安全的通信而优化的。任何合规的设备都必须遵守这些规范,从而天然限制了距离。安全性与抗干扰性短距离是NFC安全特性的基石。它有效避免了恶意读卡器在用户不知情的情况下远程窃取信息(例如,隔着口袋读取钱包中的卡片)。同时,短距离也减少了环境中的无线电频率干扰,保证了通信的可靠性。 二、如何实现“远距离”读取?1. 优化标签端高灵敏度标签芯片: 采用专门设计的低功耗、高灵敏度芯片,能够在更弱的磁场中被激活。大尺寸与优化天线设计: 增大标签天线的尺寸和匝数,可以更有效地捕获磁能。通过精密仿真设计天线的谐振频率和阻抗匹配,能最大化能量接收和信号反射效率。柔性PCB天线或蚀刻天线通常比线圈天线性能更优。专为远距离设计的标签: 市场已出现一些专为远距离应用优化的NFC标签,其天线设计经过特殊优化,在特定方向的读取距离能有显著提升。2. 增强读卡器端高功率读写器: 在法规允许的范围内,使用输出功率更高的专业读写器模块。大尺寸与高Q值天线: 为读写器配备更大尺寸、高品质因数(Q值)的天线,可以产生更强、更集中的磁场。使用定向天线可以将能量聚焦在特定方向,从而延长该方向上的读取距离。采用高灵敏度的接收电路:使用专用的高性能信号处理芯片和先进的算法(如自适应均衡、数字信号处理DSP滤波),能够从强大的背景噪声中识别并提取出极其微弱的标签返回信号。这是实现远距离读取的关键技术之一。通过上述优化,专业的远距离NFC读写器可以将对标准14443标签的读取距离提升至40厘米甚至更远(如舜识1299TZF-FZ1 远距离NFC读写器)。需要注意的是:这种工业级的读写器通常功耗巨大,且设备笨重,不适合便携场景。 三、典型应用场景智能制造与产线管控:在自动化生产线上,读写器可远距离读取工件、托盘或设备上的标签,实现生产流程追溯、质量控制和设备管理。智能仓储与物流管理:应用于仓库货物进出管理、集装箱追踪和智能货架,实现高效库存盘点和物流跟踪。资产管理与工具追踪:在大型工厂、数据中心等场景中,对高价值资产和工具设备进行远距离识别和管理,提高资产利用率。智能书架和管理系统是典型应用场景。远距离读取能力使得可以快速盘点书籍资料,提高管理效率。产品防伪与质量追溯:特别在高端商品(如葡萄酒)等领域,实现产品全生命周期追踪与防伪验证。 四、 挑战与注意事项能量与信号的平衡:延长距离的核心矛盾。距离越远,标签获能越少,信号越弱,对读写器灵敏度要求呈指数级增长。方向性:无论是读写器的大天线还是标签的大天线,其方向性都会变强,需要更精确的对准才能达到最佳读取效果。干扰与安全性:更远的读取距离也可能带来意外的读取风险,需要考虑数据隐私和安全防护。同时,环境中的金属和液体对13.56MHz信号的干扰(吸收、反射)会更明显。成本与体积:高性能的读写器、大尺寸优化标签都意味着更高的成本和更大的体积。结论NFC标签的“远距离”读取并非通过违背物理定律,而是通过极致优化读写器性能(大功率、高灵敏度、大天线)和大尺寸优化标签来实现的技术突破。它并非标准NFC的用途,而是一种针对特定行业应用的专业化扩展。虽然它无法像UHF RFID那样实现数十米的读取距离,但通过专业设备将读取范围从10厘米扩展到40厘米以上,已经为许多之前无法应用NFC的场景打开了大门。在选择方案时,必须仔细权衡其对距离、成本、方向性和合规性的具体要求。(图片来源于网络 侵删)
-
前言介绍在万物互联的数字化时代,物联网(IoT)技术正以前所未有的速度重塑着传统产业格局,推动农业、工业、医疗、家居等多个领域的智能化升级。作为嵌入式系统开发中的核心控制器之一,STM32系列微控制器凭借其高性能、低功耗、高可靠性以及丰富的外设资源,已成为物联网终端设备开发的首选平台。其中,STM32F103C8T6以其高性价比和广泛的支持生态,在智能硬件项目中得到了广泛应用。与此同时,以华为云为代表的云平台为物联网系统提供了强大的数据处理、设备管理、远程监控与可视化能力,使得海量终端设备能够实现高效互联与智能协同。将STM32等嵌入式终端与华为云平台深度融合,不仅实现了物理世界与数字世界的无缝连接,更构建起“端-边-云”一体化的智能系统架构。本文系统梳理本月物联网论坛基于STM32F103C8T6与华为云平台的一系列典型应用实践,涵盖智能农业、实验室管理、医疗存储、能源设施、楼宇控制、工业监控等多个场景。通过对这些项目的技术架构、功能实现与创新价值进行归纳与分析,展现嵌入式技术与云计算融合的巨大潜力,为物联网开发者、科研人员及工程技术人员提供可借鉴的设计思路与实践参考,助力更多智能化解决方案的落地与推广。文章列表STM32F103C8T6的智能农业大棚监控系统与华为云平台设计https://bbs.huaweicloud.com/forum/thread-0293191225619938084-1-1.htmlSTM32F103C8T6的智能实验室危化品管理系统设计与华为云实现https://bbs.huaweicloud.com/forum/thread-0228191225707856076-1-1.htmlSTM32F103C8T6的智能医疗药品存储柜系统设计与华为云实现https://bbs.huaweicloud.com/forum/thread-02114191225749892084-1-1.htmlSTM32驱动的智能农业灌溉系统与华为云管理平台https://bbs.huaweicloud.com/forum/thread-0228191225776351077-1-1.htmlSTM32与华为云联动的智能电动车充电桩管理系统https://bbs.huaweicloud.com/forum/thread-0293191225812586085-1-1.html基于STM32F103C8T6的智能家居健康环境监测系统https://bbs.huaweicloud.com/forum/thread-0223191225852569089-1-1.html基于STM32F103C8T6的智能健身姿态矫正系统设计与华为云实现https://bbs.huaweicloud.com/forum/thread-0228191225878912078-1-1.html基于STM32F103C8T6与华为云的智能楼宇照明控制系统设计https://bbs.huaweicloud.com/forum/thread-0223191225958175090-1-1.html基于STM32的工业设备状态监控与华为云预警系统https://bbs.huaweicloud.com/forum/thread-0223191225988128091-1-1.html基于STM32与华为云的智能家居环境监测系统设计https://bbs.huaweicloud.com/forum/thread-0231191226019372058-1-1.html基于华为云的STM32F103C8T6智能停车场管理系统https://bbs.huaweicloud.com/forum/thread-02102191226044540068-1-1.html基于华为云的STM32F103C8T6智能植物工厂监控系统https://bbs.huaweicloud.com/forum/thread-0293191226073363086-1-1.html基于华为云的STM32智能仓储防火防盗监控系统https://bbs.huaweicloud.com/forum/thread-0231191226192547059-1-1.html基于华为云平台的STM32F103C8T6工业生产线温湿度监控系统https://bbs.huaweicloud.com/forum/thread-02122191226224584073-1-1.html
-
已知:Host路由信息[huawei ~]$ route -nKernel IP routing tableDestination Gateway Genmask Flags Metric Ref Use Iface172.17.0.0 0.0.0.0 255.255.255.0 U 0 0 0 br_docker0172.20.74.0 0.0.0.0 255.255.255.0 U 0 0 0 GE4192.168.20.0 0.0.0.0 255.255.255.0 U 0 0 0 br_lsw192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 br0lxc容器app中获取路由信息:主题:app1/get/request/esdk/ipRoute响应关联部分:{"type":"unicast","dstIp":"172.20.74.0","dstPrefixLength":24,"proto":"kernel","metric":0,"family":"inet","nhs":[{"via":"","dev":"GE4","ifIndex":1004}]},{"type":"broadcast","dstIp":"172.20.74.0","dstPrefixLength":32,"proto":"kernel","metric":0,"family":"inet","nhs":[{"via":"","dev":"GE4","ifIndex":1004}]},{"type":"local","dstIp":"172.20.74.10","dstPrefixLength":32,"proto":"kernel","metric":0,"family":"inet","nhs":[{"via":"","dev":"GE4","ifIndex":1004}]},{"type":"broadcast","dstIp":"172.20.74.255","dstPrefixLength":32,"proto":"kernel","metric":0,"family":"inet","nhs":[{"via":"","dev":"GE4","ifIndex":1004}]} 执行删除路由:提示不存在Client mosqsub|903-lxc01 received PUBLISH (d0, q0, r0, m0, 'app1/set/request/esdk/ipRoute', ... (192 bytes)){"token":"12345","timestamp":"2025-08-21T14:13:43Z","body":{"operation":"delete","route":[{"dstIp":"172.20.74.0","dstPrefixLength":24,"family":"inet","via":"0.0.0.0","metric":0,"dev":"GE4"}]}}Client mosqsub|903-lxc01 received PUBLISH (d0, q0, r0, m0, 'esdk/set/response/app1/ipRoute', ... (286 bytes)){"token": "12345", "timestamp": "2025-02-26T16:31:50Z", "statusCode": 500, "statusDesc": "Internal Server Error", "body": {"errorDesc": "Inner error: Route doesn't exist in the configuration table(Error config: dstIp=172.20.74.0, dstPrefixLength=24, via=0.0.0.0, dev=GE4, metric=0)."}}执行添加路由:提示已存在Client mosqsub|903-lxc01 received PUBLISH (d0, q0, r0, m0, 'app1/set/request/esdk/ipRoute', ... (189 bytes)){"token":"12345","timestamp":"2025-08-21T14:13:43Z","body":{"operation":"add","route":[{"dstIp":"172.20.74.0","dstPrefixLength":24,"family":"inet","via":"0.0.0.0","metric":0,"dev":"GE4"}]}}Client mosqsub|903-lxc01 received PUBLISH (d0, q0, r0, m0, 'esdk/set/response/app1/ipRoute', ... (252 bytes)){"token": "12345", "timestamp": "2025-02-26T16:33:14Z", "statusCode": 500, "statusDesc": "Internal Server Error", "body": {"errorDesc": "Inner error: Route exists(Error config: dstIp=172.20.74.0, dstPrefixLength=24, via=0.0.0.0, dev=GE4, metric=0)."}}以上问题把via设置为via=""也是同样的结果,死循环中... 执行添加路由:关联172.20.74.255网关提示参数校验失败,如果是其他地址则可以成功,如172.20.74.254Client mosqsub|6707-lxc01 received PUBLISH (d0, q0, r0, m0, 'app1/set/request/esdk/ipRoute', ... (194 bytes)){"token":"12345","timestamp":"2025-08-21T14:13:43Z","body":{"operation":"add","route":[{"dstIp":"172.20.0.0","dstPrefixLength":16,"family":"inet","via":"172.20.74.255","metric":0,"dev":"GE4"}]}}Client mosqsub|6707-lxc01 received PUBLISH (d0, q0, r0, m0, 'esdk/set/response/app1/ipRoute', ... (276 bytes)){"token": "12345", "timestamp": "2025-02-26T16:40:49Z", "statusCode": 500, "statusDesc": "Internal Server Error", "body": {"errorDesc": "Inner error: Invalid input data or parameter(Error config: dstIp=172.20.0.0, dstPrefixLength=16, via=172.20.74.255, dev=GE4, metric=0)."}} 请问如何解决这类问题?
-
我代码想烧录的WiFi密码是123456789,但是烧录成功后却显示是12345678
-
请问小程序可以用mqtt直接订阅设备属性并显示吗?然后设备检测到的数据在小程序上实时流动变化(我需要的就是这个功能),如果不行还有什么方便的方法吗?
-
开发者们,大家好!2025数博会系列赛暨华为开发者大赛贵州赛区 的赛题专家讲解环节,已经精彩呈现!本次大赛聚焦前沿技术与产业应用,本次讲解深入浅出地剖析了赛题的核心挑战与创新方向,不仅为参赛开发者们指明了思路、拓宽了视野,更激发了大家探索数智技术、解决实际问题的潜能。这不仅仅是竞技的舞台,更是创新人才与前沿技术碰撞交流的盛会。通过专家的解读,我们得以窥见未来技术突破的可能,感受贵州赛区乃至全国开发者群体的智慧与热情。现在,就让我们一同深入精彩讲解,洞察赛题背后的技术精髓与产业价值,共同期待这场“数智时代”创新人才的精彩绽放!鸿蒙应用创新赛题依托华为云全场景服务与鸿蒙分布式能力,面向智慧生活、智慧城市、智慧工业等领域开放命题。参赛者可结合AI、大数据、物联网等技术,开发端云协同解决方案,如家庭健康管家、城市环境精细化治理、工业生产智能监测等。昇腾云AI创新赛题基于昇腾云服务和MindSpore大模型能力,推动人工智能在实体经济的深度渗透。参赛方向涵盖食饮行业质量检测、文旅行业智慧导览等场景,如酱酒异物检测、智能导览规划推荐等,助力贵州产业提质增效。赋能讲解视频链接:
-
前言随着物联网(IoT)技术、嵌入式系统和智能控制技术的迅猛发展,基于STM32单片机的智能监控与自动控制系统在农业、工业、交通、医疗、家居等多个领域中得到了广泛应用。STM32具有高性能、低功耗、外围接口丰富等优势,是现代智能系统设计的理想平台。本汇总精选了18个基于STM32的典型智能系统设计项目,涵盖了从工业仓储、智慧农业、智能交通到家庭健康、宠物养护等多个应用场景,体现了嵌入式系统在现实生活中的多样化与实用性。每个项目均以实际应用为导向,结合传感器、通信模块、控制算法和界面交互,展现出良好的系统集成能力与工程实现价值。文章总汇1. 基于STM32的工业仓库环境智能监控系统设计https://bbs.huaweicloud.com/forum/thread-0291185968094776036-1-1.html本项目设计了一套可实现仓库环境参数(如温湿度、烟雾、气体浓度等)实时监测与报警的智能系统。系统集成多种传感器,结合无线通信模块与本地显示功能,实现对仓库安全状态的智能化、自动化管理。2. 基于STM32的可编程自动宠物喂食系统设计https://bbs.huaweicloud.com/forum/thread-0291185968216895037-1-1.html本系统实现对宠物喂食的自动化控制,支持定时定量喂食、语音控制、远程APP操作、余粮监测等功能。系统通过步进电机、称重模块、语音模块等硬件协同工作,提升了宠物主人的管理效率与宠物的喂养质量。3. 基于STM32的冷库智能监控与预警系统设计https://bbs.huaweicloud.com/forum/thread-0206185968255852024-1-1.html该系统专为低温冷藏环境设计,实时监控冷库的温湿度、电源状态与门禁状况,结合报警模块及时响应异常情况,保障冷藏物品安全。支持本地显示与远程数据上传。4. 基于STM32的冷链物流智能监控终端设计https://bbs.huaweicloud.com/forum/thread-0206185968296466025-1-1.html本设计面向冷链运输场景,采用STM32监控货物环境温湿度与位置,结合GPS和4G模块实现全程数据记录与实时上传,为冷链运输安全与可追溯性提供技术保障。5. 基于STM32的远程农田智能灌溉系统设计https://bbs.huaweicloud.com/forum/thread-0206185968346839026-1-1.html该项目针对农田灌溉需求,通过土壤湿度、温度、光照等参数控制水泵自动启停,实现节水、节能的智能灌溉模式,支持远程控制与定时灌溉设置。6. 基于STM32的智慧农业温室环境监测与调控系统设计https://bbs.huaweicloud.com/forum/thread-0254185968388106028-1-1.html本系统集成光照、温湿度、土壤湿度、二氧化碳等传感器,并通过继电器控制通风、加热、补光、灌溉等装置,实现温室环境的精细化调控。7. 基于STM32和华为云的智能人体健康监测系统设计https://bbs.huaweicloud.com/forum/thread-0234185968959318033-1-1.html本系统可监测体温、心率、血氧等生命体征参数,并通过ESP8266将数据上传至华为云物联网平台,实现远程健康数据管理与异常预警,适用于康养场景。8. 基于STM32的智能车位监测系统设计https://bbs.huaweicloud.com/forum/thread-02112185968480551034-1-1.html本系统利用超声波传感器检测车位占用状态,通过无线模块上传数据至服务器或APP,实现停车位实时可视化,缓解停车难题,提高停车场使用效率。9. 基于STM32的智能车载酒驾检测与定位报警系统设计https://bbs.huaweicloud.com/forum/thread-02127185968528808038-1-1.html该系统通过酒精传感器实时检测驾驶员体内酒精浓度,超标时触发报警并自动通过GPS进行定位上传,同时阻止车辆启动,从源头预防酒驾事故。10. 基于STM32的智能家居健康环境监测系统https://bbs.huaweicloud.com/forum/thread-02101185968581225032-1-1.html系统整合了空气质量、温湿度、CO₂浓度等多个传感器,实现对家庭环境健康状况的全面感知与智能提醒,同时可联动空气净化器、加湿器等设备自动响应。11. 基于STM32的智能快递柜控制系统设计https://bbs.huaweicloud.com/forum/thread-02101185968637426033-1-1.html本项目设计了一种具备身份识别、自动分箱、远程开柜等功能的快递柜控制系统,利用RFID、密码输入、LCD显示和联网模块,实现快递智能投递与取件。12. 基于STM32的智能垃圾桶监控系统设计https://bbs.huaweicloud.com/forum/thread-02101185968682628034-1-1.html该系统支持垃圾桶满溢检测、异味监测与分类开盖控制,结合WIFI模块将垃圾状态实时上传至云端,实现城市智能环卫管理。13. 基于STM32的智能路灯远程控制与环境感知系统设计https://bbs.huaweicloud.com/forum/thread-0254185968727875029-1-1.html设计了一套集光照感应、人员检测、定时开关灯、远程控制等功能于一体的智能路灯系统,有效提升城市照明能效并降低维护成本。14. 基于STM32的智能停车位监测系统设计https://bbs.huaweicloud.com/forum/thread-0206185968773205027-1-1.html与车位监测系统类似,本设计重点突出在城市路边停车管理上,通过车辆检测与状态上报,结合小程序或云平台,提升智慧城市交通管理水平。15. 基于STM32的智能药箱监控系统设计https://bbs.huaweicloud.com/forum/thread-0254185968826195030-1-1.html该系统可记录用药时间、发送提醒、识别药品种类与用量,结合LCD显示与APP远程管理,实现老人或慢病患者的规范化、智能化用药辅助。16. 基于STM32的智能饮水机控制系统设计https://bbs.huaweicloud.com/forum/thread-0254185968862970031-1-1.html本设计实现对饮水加热、冷却、出水等过程的自动控制,并支持水质监测、用水记录与预约取水等功能,提升饮水的便利性与安全性。17. 基于STM32的智能鱼缸监控与控制系统设计https://bbs.huaweicloud.com/forum/thread-02101185968901534035-1-1.html通过检测水温、水质、光照、氧气含量等参数,系统可自动控制加热器、氧气泵、照明灯等,实现对观赏鱼健康生活环境的全面监控与调节。18. 基于STM32的智慧农业温室环境监测与联动控制系统https://bbs.huaweicloud.com/forum/thread-0255185968433915030-1-1.html在环境监测基础上增加设备间联动机制,实现数据驱动下的智能响应。例如当温度过高时自动开启排风系统,整体提升农业温室的自动化与智能化水平。
-
项目开发背景随着全球人口老龄化趋势加剧和慢性疾病发病率上升,持续性的健康监测需求日益迫切。心血管疾病作为主要的健康威胁之一,其早期预警和日常管理对降低风险至关重要,而体温则是反映人体基本生理状态的重要指标。传统医疗监测设备通常体积庞大、成本高昂且依赖专业环境,难以满足家庭或个人日常便捷、实时的健康管理需求。现有家用健康设备功能单一、数据孤立,缺乏有效的远程管理和智能分析能力。用户无法及时获取异常预警,医护人员也难以对居家患者进行长期、系统的健康数据跟踪。因此,开发一种低功耗、易部署且具备云端协同能力的智能监测系统,成为提升个人健康管理效率和及时干预能力的关键突破口。物联网技术与云计算的快速发展为此提供了技术基础。以高性能低功耗的STM32F103C8T6微控制器为核心,结合高精度传感器(如MAX30100心率模块、DHT11温湿度模块)和无线通信模块(ESP8266),可构建轻量化的实时数据采集终端。同时,依托华为云物联网平台强大的设备接入、数据存储与分析能力,能实现海量健康数据的安全汇聚与高效处理。配合跨平台的上位机软件,可为用户提供直观的数据可视化、历史回溯及智能预警服务。本设计通过整合嵌入式传感技术、无线通信、云平台及客户端应用,构建一套完整的“端-云-应用”协同系统,旨在为个人及家庭提供低成本、高可用的健康监测解决方案,推动健康管理向智能化、远程化和预防化方向发展。设计实现的功能(1) STM32F103C8T6通过I2C协议读取MAX30100心率血氧传感器的心率数据。(2) STM32F103C8T6通过单总线协议读取DHT11温湿度传感器的体温数据。(3) STM32F103C8T6通过UART串口与ESP8266-01S WiFi模块通信,使用MQTT协议将数据上传到华为云物联网服务器。(4) 华为云物联网服务器配置设备接入服务,接收、存储和处理传感器数据。(5) 上位机QT应用使用C++语言开发,通过Paho MQTT客户端库连接到华为云服务器,订阅数据主题并实现实时数据解析。(6) 上位机软件实现数据动态图表绘制、历史数据查询界面、阈值设置面板和异常警报功能。项目硬件模块组成(1) STM32F103C8T6核心板(2) MAX30100心率血氧传感器模块(3) DHT11温湿度传感器模块(4) ESP8266-01S WiFi模块(5) USB转TTL模块用于串口调试和供电(6) 5V直流电源适配器设计意义本设计基于STM32F103C8T6与华为云构建的智能人体健康监测系统,具有重要的现实意义和应用价值。该系统通过实时采集心率与体温数据,为用户提供连续、便捷的健康状态监测服务,尤其适用于家庭健康监护、康复期患者管理或老年人日常健康关注等场景,有效弥补了传统定期体检在时效性与连续性上的不足。系统深度融合了嵌入式感知技术、无线通信技术与云计算技术。STM32作为本地核心处理器,可靠地完成了多协议传感器数据采集与初步处理;ESP8266模块利用MQTT协议实现低功耗、高效率的无线数据传输;华为云物联网平台则为海量异构数据提供了安全稳定的接入、存储与处理能力。这种架构充分体现了物联网技术在健康领域的典型应用模式,验证了“端-边-云”协同的技术可行性。上位机QT软件的设计显著提升了系统的可用性与数据价值。其实时动态曲线可视化功能直观呈现生理参数变化趋势,便于用户快速掌握健康动态;历史数据查询与CSV导出功能则支持长期健康追踪与深度分析,为个人健康管理或医疗研究提供了数据基础。这种直观的数据交互方式极大增强了用户体验。系统设置的智能预警机制是保障用户安全的关键环节。通过自定义心率与体温阈值范围,配合上位机的声光报警功能,能够在检测到异常生理参数时第一时间发出警示。这种主动式监护模式显著降低了因健康突发状况延误处置的风险,为用户争取宝贵的应对时间,体现了技术对生命健康的守护价值。设计思路设计思路:系统以STM32F103C8T6微控制器为核心,负责协调各传感器模块与通信模块的工作。首先,通过I2C接口连接MAX30100传感器,周期性读取心率数据;同时通过单总线协议连接DHT11传感器获取体温数据。STM32对采集的数据进行初步处理(如滤波、单位转换)后,通过UART串口将数据发送给ESP8266-01S模块。ESP8266-01S模块通过AT指令集与STM32交互,配置为STA模式连接无线网络,并基于MQTT协议接入华为云物联网平台。STM32将传感器数据封装为符合华为云物模型格式的JSON消息,由ESP8266发送至云平台指定主题。华为云物联网平台接收数据后,通过规则引擎将数据转发到云数据库进行持久化存储,同时支持数据导出功能。上位机部分采用QT框架开发,使用Paho MQTT客户端库订阅华为云平台的数据主题。当接收到新数据时,解析JSON消息并更新实时显示面板。动态曲线图通过QChart组件实现,展示心率和体温的实时变化趋势。历史数据查询功能通过调用华为云API获取指定时间段的存储数据,并以表格形式展示。用户可在阈值设置面板自定义心率、体温的安全范围,当实时数据越界时,QT应用触发QSound播放警报音效,同时界面闪烁红色警示。异常处理机制贯穿系统:STM32层面设置传感器通信超时检测;ESP8266建立重连机制应对网络波动;华为云规则引擎配置数据异常告警;上位机软件加入数据校验逻辑,防止无效数据触发误报警。各模块间通过状态指示灯反馈运行状态,便于调试与维护。框架图系统框架图+-----------------------------------------------------------------+ | 华为云物联网服务器 | | +-----------------------------+ +-------------------------+ | | | 设备接入服务 (IoTDA) |<->| 数据存储服务 | | | | - MQTT Broker | | - 长期存储传感器数据 | | | | - 设备认证与管理 | | - CSV导出功能 | | | +-----------------------------+ +-------------------------+ | | ^ | | | | MQTT over Internet | API调用 | | | v | +--------|------------------------------------------|------------+ | | | WiFi | Internet +--------|-----------------+ +---------|----------------+ | STM32F103C8T6 系统 | | 上位机 QT应用 | | +---------------------+ | UART | +---------------------+ | | | 传感器数据采集层 |<------------->| | 数据可视化与告警层 | | | | - MAX30100 (I2C) | | +------+ | | - 实时曲线图 | | | | → 心率数据 | | |ESP8266| | | - 历史数据查询 | | | | - DHT11 (单总线) | | |WiFi模| | | - 阈值报警系统 | | | | → 体温数据 | | +------+ | | (声光警报) | | | +---------------------+ | | +---------------------+ | | ^ | +-------------------------+ | | 传感器接口 | +--------|------------------+ | +--------|------------------+ | v | | +---------------------+ | | | 传感器层 | | | | - MAX30100模块 | | | | - DHT11模块 | | | +---------------------+ | +---------------------------+ 模块说明:传感器层MAX30100:通过I2C协议提供心率数据DHT11:通过单总线协议提供体温数据STM32F103C8T6系统传感器数据采集层:处理I2C/单总线协议,聚合传感器数据ESP8266通信:通过UART串口将MQTT封装数据发送至WiFi模块网络传输ESP8266-01S:通过WiFi连接互联网,使用MQTT协议上传数据到华为云华为云物联网平台设备接入服务(IoTDA):MQTT消息代理,实现设备认证和数据路由数据存储服务:长期存储结构化数据,支持CSV导出上位机QT应用数据可视化:实时曲线图/历史数据图表渲染告警系统:阈值检测触发声光警报MQTT订阅:通过Paho库从华为云获取实时数据系统总体设计系统总体设计本系统构建了一个端到端的智能人体健康监测平台,以STM32F103C8T6微控制器为核心,整合传感器数据采集、无线通信、云平台存储与处理和上位机可视化功能。系统通过STM32实时采集用户的心率与体温数据,利用ESP8266 WiFi模块将数据安全传输至华为云物联网平台进行集中存储与分析。同时,开发基于QT框架的上位机应用,动态订阅云端数据流,实现数据的实时显示、历史回溯、阈值预警及管理功能。在硬件层,STM32F103C8T6作为本地处理中枢。它通过I2C总线协议驱动MAX30100心率血氧传感器,精确获取心率信号;通过单总线协议与DHT11温湿度传感器通信,提取体温数据。采集到的数据经过初步处理后,STM32通过UART串口与ESP8266-01S WiFi模块交互,封装成符合MQTT协议的数据包,经无线网络上传至华为云物联网服务器。华为云物联网平台作为系统的数据中心枢纽。它提供设备接入服务,接收并验证来自ESP8266的MQTT数据流。平台对传感器数据进行结构化存储,建立长期历史数据库,并提供数据导出为CSV格式的功能,确保数据的持久化与可追溯性。平台同时承担数据路由角色,将实时数据推送给已订阅的上位机应用。上位机软件采用QT框架开发,集成Paho MQTT客户端库。该应用主动连接华为云服务器,订阅指定的MQTT主题以接收实时心率与体温数据流。软件核心功能包括:动态曲线绘制模块,以可视化图表展示实时生理参数变化;历史数据查询界面,支持按时间范围检索云端记录;可配置阈值管理面板,允许用户设定心率与体温的安全范围。当监测数据超越预设阈值时,软件立即触发声光警报机制,实现异常状态的即时预警。整个系统形成从终端感知、云端中继到上位机监控的闭环数据流,满足健康监测的实时性、可靠性与可管理性需求。系统功能总结功能模块功能描述数据采集通过MAX30100心率血氧传感器(I2C协议)实时采集用户心率数据通过DHT11温湿度传感器(单总线协议)实时采集用户体温数据数据传输STM32通过UART串口驱动ESP8266-01S WiFi模块,使用MQTT协议上传数据至华为云云平台处理华为云物联网服务器接收、存储和处理传感器数据实现数据长期存储,支持CSV格式导出上位机监控QT应用通过Paho MQTT订阅华为云数据,实时显示心率和体温数值动态曲线图展示实时数据变化趋势数据分析提供历史数据查询界面,支持按时间范围检索数据允许设置心率/体温阈值,超限时触发声光警报设计的各个功能模块描述STM32F103C8T6微控制器作为核心处理单元,通过I2C协议与MAX30100心率血氧传感器通信,实时采集用户心率数据。同时利用单总线协议连接DHT11温湿度传感器获取体温数据,完成对两项健康指标的同步监测。传感器数据通过UART串口传输至ESP8266-01S WiFi模块,该模块基于MQTT协议与华为云物联网服务器建立安全连接,实现采集数据的实时上传。华为云物联网平台配置专用设备接入服务,接收并存储传感器数据流,提供长期数据归档管理,支持通过云端接口导出CSV格式的历史数据文件。上位机QT应用集成Paho MQTT客户端库,订阅华为云服务器的数据主题通道,实时解析心率体温数据流。软件界面动态绘制数据曲线图,直观展示实时变化趋势,同时提供历史数据查询面板,支持按时间范围检索云端存储记录。异常监测模块通过独立配置界面设置心率体温阈值参数。当实时数据流超过安全范围时,QT应用立即触发声光报警系统,包括界面警示色闪烁与蜂鸣器提示。所有告警事件同步记录至历史数据库,便于后续追溯分析。上位机代码设计#include <QApplication> #include <QMainWindow> #include <QtMqtt/QMqttClient> #include <QChart> #include <QChartView> #include <QLineSeries> #include <QValueAxis> #include <QDateTimeAxis> #include <QSqlDatabase> #include <QSqlQuery> #include <QSqlError> #include <QVBoxLayout> #include <QHBoxLayout> #include <QPushButton> #include <QLabel> #include <QLineEdit> #include <QSpinBox> #include <QMessageBox> #include <QFileDialog> #include <QSoundEffect> #include <QTimer> QT_CHARTS_USE_NAMESPACE class MainWindow : public QMainWindow { Q_OBJECT public: MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) { setupUI(); setupDatabase(); setupMQTT(); } private slots: void onConnected() { qDebug() << "Connected to Huawei Cloud!"; mqttClient->subscribe("sensor/data"); } void onMessageReceived(const QByteArray &message, const QString &topic) { QJsonDocument doc = QJsonDocument::fromJson(message); QJsonObject obj = doc.object(); double heartRate = obj["heart_rate"].toDouble(); double bodyTemp = obj["temperature"].toDouble(); // 更新实时数据 lblHeartRate->setText(QString::number(heartRate)); lblTemperature->setText(QString::number(bodyTemp)); // 添加数据到图表 QDateTime now = QDateTime::currentDateTime(); heartRateSeries->append(now.toMSecsSinceEpoch(), heartRate); tempSeries->append(now.toMSecsSinceEpoch(), bodyTemp); // 限制数据点数量 if (heartRateSeries->count() > 100) heartRateSeries->remove(0); if (tempSeries->count() > 100) tempSeries->remove(0); // 更新图表范围 chart->axisX()->setRange(now.addSecs(-60), now); chart->axisY()->setRange(0, 150); // 检查阈值报警 checkThresholds(heartRate, bodyTemp); // 存储到数据库 saveToDatabase(heartRate, bodyTemp); } void onThresholdChanged() { heartRateThreshold = spinHeartRate->value(); tempThreshold = spinTemperature->value(); } void onExportClicked() { QString fileName = QFileDialog::getSaveFileName(this, "Export CSV", "", "CSV Files (*.csv)"); if (fileName.isEmpty()) return; QFile file(fileName); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) return; QTextStream out(&file); out << "Timestamp,HeartRate,Temperature\n"; QSqlQuery query("SELECT timestamp, heart_rate, temperature FROM sensor_data"); while (query.next()) { out << query.value(0).toString() << "," << query.value(1).toString() << "," << query.value(2).toString() << "\n"; } file.close(); } private: void setupUI() { QWidget *centralWidget = new QWidget(this); QVBoxLayout *mainLayout = new QVBoxLayout(centralWidget); // 实时数据显示 QHBoxLayout *dataLayout = new QHBoxLayout(); lblHeartRate = new QLabel("--", this); lblTemperature = new QLabel("--", this); dataLayout->addWidget(new QLabel("Heart Rate:")); dataLayout->addWidget(lblHeartRate); dataLayout->addWidget(new QLabel("°C Temperature:")); dataLayout->addWidget(lblTemperature); mainLayout->addLayout(dataLayout); // 图表初始化 chart = new QChart(); heartRateSeries = new QLineSeries(); heartRateSeries->setName("Heart Rate"); tempSeries = new QLineSeries(); tempSeries->setName("Temperature"); chart->addSeries(heartRateSeries); chart->addSeries(tempSeries); QDateTimeAxis *axisX = new QDateTimeAxis(); axisX->setFormat("hh:mm:ss"); chart->addAxis(axisX, Qt::AlignBottom); heartRateSeries->attachAxis(axisX); tempSeries->attachAxis(axisX); QValueAxis *axisY = new QValueAxis(); axisY->setRange(0, 150); chart->addAxis(axisY, Qt::AlignLeft); heartRateSeries->attachAxis(axisY); tempSeries->attachAxis(axisY); chartView = new QChartView(chart); mainLayout->addWidget(chartView); // 阈值设置 QHBoxLayout *thresholdLayout = new QHBoxLayout(); spinHeartRate = new QSpinBox(this); spinHeartRate->setRange(40, 150); spinHeartRate->setValue(100); spinTemperature = new QSpinBox(this); spinTemperature->setRange(35, 42); spinTemperature->setValue(38); thresholdLayout->addWidget(new QLabel("Heart Rate Alert:")); thresholdLayout->addWidget(spinHeartRate); thresholdLayout->addWidget(new QLabel("°C Temp Alert:")); thresholdLayout->addWidget(spinTemperature); connect(spinHeartRate, SIGNAL(valueChanged(int)), this, SLOT(onThresholdChanged())); connect(spinTemperature, SIGNAL(valueChanged(int)), this, SLOT(onThresholdChanged())); // 报警指示器 alarmIndicator = new QLabel("NORMAL", this); alarmIndicator->setStyleSheet("background-color: green; color: white; padding: 5px;"); thresholdLayout->addWidget(alarmIndicator); // 导出按钮 QPushButton *exportButton = new QPushButton("Export CSV", this); thresholdLayout->addWidget(exportButton); connect(exportButton, SIGNAL(clicked()), this, SLOT(onExportClicked())); mainLayout->addLayout(thresholdLayout); setCentralWidget(centralWidget); resize(800, 600); // 初始化阈值 heartRateThreshold = 100; tempThreshold = 38; // 报警音效 alarmSound = new QSoundEffect(this); alarmSound->setSource(QUrl::fromLocalFile("alarm.wav")); } void setupDatabase() { QSqlDatabase db = QSqlDatabase::addDatabase("QSQLITE"); db.setDatabaseName("sensor_data.db"); if (!db.open()) { QMessageBox::critical(this, "Database Error", db.lastError().text()); return; } QSqlQuery query; query.exec("CREATE TABLE IF NOT EXISTS sensor_data (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "timestamp DATETIME DEFAULT CURRENT_TIMESTAMP, " "heart_rate REAL, " "temperature REAL)"); } void setupMQTT() { mqttClient = new QMqttClient(this); mqttClient->setHostname("your_huaweicloud_address"); // 替换实际地址 mqttClient->setPort(1883); mqttClient->setClientId("your_client_id"); mqttClient->setUsername("your_username"); mqttClient->setPassword("your_password"); connect(mqttClient, &QMqttClient::connected, this, &MainWindow::onConnected); connect(mqttClient, &QMqttClient::messageReceived, this, &MainWindow::onMessageReceived); mqttClient->connectToHost(); } void checkThresholds(double heartRate, double temperature) { bool isAlarm = false; if (heartRate > heartRateThreshold) { alarmIndicator->setText("HIGH HEART RATE!"); isAlarm = true; } if (temperature > tempThreshold) { alarmIndicator->setText("HIGH TEMPERATURE!"); isAlarm = true; } if (isAlarm) { alarmIndicator->setStyleSheet("background-color: red; color: white; padding: 5px;"); alarmSound->play(); } else { alarmIndicator->setText("NORMAL"); alarmIndicator->setStyleSheet("background-color: green; color: white; padding: 5px;"); } } void saveToDatabase(double heartRate, double temperature) { QSqlQuery query; query.prepare("INSERT INTO sensor_data (heart_rate, temperature) VALUES (?, ?)"); query.addBindValue(heartRate); query.addBindValue(temperature); query.exec(); } // UI Components QLabel *lblHeartRate; QLabel *lblTemperature; QLabel *alarmIndicator; QChart *chart; QChartView *chartView; QLineSeries *heartRateSeries; QLineSeries *tempSeries; QSpinBox *spinHeartRate; QSpinBox *spinTemperature; QSoundEffect *alarmSound; // MQTT Client QMqttClient *mqttClient; // Thresholds int heartRateThreshold; int tempThreshold; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); // 初始化数据库驱动 QSqlDatabase::addDatabase("QSQLITE"); MainWindow mainWin; mainWin.show(); return app.exec(); } #include "main.moc" // 包含元对象编译器生成的代码 代码说明MQTT通信:使用QMqttClient连接华为云IoT平台订阅sensor/data主题接收传感器数据消息格式为JSON:{"heart_rate": 75.3, "temperature": 36.5}实时数据显示:顶部标签显示最新心率和体温值使用QChart动态绘制实时曲线图自动调整X轴时间范围为最近60秒阈值报警:设置心率/体温阈值(默认100bpm/38℃)超出阈值时:界面显示红色警报标识播放报警音效(需准备alarm.wav文件)正常状态显示绿色"NORMAL"标识数据存储与导出:使用SQLite数据库存储历史数据数据表结构:timestamp | heart_rate | temperatureCSV导出功能包含时间戳和传感器数据华为云配置:需替换实际连接参数:mqttClient->setHostname("your_huaweicloud_address"); mqttClient->setClientId("your_client_id"); mqttClient->setUsername("your_username"); mqttClient->setPassword("your_password"); 使用说明依赖库:Qt 5.15+(需包含Charts、Sql、Network模块)QtMqtt模块(官方或第三方实现)运行准备:在项目目录放置报警音效文件alarm.wav配置正确的华为云连接参数确保MQTT主题与设备端发布主题一致功能操作:通过旋钮控件设置报警阈值点击"Export CSV"导出历史数据实时曲线自动滚动显示最新100个数据点模块代码设计以下是基于STM32F103C8T6的完整传感器驱动代码(寄存器开发方式),包含MAX30100心率传感器和DHT11温湿度传感器的驱动实现:#include "stm32f10x.h" // 硬件定义 #define DHT11_GPIO_PORT GPIOB #define DHT11_GPIO_PIN GPIO_Pin_0 #define DHT11_RCC_PORT RCC_APB2Periph_GPIOB // I2C引脚定义 #define I2C_PORT GPIOB #define I2C_SCL_PIN GPIO_Pin_6 #define I2C_SDA_PIN GPIO_Pin_7 #define I2C_RCC RCC_APB2Periph_GPIOB #define I2C_SPEED 400000 // 400kHz // MAX30100寄存器地址 #define MAX30100_ADDR 0xAE // 7位地址 << 1 #define REG_INTR_STATUS_1 0x00 #define REG_INTR_ENABLE_1 0x01 #define REG_FIFO_WR_PTR 0x04 #define REG_FIFO_RD_PTR 0x06 #define REG_FIFO_DATA 0x07 #define REG_MODE_CONFIG 0x09 #define REG_SPO2_CONFIG 0x0A #define REG_LED1_PA 0x0C #define REG_LED2_PA 0x0D #define REG_TEMP_INTG 0x16 #define REG_TEMP_FRAC 0x17 // 函数声明 void SystemInit(void); void Delay_us(uint32_t us); void Delay_ms(uint32_t ms); void GPIO_Configuration(void); void USART1_Init(void); void I2C_Init(void); void I2C_Start(void); void I2C_Stop(void); uint8_t I2C_WaitAck(void); void I2C_Ack(void); void I2C_NAck(void); void I2C_SendByte(uint8_t data); uint8_t I2C_ReadByte(void); uint8_t MAX30100_ReadReg(uint8_t reg); void MAX30100_WriteReg(uint8_t reg, uint8_t value); void MAX30100_Init(void); int MAX30100_ReadFIFO(uint32_t *red, uint32_t *ir); void DHT11_Start(void); uint8_t DHT11_CheckResponse(void); uint8_t DHT11_ReadByte(void); uint8_t DHT11_ReadData(uint8_t *temp, uint8_t *humi); // 系统时钟初始化 (72MHz HSE) void SystemInit(void) { RCC->CR |= RCC_CR_HSEON; // 开启HSE while(!(RCC->CR & RCC_CR_HSERDY)); // 等待HSE就绪 FLASH->ACR |= FLASH_ACR_LATENCY_2; // Flash等待周期 RCC->CFGR |= RCC_CFGR_PLLMULL9; // PLL倍频9倍 RCC->CFGR |= RCC_CFGR_PLLSRC; // PLL源选择HSE RCC->CR |= RCC_CR_PLLON; // 开启PLL while(!(RCC->CR & RCC_CR_PLLRDY)); // 等待PLL就绪 RCC->CFGR |= RCC_CFGR_SW_PLL; // 系统时钟切换到PLL while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // 等待切换完成 SystemCoreClock = 72000000; } // 微秒级延时 void Delay_us(uint32_t us) { SysTick->LOAD = SystemCoreClock / 8000000 * us; SysTick->VAL = 0; SysTick->CTRL = SysTick_CTRL_ENABLE_Msk; while(!(SysTick->CTRL & SysTick_CTRL_COUNTFLAG_Msk)); SysTick->CTRL = 0; } // 毫秒级延时 void Delay_ms(uint32_t ms) { while(ms--) Delay_us(1000); } // GPIO初始化 void GPIO_Configuration(void) { RCC->APB2ENR |= RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB; // DHT11配置 (PB0) GPIOB->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_MODE0); GPIOB->CRL |= GPIO_CRL_MODE0; // 推挽输出模式 // USART1 TX (PA9) GPIOA->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_MODE9); GPIOA->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9; // 复用推挽输出 } // USART1初始化 (115200) void USART1_Init(void) { RCC->APB2ENR |= RCC_APB2Periph_USART1; USART1->BRR = 72000000 / 115200; // 波特率 USART1->CR1 = USART_CR1_UE | USART_CR1_TE; // 使能USART和发送 USART1->CR2 = 0; USART1->CR3 = 0; } // I2C初始化 void I2C_Init(void) { RCC->APB2ENR |= I2C_RCC; // 配置PB6(SCL), PB7(SDA)为开漏输出 GPIOB->CRL &= ~(GPIO_CRL_CNF6 | GPIO_CRL_MODE6 | GPIO_CRL_CNF7 | GPIO_CRL_MODE7); GPIOB->CRL |= GPIO_CRL_CNF6 | GPIO_CRL_MODE6 | GPIO_CRL_CNF7 | GPIO_CRL_MODE7; RCC->APB1ENR |= RCC_APB1Periph_I2C1; I2C1->CR1 = I2C_CR1_SWRST; I2C1->CR1 = 0; I2C1->CR2 = SystemCoreClock / 1000000; // 设置时钟频率 I2C1->CCR = SystemCoreClock / (2 * I2C_SPEED); // 设置CCR I2C1->TRISE = SystemCoreClock / 1000000 + 1; // 设置TRISE I2C1->CR1 |= I2C_CR1_PE; // 使能I2C } // I2C起始信号 void I2C_Start(void) { I2C1->CR1 |= I2C_CR1_START; while(!(I2C1->SR1 & I2C_SR1_SB)); } // I2C停止信号 void I2C_Stop(void) { I2C1->CR1 |= I2C_CR1_STOP; while(I2C1->CR1 & I2C_CR1_STOP); } // 等待ACK uint8_t I2C_WaitAck(void) { if(I2C1->SR1 & I2C_SR1_AF) { I2C1->SR1 &= ~I2C_SR1_AF; return 1; // NACK } return 0; // ACK } // 发送ACK void I2C_Ack(void) { I2C1->CR1 &= ~I2C_CR1_ACK; } // 发送NACK void I2C_NAck(void) { I2C1->CR1 |= I2C_CR1_ACK; } // I2C发送一个字节 void I2C_SendByte(uint8_t data) { I2C1->DR = data; while(!(I2C1->SR1 & I2C_SR1_TXE)); } // I2C读取一个字节 uint8_t I2C_ReadByte(void) { while(!(I2C1->SR1 & I2C_SR1_RXNE)); return I2C1->DR; } // MAX30100读取寄存器 uint8_t MAX30100_ReadReg(uint8_t reg) { uint8_t value; I2C_Start(); I2C_SendByte(MAX30100_ADDR); I2C_WaitAck(); I2C_SendByte(reg); I2C_WaitAck(); I2C_Start(); I2C_SendByte(MAX30100_ADDR | 0x01); I2C_WaitAck(); value = I2C_ReadByte(); I2C_NAck(); I2C_Stop(); return value; } // MAX30100写入寄存器 void MAX30100_WriteReg(uint8_t reg, uint8_t value) { I2C_Start(); I2C_SendByte(MAX30100_ADDR); I2C_WaitAck(); I2C_SendByte(reg); I2C_WaitAck(); I2C_SendByte(value); I2C_WaitAck(); I2C_Stop(); } // MAX30100初始化 void MAX30100_Init(void) { MAX30100_WriteReg(REG_MODE_CONFIG, 0x03); // HR模式 MAX30100_WriteReg(REG_SPO2_CONFIG, 0x27); // 100Hz, 16位分辨率 MAX30100_WriteReg(REG_LED1_PA, 0x24); // LED1电流=36mA MAX30100_WriteReg(REG_LED2_PA, 0x24); // LED2电流=36mA MAX30100_WriteReg(REG_FIFO_WR_PTR, 0x00); // 重置FIFO MAX30100_WriteReg(REG_FIFO_RD_PTR, 0x00); } // 从FIFO读取数据 int MAX30100_ReadFIFO(uint32_t *red, uint32_t *ir) { uint8_t buffer[6]; uint8_t i; if(MAX30100_ReadReg(REG_FIFO_WR_PTR) == MAX30100_ReadReg(REG_FIFO_RD_PTR)) return 0; // FIFO空 I2C_Start(); I2C_SendByte(MAX30100_ADDR); I2C_WaitAck(); I2C_SendByte(REG_FIFO_DATA); I2C_WaitAck(); I2C_Start(); I2C_SendByte(MAX30100_ADDR | 0x01); I2C_WaitAck(); for(i=0; i<5; i++) { buffer[i] = I2C_ReadByte(); I2C_Ack(); } buffer[5] = I2C_ReadByte(); I2C_NAck(); I2C_Stop(); *red = (buffer[0] << 16) | (buffer[1] << 8) | buffer[2]; *ir = (buffer[3] << 16) | (buffer[4] << 8) | buffer[5]; return 1; } // DHT11启动信号 void DHT11_Start(void) { GPIOB->CRL &= ~GPIO_CRL_MODE0; // 输出模式 GPIOB->BRR = DHT11_GPIO_PIN; // 拉低 Delay_ms(18); // 保持18ms GPIOB->BSRR = DHT11_GPIO_PIN; // 释放总线 GPIOB->CRL |= GPIO_CRL_CNF0_0; // 输入模式(浮空) Delay_us(30); } // 检测DHT11响应 uint8_t DHT11_CheckResponse(void) { uint8_t retry = 0; while(GPIOB->IDR & DHT11_GPIO_PIN) { if(retry++ > 100) return 0; Delay_us(1); } retry = 0; while(!(GPIOB->IDR & DHT11_GPIO_PIN)) { if(retry++ > 100) return 0; Delay_us(1); } retry = 0; while(GPIOB->IDR & DHT11_GPIO_PIN) { if(retry++ > 100) return 0; Delay_us(1); } return 1; } // DHT11读取一个字节 uint8_t DHT11_ReadByte(void) { uint8_t data = 0; for(int i=0; i<8; i++) { while(!(GPIOB->IDR & DHT11_GPIO_PIN)); // 等待低电平结束 Delay_us(40); if(GPIOB->IDR & DHT11_GPIO_PIN) data |= (1 << (7-i)); while(GPIOB->IDR & DHT11_GPIO_PIN); // 等待高电平结束 } return data; } // DHT11读取数据 uint8_t DHT11_ReadData(uint8_t *temp, uint8_t *humi) { uint8_t buf[5]; DHT11_Start(); if(!DHT11_CheckResponse()) return 0; for(int i=0; i<5; i++) buf[i] = DHT11_ReadByte(); if(buf[4] != (buf[0]+buf[1]+buf[2]+buf[3])) return 0; // 校验失败 *humi = buf[0]; *temp = buf[2]; return 1; } // 主函数 int main(void) { uint8_t temperature, humidity; uint32_t heart_rate, spo2; char uart_buf[64]; SystemInit(); GPIO_Configuration(); USART1_Init(); I2C_Init(); MAX30100_Init(); while(1) { // 读取DHT11数据 if(DHT11_ReadData(&temperature, &humidity)) { sprintf(uart_buf, "TEMP:%dC,HUMI:%d%%\r\n", temperature, humidity); for(char *p = uart_buf; *p; p++) { while(!(USART1->SR & USART_SR_TXE)); USART1->DR = *p; } } // 读取MAX30100数据 if(MAX30100_ReadFIFO(&spo2, &heart_rate)) { sprintf(uart_buf, "HR:%lu,SpO2:%lu\r\n", heart_rate, spo2); for(char *p = uart_buf; *p; p++) { while(!(USART1->SR & USART_SR_TXE)); USART1->DR = *p; } } Delay_ms(1000); // 每秒采集一次 } } 代码说明:系统初始化配置72MHz系统时钟(HSE外部晶振)实现精确延时函数(us/ms级)I2C驱动完全寄存器方式实现I2C协议支持400kHz高速模式包含起始/停止/ACK/NACK等基本操作MAX30100驱动初始化配置为心率监测模式实现寄存器读写函数FIFO数据读取功能支持红光(red)和红外(ir)双通道数据采集DHT11驱动单总线协议实现严格的时序控制(us级延时)数据校验机制同时获取温度和湿度数据USART通信配置115200波特率通过PA9(TX)发送传感器数据到ESP8266使用说明:硬件连接:MAX30100: SCL→PB6, SDA→PB7DHT11: DATA→PB0ESP8266: TX→PA10(RX), RX→PA9(TX)数据格式:温度/湿度: “TEMP:25C,HUMI:45%”心率/血氧: “HR:75,SpO2:98”工作流程:系统每1秒采集一次传感器数据通过串口发送给ESP8266模块ESP8266通过MQTT协议转发至华为云项目核心代码以下是基于STM32F103C8T6的智能健康监测系统main.c完整代码(寄存器开发方式):#include "stm32f10x.h" // 传感器数据结构 typedef struct { uint16_t heart_rate; float temperature; } SensorData; // 函数声明 void SystemClock_Config(void); void GPIO_Config(void); void USART1_Init(void); void USART2_Init(void); void I2C1_Init(void); void DHT11_Init(void); void SysTick_Init(void); void Delay_us(uint32_t us); void Delay_ms(uint32_t ms); uint8_t MAX30100_ReadHeartRate(uint16_t *hr); uint8_t DHT11_ReadTemp(float *temp); void ESP8266_SendCommand(char *cmd, char *ack, uint32_t timeout); void MQTT_PublishData(SensorData data); int main(void) { // 系统初始化 SystemClock_Config(); GPIO_Config(); USART1_Init(); // 调试串口 USART2_Init(); // ESP8266通信 I2C1_Init(); // MAX30100 DHT11_Init(); // DHT11 SysTick_Init(); // 发送AT指令初始化ESP8266 ESP8266_SendCommand("AT\r\n", "OK", 1000); ESP8266_SendCommand("AT+CWMODE=1\r\n", "OK", 1000); ESP8266_SendCommand("AT+CWJAP=\"YourSSID\",\"YourPassword\"\r\n", "GOT IP", 5000); ESP8266_SendCommand("AT+MQTTUSERCFG=0,1,\"DeviceID\",\"Username\",\"Password\",0,0,\"\"\r\n", "OK", 1000); ESP8266_SendCommand("AT+MQTTCONN=0,\"YourHuaweiCloudAddress\",1883,1\r\n", "OK", 5000); SensorData sensor_data; uint32_t last_send = 0; while (1) { // 每2秒采集并发送数据 if (HAL_GetTick() - last_send >= 2000) { // 读取心率传感器 if (MAX30100_ReadHeartRate(&sensor_data.heart_rate) == 0) { // 串口调试输出 USART_SendData(USART1, 'H'); USART_SendData(USART1, ':'); USART_SendData(USART1, (sensor_data.heart_rate/100) + '0'); USART_SendData(USART1, (sensor_data.heart_rate%100/10) + '0'); USART_SendData(USART1, (sensor_data.heart_rate%10) + '0'); USART_SendData(USART1, '\n'); } // 读取温度传感器 if (DHT11_ReadTemp(&sensor_data.temperature) == 0) { USART_SendData(USART1, 'T'); USART_SendData(USART1, ':'); int temp_int = (int)sensor_data.temperature; USART_SendData(USART1, temp_int/10 + '0'); USART_SendData(USART1, temp_int%10 + '0'); USART_SendData(USART1, '.'); int temp_dec = (int)(sensor_data.temperature*10)%10; USART_SendData(USART1, temp_dec + '0'); USART_SendData(USART1, '\n'); } // 通过MQTT上传到华为云 MQTT_PublishData(sensor_data); last_send = HAL_GetTick(); } } } // MQTT数据发布函数 void MQTT_PublishData(SensorData data) { char mqtt_msg[50]; sprintf(mqtt_msg, "{\"heart_rate\":%d,\"temperature\":%.1f}", data.heart_rate, data.temperature); char mqtt_cmd[100]; sprintf(mqtt_cmd, "AT+MQTTPUB=0,\"Your/Topic\",\"%s\",1,0\r\n", mqtt_msg); ESP8266_SendCommand(mqtt_cmd, "OK", 1000); } // ESP8266命令发送函数 void ESP8266_SendCommand(char *cmd, char *ack, uint32_t timeout) { // 发送命令 while (*cmd) { USART_SendData(USART2, *cmd++); while (!(USART2->SR & USART_SR_TC)); } // 等待响应(简化实现) Delay_ms(timeout); } // 系统时钟配置(72MHz HSE) void SystemClock_Config(void) { RCC->CR |= RCC_CR_HSEON; // 开启HSE while (!(RCC->CR & RCC_CR_HSERDY)); // 等待HSE就绪 // 配置PLL:HSE * 9 = 72MHz RCC->CFGR |= RCC_CFGR_PLLMULL9 | RCC_CFGR_PLLSRC; RCC->CR |= RCC_CR_PLLON; // 开启PLL while (!(RCC->CR & RCC_CR_PLLRDY)); // 等待PLL就绪 // 配置FLASH预取指 FLASH->ACR |= FLASH_ACR_PRFTBE | FLASH_ACR_LATENCY_1; // 切换系统时钟 RCC->CFGR |= RCC_CFGR_SW_PLL; while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // 等待切换完成 } // USART1初始化(调试串口,115200bps) void USART1_Init(void) { RCC->APB2ENR |= RCC_APB2ENR_USART1EN | RCC_APB2ENR_IOPAEN; // PA9(TX)复用推挽输出,PA10(RX)浮空输入 GPIOA->CRH &= ~(GPIO_CRH_CNF9 | GPIO_CRH_MODE9); GPIOA->CRH |= GPIO_CRH_CNF9_1 | GPIO_CRH_MODE9; GPIOA->CRH &= ~(GPIO_CRH_CNF10 | GPIO_CRH_MODE10); GPIOA->CRH |= GPIO_CRH_CNF10_0; // 波特率设置:72MHz/(16*39.0625)=115200 USART1->BRR = 0x0271; USART1->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; } // USART2初始化(ESP8266通信,115200bps) void USART2_Init(void) { RCC->APB1ENR |= RCC_APB1ENR_USART2EN; RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; // PA2(TX)复用推挽输出,PA3(RX)浮空输入 GPIOA->CRL &= ~(GPIO_CRL_CNF2 | GPIO_CRL_MODE2); GPIOA->CRL |= GPIO_CRL_CNF2_1 | GPIO_CRL_MODE2; GPIOA->CRL &= ~(GPIO_CRL_CNF3 | GPIO_CRL_MODE3); GPIOA->CRL |= GPIO_CRL_CNF3_0; // 波特率设置 USART2->BRR = 0x0271; USART2->CR1 = USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; } // I2C1初始化(MAX30100) void I2C1_Init(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; // PB6(SCL)/PB7(SDA) 复用开漏输出 GPIOB->CRL &= ~(GPIO_CRL_CNF6 | GPIO_CRL_MODE6 | GPIO_CRL_CNF7 | GPIO_CRL_MODE7); GPIOB->CRL |= GPIO_CRL_CNF6_1 | GPIO_CRL_MODE6 | GPIO_CRL_CNF7_1 | GPIO_CRL_MODE7; // I2C配置 I2C1->CR2 = 36; // APB1时钟36MHz I2C1->CCR = 180; // 100kHz标准模式 I2C1->TRISE = 37; // 最大上升时间 I2C1->CR1 = I2C_CR1_PE; // 使能I2C } // DHT11初始化(PA0) void DHT11_Init(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; GPIOA->CRL &= ~GPIO_CRL_MODE0; // 初始化为输出模式 GPIOA->BSRR = GPIO_BSRR_BS0; // 输出高电平 } // SysTick初始化(1ms中断) void SysTick_Init(void) { SysTick->LOAD = 72000 - 1; // 72MHz/1000 = 72kHz SysTick->VAL = 0; SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk; } // 微秒级延时 void Delay_us(uint32_t us) { uint32_t start = SysTick->VAL; uint32_t ticks = us * 72; // 72MHz时钟 while ((start - SysTick->VAL) < ticks); } // 毫秒级延时 void Delay_ms(uint32_t ms) { while (ms--) { Delay_us(1000); } } // GPIO配置 void GPIO_Config(void) { // 启用GPIO时钟 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN; // LED指示灯(PC13) GPIOC->CRH &= ~GPIO_CRH_CNF13; GPIOC->CRH |= GPIO_CRH_MODE13; GPIOC->BSRR = GPIO_BSRR_BS13; // 初始关闭 } 关键代码说明:系统初始化:配置72MHz系统时钟(HSE+PLL)初始化调试串口(USART1)和ESP8266通信串口(USART2)配置I2C接口用于MAX30100心率传感器配置GPIO用于DHT11温湿度传感器传感器驱动:MAX30100_ReadHeartRate() 通过I2C读取心率数据DHT11_ReadTemp() 通过单总线协议读取温度网络通信:ESP8266_SendCommand() 发送AT指令配置WiFi和MQTTMQTT_PublishData() 封装JSON格式数据发布到华为云数据处理:每2秒采集一次传感器数据通过串口输出调试信息数据格式:{"heart_rate":75,"temperature":36.5}华为云对接:使用标准MQTT协议发布数据需替换实际参数:YourSSID/YourPassword:WiFi凭证YourHuaweiCloudAddress:华为云IoT地址DeviceID/Username/Password:华为云设备认证信息Your/Topic:华为云数据上报主题总结本设计成功构建了一套完整的智能人体健康监测系统。该系统以STM32F103C8T6微控制器为核心,高效整合了MAX30100心率血氧传感器和DHT11温湿度传感器,通过I2C和单总线协议精确采集用户的心率与体温数据,为健康监测提供了可靠的数据来源。系统借助ESP8266-01S WiFi模块,利用UART串口通信和MQTT协议,实现了传感器数据的稳定、实时无线传输。数据被安全、高效地上传至华为云物联网平台,该平台承担了数据的接收、存储、处理及长期管理的核心任务,并支持关键数据的导出功能,为健康数据分析提供了坚实基础。上位机软件基于QT框架开发,通过集成Paho MQTT客户端库与华为云建立连接,实现了数据的实时接收与解析。软件界面友好,功能丰富,不仅动态展示实时数据曲线,还提供了历史数据查询、心率与体温安全阈值设定等功能,并在数据异常时触发显著的声光报警,有效提升了系统的预警能力与用户交互体验。综上所述,该毕业设计实现了从终端数据采集、云端传输存储到上位机可视化监控与预警的全流程闭环。系统结构清晰,功能完备,具备良好的实用性和扩展性,为远程健康监护提供了一套可行的技术方案,具有实际应用价值。
-
项目开发背景现代家庭和办公场所中,观赏鱼缸因其美化环境、舒缓压力的作用而日益普及。然而,维持鱼缸内生态系统的健康平衡是一项需要持续关注和专业知识的任务。传统的人工管理方式存在诸多不便:饲养者需频繁手动检测水温、水位等关键参数,难以实现精准控制;光照调节依赖主观判断且易被遗忘,影响水草生长和鱼类生物钟;水位过低风险若未能及时发现,可能导致昂贵的设备损坏甚至危及鱼类生命。这些痛点不仅耗费用户大量精力,也对鱼缸生态的稳定性构成挑战。随着物联网技术和嵌入式系统的快速发展,为鱼缸管理的智能化升级提供了坚实基础。基于高性能、低功耗的STM32微控制器核心,结合高精度数字温度传感器、可靠的模拟液位检测模块以及先进的光强度采集芯片,构建一套实时、自动化的监控系统在技术上已完全可行。该系统不仅能持续获取鱼缸环境的核心数据,更能通过执行机构(如继电器控制的灯光和水泵)自动响应环境变化,大幅减轻用户负担,同时显著提升鱼类生存环境的可靠性与舒适度。该项目的核心价值在于将鱼缸管理无缝融入智慧家居生态。通过集成Wi-Fi通信模块(如ESP8266)并利用MQTT协议对接华为云物联网平台,系统实现了环境数据的远程可视化与历史追溯。用户无论身处何地,都能通过定制的Qt上位机软件或便捷的Android移动应用,实时查看鱼缸状态(水温、水位、光照),并在必要时远程干预(如手动开关灯光、水泵)。OLED显示屏则提供本地的即时信息反馈。这种“本地自动化+云端互联+移动控制”的三位一体设计,不仅解决了传统鱼缸管理的核心痛点,更契合了现代用户对智能、便捷、互联生活的追求,是智能家居理念在细分场景下的成功落地实践。设计实现的功能(1)实时监测水温:使用DS18B20传感器采集水温数据(2)实时监测水位:通过模拟输出型液位传感器检测水位高度(3)实时监测光照强度:通过BH1750传感器(I2C接口)获取光照数据(4)自动补光控制:根据光照强度阈值,用继电器控制LED补光灯(5)定时水泵控制:通过继电器定时启停循环水泵(6)水位过低报警:当水位低于阈值时,触发有源蜂鸣器报警(7)参数显示:在0.96寸SPI OLED上实时显示水温、水位、光照强度等数据(8)华为云数据上传:通过ESP8266模块(MQTT协议)上传传感器数据至华为云物联网平台(9)远程控制支持:支持通过Qt上位机软件和Android APP远程查看数据及控制设备(10)系统供电:采用DC 5V电源输入,经AMS1117稳压芯片提供系统所需电压项目硬件模块组成(1)主控芯片:STM32F103C8T6(2)水温传感器:DS18B20(3)水位传感器:模拟输出型液位传感器(电阻式)(4)光照传感器:BH1750(I2C)(5)显示模块:0.96寸SPI OLED(6)执行模块:继电器(控制补光LED灯和循环水泵)(7)报警模块:有源蜂鸣器(8)联网模块:ESP8266(通过MQTT连接华为云)(9)供电模块:DC 5V电源+AMS1117稳压芯片设计意义该智能鱼缸监控与控制系统设计具有显著的实际意义。首先,它实现了鱼缸环境关键参数的自动化监测与管理。通过实时采集水温、水位和光照强度数据,并自动控制补光LED、定时启停循环水泵,以及在低水位时触发蜂鸣器报警,系统显著降低了人工维护的频率和复杂度。这种自动化管理不仅提升了鱼缸运行的稳定性,更有效保障了水生生物生存环境的适宜性,减少了因人为疏忽导致环境突变的风险。其次,系统提供了便捷的本地与远程监控能力。OLED显示屏直观地本地化展示所有环境参数,使用户能够快速了解鱼缸状态。更重要的是,通过ESP8266模块连接华为云物联网平台,系统实现了数据的远程上传。用户能够借助Qt上位机软件或Android APP,随时随地查看鱼缸实时数据(如水温、水位、光照)和历史记录,并在必要时进行远程控制操作(如手动开关灯、水泵)。这极大地提升了用户的管理自由度与及时响应能力,特别适合用户外出时的场景。再者,该系统积累了宝贵的环境运行数据。持续上传至云端的水温、水位、光照等参数,形成了鱼缸环境的长期运行记录。这些数据对于用户分析水质变化趋势、评估设备运行效果、优化饲养策略(如投喂、换水周期)提供了客观依据,有助于实现更科学、精细化的观赏鱼养护。最后,该设计是嵌入式系统与物联网技术在实际生活场景中的典型应用示范。它综合运用了STM32微控制器进行数据采集、逻辑控制与设备驱动,结合了多种传感器技术、执行器控制、人机交互(OLED)以及基于ESP8266和MQTT协议的云平台接入,完整展示了从感知层到网络层再到应用层的物联网架构实现。这种技术集成方案为解决类似的农业养殖、环境监控等场景需求提供了可借鉴的工程实践案例。设计思路设计思路:系统以STM32F103C8T6为主控核心,通过多传感器协同实现鱼缸环境监控。DS18B20温度传感器采用单总线协议实时采集水温数据;模拟液位传感器通过ADC通道获取水位电压信号,经STM32内部ADC转换为数字量并计算水位高度;BH1750光照传感器通过I2C接口传输环境光强度数据。所有采集数据通过SPI接口驱动0.96寸OLED进行实时显示。控制逻辑设计包含三重机制:首先,光照强度低于阈值时通过GPIO控制继电器自动开启补光LED;其次,利用STM32定时器模块实现水泵的定时启停控制;最后,当检测到水位低于安全值时,立即触发有源蜂鸣器报警模块。网络通信层通过串口连接ESP8266模块,基于AT指令集建立Wi-Fi连接,采用MQTT协议接入华为云物联网平台。STM32将传感器数据封装为JSON格式上传至云端,同时订阅云平台下发的控制指令(如手动开关灯/水泵),实现双向通信。远程控制端通过Qt上位机软件和Android APP解析云端数据并发送控制指令。供电系统采用DC 5V外部电源输入,经AMS1117稳压芯片转换为3.3V,为STM32及低功耗外设提供稳定电压。主程序采用轮询方式采集传感器数据,结合中断机制处理紧急报警事件,确保系统实时响应能力。框架图系统框架图+-----------------------------------------------------------------------+ | 智能鱼缸监控与控制系统 | | 基于STM32F103C8T6 | +-----------------------------------------------------------------------+ | | | +----------------+ +----------------+ +----------------+ | | | 传感器模块 | | 主控芯片 | | 执行/报警模块 | | | | - DS18B20 |<---->| STM32F103C8T6 |<---->| - 继电器(LED) | | | | (水温) | 1-Wire| | GPIO | - 继电器(水泵) | | | | - 液位传感器 |<---->| +------------+ |<---->| - 蜂鸣器 | | | | (水位) | ADC | | 控制逻辑 | | I2C +----------------+ | | | - BH1750 |<---->| | - 自动补光 | | | | | (光照) | I2C | | - 水泵定时 | |<---->+----------------+ | | +----------------+ | | - 水位报警 | | UART | 通信模块 | | | | +------------+ |<---->| - ESP8266 | | | | |<---->| (WiFi) | | | | +------------+ | SPI | MQTT协议 | | | | | 显示驱动 | |<---->| 华为云连接 | | | | +------------+ | +----------------+ | | +----------------+ | | | | UPLOAD | | v | | +----------------+ +----------------+ | | | 显示模块 |<----------------------------| 华为云物联网平台 | | | | - SPI OLED | SPI | (数据存储与分析)| | | | (实时参数显示)| +----------------+ | | +----------------+ | API | | | | | +----------------+ +----------------+ | | | | 供电模块 | | 远程控制端 |<-----------| | | | - DC 5V电源 |------| - Qt上位机 | | | | | - AMS1117稳压 | 3.3V | - Android APP |<-----------| | | +----------------+ +----------------+ 远程指令 +-------------+ | +-----------------------------------------------------------------------+ 框架说明:传感器模块DS18B20(1-Wire协议)→ 水温监测模拟液位传感器(ADC采集)→ 水位监测BH1750(I2C协议)→ 光照强度监测主控芯片STM32F103C8T6 实现:控制逻辑(自动补光/水泵定时/水位报警)显示驱动(SPI OLED)外设通信管理执行/报警模块继电器控制补光LED和水泵蜂鸣器触发水位过低报警通信模块ESP8266通过UART与STM32通信MQTT协议上传数据至华为云物联网平台远程控制Qt上位机与Android APP通过华为云API:查看实时数据远程控制继电器(LED/水泵)显示模块SPI接口OLED显示所有参数(水温/水位/光照/设备状态)供电模块DC 5V输入 → AMS1117稳压至3.3V → 为全系统供电系统总体设计系统总体设计以STM32F103C8T6微控制器为核心,集成多类传感器与执行模块,实现鱼缸环境的智能监控与控制。水温监测通过单总线通信的DS18B20传感器完成,其数字信号直接传输至STM32,确保温度数据的实时性和准确性。水位检测采用模拟输出型液位传感器,传感器输出的电压信号经STM32内置ADC转换为数字量,通过预设阈值判断水位状态,触发后续控制逻辑。光照强度采集由I2C接口的BH1750传感器实现,可动态感知环境光变化。本地控制与显示部分通过SPI接口的0.96寸OLED实时展示水温、水位、光照强度及设备运行状态。系统设置两级自动控制策略:光照强度低于阈值时,STM32驱动继电器开启补光LED;基于内部定时器控制水泵的周期性启停,由继电器执行开关动作。安全防护方面,水位过低时STM32触发有源蜂鸣器报警,实现本地声学警示。云平台交互由ESP8266 WiFi模块完成,STM32通过UART发送AT指令配置ESP8266连接网络,并基于MQTT协议与华为云物联网平台建立双向通信。传感器数据按预设间隔封装为JSON格式上传至云端,同时云端下发的控制指令(如手动启停水泵/补光灯)经解析后由STM32执行。远程监控通过Qt开发的上位机软件和Android APP实现,用户可实时查看鱼缸参数并远程干预设备状态。供电系统采用DC 5V外部电源输入,通过AMS1117-3.3V稳压芯片转换后为STM32、传感器及低功耗模块提供稳定电源,继电器控制的水泵和补光灯则直接由5V电源驱动,确保大功率负载与核心电路隔离。系统功能总结功能模块实现方式实时监测使用DS18B20采集水温,模拟液位传感器检测水位,BH1750测量光照强度自动补光根据光照强度阈值,通过继电器控制补光LED开关定时水泵内置定时器控制继电器定时启/停循环水泵水位报警水位低于阈值时触发有源蜂鸣器持续报警参数显示0.96寸SPI OLED实时显示水温、水位、光照强度及设备状态云端数据上传ESP8266通过MQTT协议将传感器数据上传至华为云物联网平台远程控制支持Qt上位机/Android APP远程控制补光、水泵开关及报警阈值设置供电管理DC 5V电源输入,经AMS1117稳压芯片输出3.3V稳定电压供系统运行设计的各个功能模块描述基于STM32F103C8T6的智能鱼缸监控与控制系统包含以下功能模块:主控芯片STM32F103C8T6作为系统核心,协调所有模块的数据采集、逻辑处理和执行控制。通过其丰富的外设接口(如ADC、I2C、SPI、UART等)连接各类传感器和执行器,实现实时数据处理和任务调度。水温监测模块采用DS18B20数字温度传感器,通过单总线协议与主控芯片通信。该传感器直接浸入鱼缸水体中,实时采集水温数据并转换为数字信号传输至STM32,精度可达±0.5℃,确保温度监控的可靠性。水位监测使用模拟输出型液位传感器,通过电阻变化检测水位高度。传感器输出模拟电压信号接入STM32的ADC通道,经模数转换和校准算法处理,实时计算实际水位值。当水位低于预设阈值时触发报警机制。光照强度监测由BH1750传感器实现,通过I2C接口与主控芯片交互。该传感器以勒克斯(Lux)为单位精确测量环境光照强度,支持自动量程切换,数据用于触发补光系统的自动控制逻辑。OLED显示模块采用0.96寸SPI接口屏幕,实时展示水温、水位、光照强度等关键参数及设备状态(如水泵/补光灯开关状态)。屏幕刷新率可调,低功耗设计确保长时间稳定运行。执行控制模块包含两个继电器组,分别驱动补光LED灯和水泵。继电器由STM32的GPIO引脚通过驱动电路控制,实现弱电信号对强电设备的隔离操作。系统支持光照不足时自动开启补光灯,并按预设时间表启停水泵。报警模块集成有源蜂鸣器,直接由STM32的GPIO引脚驱动。当水位传感器检测到液位低于安全阈值时,主控芯片立即触发蜂鸣器发出高分贝警报,直至水位恢复正常或人工干预。联网通信基于ESP8266 Wi-Fi模块,通过UART串口与STM32交互。模块运行AT指令集建立MQTT连接,将传感器数据实时上传至华为云物联网平台,同时接收云端下发的控制指令(如远程启停设备)。数据加密传输确保通信安全。远程控制终端包含Qt开发的PC端上位机和Android移动应用,通过华为云平台API获取设备实时数据并发送控制命令。用户可远程查看鱼缸状态,手动调节补光灯/水泵开关,实现跨平台监控。供电模块采用外部5V DC电源输入,经AMS1117-3.3稳压芯片转换为稳定的3.3V电压,为STM32微控制器及所有外设模块提供纯净电源。过流保护设计保障系统长时间安全运行。上位机代码设计以下是一个基于Qt的智能鱼缸监控系统上位机完整代码设计,采用MQTT协议连接华为云物联网平台:#include <QMainWindow> #include <QtMqtt/QMqttClient> #include <QChart> #include <QChartView> #include <QLineSeries> #include <QDateTimeAxis> #include <QValueAxis> QT_CHARTS_USE_NAMESPACE namespace Ui { class MainWindow; } class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = nullptr); ~MainWindow(); private slots: void connectToBroker(); void disconnectFromBroker(); void onConnected(); void messageReceived(const QByteArray &message, const QMqttTopicName &topic); void controlLight(bool state); void controlPump(bool state); void updateChart(double value, QString parameter); private: Ui::MainWindow *ui; QMqttClient *m_client; QChart *tempChart; QLineSeries *tempSeries; QChartView *chartView; QDateTimeAxis *axisX; QValueAxis *axisY; }; #include "mainwindow.h" #include "ui_mainwindow.h" MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); // 初始化MQTT客户端 m_client = new QMqttClient(this); m_client->setHostname("your_huaweicloud_address.com"); // 替换为华为云地址 m_client->setPort(1883); m_client->setUsername("device_id"); // 替换设备ID m_client->setPassword("device_secret"); // 替换设备密钥 // 连接信号槽 connect(m_client, &QMqttClient::connected, this, &MainWindow::onConnected); connect(ui->btnConnect, &QPushButton::clicked, this, &MainWindow::connectToBroker); connect(ui->btnDisconnect, &QPushButton::clicked, this, &MainWindow::disconnectFromBroker); connect(ui->btnLight, &QPushButton::toggled, this, &MainWindow::controlLight); connect(ui->btnPump, &QPushButton::toggled, this, &MainWindow::controlPump); // 初始化图表 tempChart = new QChart(); tempSeries = new QLineSeries(); tempChart->addSeries(tempSeries); axisX = new QDateTimeAxis; axisX->setFormat("hh:mm:ss"); axisX->setTitleText("时间"); tempChart->addAxis(axisX, Qt::AlignBottom); tempSeries->attachAxis(axisX); axisY = new QValueAxis; axisY->setRange(0, 40); axisY->setTitleText("温度(℃)"); tempChart->addAxis(axisY, Qt::AlignLeft); tempSeries->attachAxis(axisY); chartView = new QChartView(tempChart); ui->chartLayout->addWidget(chartView); } MainWindow::~MainWindow() { delete ui; } void MainWindow::connectToBroker() { if (m_client->state() == QMqttClient::Disconnected) { m_client->connectToHost(); } } void MainWindow::disconnectFromBroker() { if (m_client->state() == QMqttClient::Connected) { m_client->disconnectFromHost(); } } void MainWindow::onConnected() { // 订阅数据主题 m_client->subscribe("fish_tank/data"); connect(m_client, &QMqttClient::messageReceived, this, &MainWindow::messageReceived); } void MainWindow::messageReceived(const QByteArray &message, const QMqttTopicName &topic) { // 解析JSON数据 QJsonDocument doc = QJsonDocument::fromJson(message); QJsonObject obj = doc.object(); double temp = obj["temperature"].toDouble(); int level = obj["water_level"].toInt(); int light = obj["light_intensity"].toInt(); // 更新UI ui->lblTemp->setText(QString::number(temp) + " ℃"); ui->lblLevel->setText(QString::number(level) + " %"); ui->lblLight->setText(QString::number(light) + " lux"); // 更新图表 updateChart(temp, "temperature"); // 水位报警 if(level < 30) { ui->statusBar->showMessage("警告:水位过低!", 5000); } } void MainWindow::updateChart(double value, QString parameter) { if(parameter == "temperature") { QDateTime now = QDateTime::currentDateTime(); tempSeries->append(now.toMSecsSinceEpoch(), value); // 保持最近60个数据点 if(tempSeries->count() > 60) { tempSeries->removePoints(0, tempSeries->count() - 60); } axisX->setRange(now.addSecs(-60), now); } } void MainWindow::controlLight(bool state) { QJsonObject json; json["light"] = state; QJsonDocument doc(json); m_client->publish("fish_tank/control/light", doc.toJson()); } void MainWindow::controlPump(bool state) { QJsonObject json; json["pump"] = state; QJsonDocument doc(json); m_client->publish("fish_tank/control/pump", doc.toJson()); } 配套UI文件 (mainwindow.ui):<?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> <class>MainWindow</class> <widget class="QMainWindow" name="MainWindow"> <property name="geometry"> <rect> <x>0</x> <y>0</y> <width>800</width> <height>600</height> </rect> </property> <widget class="QWidget" name="centralWidget"> <layout class="QVBoxLayout" name="verticalLayout"> <item> <layout class="QHBoxLayout" name="controlLayout"> <item> <widget class="QPushButton" name="btnConnect"> <property name="text"> <string>连接云平台</string> </property> </widget> </item> <item> <widget class="QPushButton" name="btnDisconnect"> <property name="text"> <string>断开连接</string> </property> </widget> </item> <item> <widget class="QPushButton" name="btnLight"> <property name="checkable"> <bool>true</bool> </property> <property name="text"> <string>补光灯</string> </property> </widget> </item> <item> <widget class="QPushButton" name="btnPump"> <property name="checkable"> <bool>true</bool> </property> <property name="text"> <string>循环水泵</string> </property> </widget> </item> </layout> </item> <item> <layout class="QGridLayout" name="dataLayout"> <item row="0" column="0"> <widget class="QLabel" name="label"> <property name="text"> <string>水温:</string> </property> </widget> </item> <item row="0" column="1"> <widget class="QLabel" name="lblTemp"> <property name="text"> <string>0 ℃</string> </property> </widget> </item> <item row="1" column="0"> <widget class="QLabel" name="label_2"> <property name="text"> <string>水位:</string> </property> </widget> </item> <item row="1" column="1"> <widget class="QLabel" name="lblLevel"> <property name="text"> <string>0 %</string> </property> </widget> </item> <item row="2" column="0"> <widget class="QLabel" name="label_3"> <property name="text"> <string>光照:</string> </property> </widget> </item> <item row="2" column="1"> <widget class="QLabel" name="lblLight"> <property name="text"> <string>0 lux</string> </property> </widget> </item> </layout> </item> <item> <layout class="QVBoxLayout" name="chartLayout"/> </item> </layout> </widget> <widget class="QStatusBar" name="statusBar"/> </widget> <resources/> <connections/> </ui> 项目配置文件 (fish_tank_monitor.pro):QT += core gui network mqtt charts CONFIG += c++17 TARGET = fish_tank_monitor TEMPLATE = app SOURCES += \ main.cpp \ mainwindow.cpp HEADERS += \ mainwindow.h FORMS += \ mainwindow.ui使用说明:替换代码中的华为云连接参数:your_huaweicloud_address.comdevice_iddevice_secret需要安装:Qt 5.15+QtMqtt模块QtCharts模块功能特性:实时显示水温/水位/光照数据温度数据曲线可视化远程控制补光灯和水泵水位过低报警提示MQTT协议连接华为云数据格式示例:{ "temperature": 25.6, "water_level": 75, "light_intensity": 300 } 控制命令格式:// 补光灯控制 {"light": true} // 水泵控制 {"pump": false} 这个上位机程序实现了与STM32设备的云端数据交互、实时监控和远程控制功能,界面简洁直观,操作方便。模块代码设计STM32智能鱼缸监控系统模块代码设计(寄存器开发)#include "stm32f10x.h" #include <stdio.h> // 硬件接口定义 #define DS18B20_GPIO GPIOA #define DS18B20_PIN GPIO_Pin_0 #define BUZZER_GPIO GPIOC #define BUZZER_PIN GPIO_Pin_13 #define PUMP_RELAY_GPIO GPIOB #define PUMP_RELAY_PIN GPIO_Pin_0 #define LIGHT_RELAY_GPIO GPIOB #define LIGHT_RELAY_PIN GPIO_Pin_1 // OLED SPI接口定义 #define OLED_CS_GPIO GPIOA #define OLED_CS_PIN GPIO_Pin_4 #define OLED_DC_GPIO GPIOA #define OLED_DC_PIN GPIO_Pin_5 #define OLED_RST_GPIO GPIOA #define OLED_RST_PIN GPIO_Pin_6 #define OLED_SDA_GPIO GPIOA #define OLED_SDA_PIN GPIO_Pin_7 #define OLED_SCK_GPIO GPIOA #define OLED_SCK_PIN GPIO_Pin_8 // ESP8266串口定义 #define ESP8266_USART USART1 // 传感器数据结构 typedef struct { float temperature; uint16_t water_level; uint16_t light_intensity; } SensorData; // 系统时钟配置 void SystemClock_Config(void) { // 启用外部晶振 RCC->CR |= RCC_CR_HSEON; while(!(RCC->CR & RCC_CR_HSERDY)); // 配置PLL 8MHz*9=72MHz RCC->CFGR |= RCC_CFGR_PLLMULL9 | RCC_CFGR_PLLSRC; RCC->CR |= RCC_CR_PLLON; while(!(RCC->CR & RCC_CR_PLLRDY)); // 切换系统时钟到PLL RCC->CFGR |= RCC_CFGR_SW_PLL; while((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // 设置APB1分频(36MHz), APB2分频(72MHz) RCC->CFGR |= RCC_CFGR_PPRE1_DIV2 | RCC_CFGR_PPRE2_DIV1; } // GPIO初始化 void GPIO_Init(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN; // DS18B20 (PA0 输入) GPIOA->CRL &= ~(0x0F << (0*4)); GPIOA->CRL |= 0x08 << (0*4); // 浮空输入 // 继电器控制 (PB0, PB1 推挽输出) GPIOB->CRL &= ~(0xFF << (0*4)); GPIOB->CRL |= 0x33 << (0*4); // PB0, PB1 推挽输出50MHz // 蜂鸣器 (PC13 推挽输出) GPIOC->CRH &= ~(0x0F << (5*4)); GPIOC->CRH |= 0x03 << (5*4); // PC13 推挽输出50MHz // OLED SPI引脚初始化 GPIOA->CRL &= ~(0xFF << (4*4)); // PA4(CS), PA5(DC) GPIOA->CRL |= 0x33 << (4*4); // 推挽输出 GPIOA->CRH &= ~(0xFF << (0*4)); // PA6(RST), PA7(SDA), PA8(SCK) GPIOA->CRH |= 0x333 << (0*4); // 推挽输出 } // DS18B20温度传感器驱动 float DS18B20_ReadTemp(void) { // 初始化序列 GPIOA->CRL |= 0x04 << (0*4); // 配置为开漏输出 DS18B20_GPIO->ODR &= ~DS18B20_PIN; // 拉低总线 Delay_us(480); DS18B20_GPIO->ODR |= DS18B20_PIN; // 释放总线 Delay_us(60); GPIOA->CRL &= ~(0x0F << (0*4)); // 配置为输入 while(DS18B20_GPIO->IDR & DS18B20_PIN); // 等待响应 // 发送读取温度命令 DS18B20_WriteByte(0xCC); // Skip ROM DS18B20_WriteByte(0x44); // Convert T // 等待转换完成 while(!DS18B20_ReadBit()); // 读取温度值 DS18B20_WriteByte(0xCC); // Skip ROM DS18B20_WriteByte(0xBE); // Read Scratchpad uint8_t temp_l = DS18B20_ReadByte(); uint8_t temp_h = DS18B20_ReadByte(); int16_t temp = (temp_h << 8) | temp_l; return temp / 16.0f; } // BH1750光照传感器驱动(I2C) uint16_t BH1750_ReadLight(void) { // I2C初始化 I2C_InitTypeDef i2c_init; i2c_init.I2C_Mode = I2C_Mode_I2C; i2c_init.I2C_DutyCycle = I2C_DutyCycle_2; i2c_init.I2C_OwnAddress1 = 0x00; i2c_init.I2C_Ack = I2C_Ack_Enable; i2c_init.I2C_AcknowledgedAddress = I2C_AcknowledgedAddress_7bit; i2c_init.I2C_ClockSpeed = 100000; I2C_Init(I2C1, &i2c_init); I2C_Cmd(I2C1, ENABLE); // 发送测量命令 I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, 0x23, I2C_Direction_Transmitter); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_TRANSMITTER_MODE_SELECTED)); I2C_SendData(I2C1, 0x10); // 1lx分辨率模式 while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_TRANSMITTED)); // 读取数据 I2C_GenerateSTART(I2C1, ENABLE); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_MODE_SELECT)); I2C_Send7bitAddress(I2C1, 0x23, I2C_Direction_Receiver); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_RECEIVER_MODE_SELECTED)); uint8_t data_h = I2C_ReceiveData(I2C1); while(!I2C_CheckEvent(I2C1, I2C_EVENT_MASTER_BYTE_RECEIVED)); uint8_t data_l = I2C_ReceiveData(I2C1); I2C_AcknowledgeConfig(I2C1, DISABLE); I2C_GenerateSTOP(I2C1, ENABLE); return (data_h << 8) | data_l; } // 水位传感器(ADC读取) uint16_t WaterLevel_Read(void) { // ADC初始化 RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; ADC1->CR2 = ADC_CR2_ADON; Delay_ms(1); // 通道1 (PA1)配置 ADC1->SQR3 = 1; // 通道1为第一个转换 ADC1->SMPR2 = 0x07 << (1*3); // 通道1采样时间239.5周期 // 启动转换 ADC1->CR2 |= ADC_CR2_ADON; while(!(ADC1->SR & ADC_SR_EOC)); return ADC1->DR; } // OLED显示驱动 void OLED_Display(SensorData data) { OLED_WriteCmd(0xAE); // 关闭显示 // 设置显示位置 OLED_WriteCmd(0xB0); // 页地址 OLED_WriteCmd(0x00); // 列低地址 OLED_WriteCmd(0x10); // 列高地址 // 显示温度 char temp_str[16]; sprintf(temp_str, "Temp:%.1fC", data.temperature); OLED_ShowString(0, 0, temp_str); // 显示水位 char level_str[16]; sprintf(level_str, "Level:%d", data.water_level); OLED_ShowString(0, 2, level_str); // 显示光照 char light_str[16]; sprintf(light_str, "Light:%d lx", data.light_intensity); OLED_ShowString(0, 4, light_str); OLED_WriteCmd(0xAF); // 开启显示 } // ESP8266 MQTT通信 void ESP8266_SendData(SensorData data) { char mqtt_msg[128]; sprintf(mqtt_msg, "{\"temp\":%.1f,\"level\":%d,\"light\":%d}", data.temperature, data.water_level, data.light_intensity); // 发送MQTT发布命令 USART_SendString(ESP8266_USART, "AT+MQTTPUB=0,\"fish_tank/data\",\""); USART_SendString(ESP8266_USART, mqtt_msg); USART_SendString(ESP8266_USART, "\",0,0\r\n"); } // 主控制逻辑 int main(void) { SystemClock_Config(); GPIO_Init(); USART_Init(ESP8266_USART, 115200); ADC_Config(); I2C_Init(); OLED_Init(); SensorData sensor_data; uint32_t last_pump_time = 0; uint32_t last_upload_time = 0; while(1) { // 读取传感器数据 sensor_data.temperature = DS18B20_ReadTemp(); sensor_data.water_level = WaterLevel_Read(); sensor_data.light_intensity = BH1750_ReadLight(); // OLED显示 OLED_Display(sensor_data); // 水位过低报警 if(sensor_data.water_level < 100) { BUZZER_GPIO->ODR |= BUZZER_PIN; // 开启蜂鸣器 } else { BUZZER_GPIO->ODR &= ~BUZZER_PIN; // 关闭蜂鸣器 } // 自动补光控制 if(sensor_data.light_intensity < 50) { LIGHT_RELAY_GPIO->ODR |= LIGHT_RELAY_PIN; // 开启补光灯 } else { LIGHT_RELAY_GPIO->ODR &= ~LIGHT_RELAY_PIN; // 关闭补光灯 } // 定时水泵控制 (每2小时开启10分钟) if(HAL_GetTick() - last_pump_time > 7200000) { // 2小时 PUMP_RELAY_GPIO->ODR |= PUMP_RELAY_PIN; // 开启水泵 last_pump_time = HAL_GetTick(); } if(HAL_GetTick() - last_pump_time > 600000) { // 10分钟后关闭 PUMP_RELAY_GPIO->ODR &= ~PUMP_RELAY_PIN; // 关闭水泵 } // 数据上传 (每30秒) if(HAL_GetTick() - last_upload_time > 30000) { ESP8266_SendData(sensor_data); last_upload_time = HAL_GetTick(); } Delay_ms(1000); } } 关键传感器驱动补充1. DS18B20驱动核心函数void DS18B20_WriteByte(uint8_t dat) { GPIOA->CRL |= 0x04 << (0*4); // 开漏输出 for(int i=0; i<8; i++) { DS18B20_GPIO->ODR &= ~DS18B20_PIN; // 拉低总线 if(dat & 0x01) Delay_us(5); else Delay_us(60); DS18B20_GPIO->ODR |= DS18B20_PIN; // 释放总线 dat >>= 1; Delay_us(60); } } uint8_t DS18B20_ReadByte(void) { uint8_t value = 0; for(int i=0; i<8; i++) { GPIOA->CRL |= 0x04 << (0*4); // 开漏输出 DS18B20_GPIO->ODR &= ~DS18B20_PIN; // 拉低总线 Delay_us(2); DS18B20_GPIO->ODR |= DS18B20_PIN; // 释放总线 GPIOA->CRL &= ~(0x0F << (0*4)); // 输入模式 Delay_us(10); if(DS18B20_GPIO->IDR & DS18B20_PIN) value |= 0x01<<i; Delay_us(50); } return value; } 2. OLED显示核心函数void OLED_WriteCmd(uint8_t cmd) { OLED_DC_GPIO->ODR &= ~OLED_DC_PIN; // 命令模式 OLED_CS_GPIO->ODR &= ~OLED_CS_PIN; // 片选有效 SPI_WriteByte(cmd); OLED_CS_GPIO->ODR |= OLED_CS_PIN; // 取消片选 } void SPI_WriteByte(uint8_t data) { for(uint8_t i=0; i<8; i++) { OLED_SCK_GPIO->ODR &= ~OLED_SCK_PIN; // SCK低 if(data & 0x80) OLED_SDA_GPIO->ODR |= OLED_SDA_PIN; else OLED_SDA_GPIO->ODR &= ~OLED_SDA_PIN; OLED_SCK_GPIO->ODR |= OLED_SCK_PIN; // SCK高 data <<= 1; } } 3. ESP8266 MQTT初始化void ESP8266_Init(void) { USART_SendString(ESP8266_USART, "AT+RST\r\n"); Delay_ms(1000); USART_SendString(ESP8266_USART, "AT+CWMODE=1\r\n"); Delay_ms(500); USART_SendString(ESP8266_USART, "AT+CWJAP=\"SSID\",\"PASSWORD\"\r\n"); Delay_ms(3000); USART_SendString(ESP8266_USART, "AT+MQTTUSERCFG=0,1,\"device_id\",\"username\",\"password\",0,0,\"\"\r\n"); Delay_ms(500); USART_SendString(ESP8266_USART, "AT+MQTTCONN=0,\"your_endpoint.iotcloud.tencentdevices.com\",1883,1\r\n"); Delay_ms(2000); } 系统功能说明多传感器采集:同时监测水温、水位、光照强度智能控制:水位<100时触发蜂鸣器报警光照<50lux自动补光每2小时开启水泵10分钟数据显示:OLED实时显示所有参数云端通信:通过ESP8266每30秒上传数据到华为云远程控制:支持MQTT指令控制设备开关代码采用STM32寄存器级开发,包含完整的传感器驱动、控制逻辑和通信协议实现。硬件接口定义清晰,可直接匹配原理图连接。项目核心代码以下是基于STM32F103C8T6的智能鱼缸监控系统main.c完整代码(寄存器开发):#include "stm32f10x.h" #include "ds18b20.h" #include "bh1750.h" #include "oled.h" #include "esp8266.h" #include <stdio.h> // 硬件定义 #define BUZZER_GPIO GPIOC #define BUZZER_PIN GPIO_Pin_13 #define PUMP_GPIO GPIOB #define PUMP_PIN GPIO_Pin_14 #define LED_GPIO GPIOB #define LED_PIN GPIO_Pin_15 // 全局变量 float water_temp = 0.0; uint16_t water_level = 0; uint16_t light_intensity = 0; uint8_t alert_flag = 0; uint32_t system_tick = 0; // 函数声明 void RCC_Configuration(void); void GPIO_Configuration(void); void ADC1_Configuration(void); void TIM3_Configuration(void); void NVIC_Configuration(void); void SysTick_Handler(void); void TIM3_IRQHandler(void); void Sensor_Update(void); void Control_Logic(void); void OLED_Display(void); void Cloud_Upload(void); int main(void) { // 系统初始化 RCC_Configuration(); GPIO_Configuration(); ADC1_Configuration(); TIM3_Configuration(); NVIC_Configuration(); // 外设初始化 DS18B20_Init(); BH1750_Init(); OLED_Init(); ESP8266_Init(); // 系统定时器配置 SysTick_Config(SystemCoreClock / 1000); // 1ms中断 while(1) { if(system_tick % 1000 == 0) { // 1秒任务 Sensor_Update(); Control_Logic(); OLED_Display(); } if(system_tick % 30000 == 0) { // 30秒任务 Cloud_Upload(); } ESP8266_DataProcess(); // 处理云平台数据 } } // 时钟配置 void RCC_Configuration(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_ADC1EN | RCC_APB2ENR_USART1EN; RCC->APB1ENR |= RCC_APB1ENR_TIM3EN; } // GPIO配置 void GPIO_Configuration(void) { // 蜂鸣器(PC13) GPIOC->CRH &= 0xFF0FFFFF; GPIOC->CRH |= 0x00300000; // 推挽输出 // 水泵(PB14)和补光灯(PB15) GPIOB->CRH &= 0x00FFFFFF; GPIOB->CRH |= 0x33000000; // 推挽输出 // ADC水位传感器(PA0) GPIOA->CRL &= 0xFFFFFFF0; // 模拟输入 } // ADC1配置 void ADC1_Configuration(void) { ADC1->CR2 = ADC_CR2_ADON; // 开启ADC // 通道0采样时间239.5周期 ADC1->SMPR2 |= ADC_SMPR2_SMP0_0 | ADC_SMPR2_SMP0_1 | ADC_SMPR2_SMP0_2; // 单次转换模式 ADC1->CR2 |= ADC_CR2_CONT; } // TIM3定时器配置(10ms中断) void TIM3_Configuration(void) { TIM3->PSC = 7200 - 1; // 72MHz/7200 = 10kHz TIM3->ARR = 100 - 1; // 100分频 = 100Hz(10ms) TIM3->DIER |= TIM_DIER_UIE; // 允许更新中断 TIM3->CR1 |= TIM_CR1_CEN; // 启动定时器 } // 中断配置 void NVIC_Configuration(void) { NVIC_EnableIRQ(TIM3_IRQn); NVIC_SetPriority(TIM3_IRQn, 0); } // SysTick中断处理 void SysTick_Handler(void) { system_tick++; } // TIM3中断处理 void TIM3_IRQHandler(void) { if(TIM3->SR & TIM_SR_UIF) { TIM3->SR &= ~TIM_SR_UIF; // 定时任务可在此添加 } } // 传感器数据采集 void Sensor_Update(void) { // 读取水温 water_temp = DS18B20_GetTemp(); // 读取光照 light_intensity = BH1750_ReadLight(); // 读取水位(ADC) ADC1->CR2 |= ADC_CR2_ADON; while(!(ADC1->SR & ADC_SR_EOC)); water_level = ADC1->DR; } // 控制逻辑 void Control_Logic(void) { // 水位报警 if(water_level < 500) { // 阈值根据实际调整 BUZZER_GPIO->ODR &= ~BUZZER_PIN; alert_flag = 1; } else { BUZZER_GPIO->ODR |= BUZZER_PIN; alert_flag = 0; } // 自动补光 if(light_intensity < 100) { // 100lux阈值 LED_GPIO->ODR &= ~LED_PIN; } else { LED_GPIO->ODR |= LED_PIN; } // 定时水泵控制(示例:每小时开启10分钟) static uint32_t pump_timer = 0; pump_timer++; if((pump_timer % 3600) < 600) { // 3600秒周期,前600秒开启 PUMP_GPIO->ODR &= ~PUMP_PIN; } else { PUMP_GPIO->ODR |= PUMP_PIN; } } // OLED显示 void OLED_Display(void) { char buf[32]; OLED_Clear(); sprintf(buf, "Temp:%.1fC", water_temp); OLED_ShowString(0, 0, (uint8_t*)buf); sprintf(buf, "Level:%d", water_level); OLED_ShowString(0, 2, (uint8_t*)buf); sprintf(buf, "Light:%dlux", light_intensity); OLED_ShowString(0, 4, (uint8_t*)buf); OLED_ShowString(0, 6, alert_flag ? "ALERT! LOW WATER" : "NORMAL STATUS"); } // 数据上传至云平台 void Cloud_Upload(void) { char mqtt_msg[128]; snprintf(mqtt_msg, sizeof(mqtt_msg), "{\"temp\":%.1f,\"level\":%d,\"light\":%d,\"alert\":%d}", water_temp, water_level, light_intensity, alert_flag); ESP8266_MQTTPublish("fish_tank/data", mqtt_msg); } 代码说明:硬件抽象:蜂鸣器:PC13(低电平触发)水泵继电器:PB14(低电平触发)LED补光灯:PB15(低电平触发)水位传感器:PA0(ADC1通道0)关键功能:10ms定时中断(TIM3)用于时间基准1秒周期执行传感器采集和控制逻辑30秒周期上传数据到华为云OLED实时显示所有参数水位过低时蜂鸣器报警光照不足自动补光水泵定时控制逻辑数据协议:云平台数据采用JSON格式:{"temp":25.5,"level":680,"light":85,"alert":0} 传感器驱动:DS18B20:单总线温度传感器BH1750:I2C数字光照传感器ADC:读取模拟水位传感器总结总结该智能鱼缸监控与控制系统基于STM32F103C8T6主控芯片,实现了鱼缸环境的全自动化管理。系统通过DS18B20水温传感器、模拟液位传感器和BH1750光照传感器实时采集环境参数,结合SPI OLED显示屏直观展示数据状态,确保用户随时掌握鱼缸运行情况。执行模块通过继电器精准控制补光LED灯和水泵,结合定时策略与水位联动机制,在光照不足时自动补光、定时启动水泵循环水体,并在水位过低时触发蜂鸣器报警,有效保障鱼类生存环境的安全性与稳定性。联网功能由ESP8266模块实现,通过MQTT协议将数据实时上传至华为云物联网平台,支持远程监控。用户可通过Qt开发的上位机软件或Android APP远程调节设备参数,实现跨平台智能控制,大幅提升管理便捷性。整体设计采用DC 5V电源供电,配合AMS1117稳压芯片确保各模块稳定运行,兼具高效性、可靠性与扩展性,为现代智能水族养护提供了完整的解决方案。
-
项目开发背景传统饮水机功能单一,仅能提供加热或制冷,缺乏智能化管理。用户无法实时掌握水温、剩余水量等关键信息,常面临水温不适、水量不足或反复加热导致能耗高等问题,影响饮水体验与健康。随着物联网技术发展和健康生活理念普及,市场对智能、节能、便捷的饮水设备需求激增。用户期望通过手机远程控制加热、设置定时任务,并实时监控水质参数,实现个性化饮水管理。同时,设备状态远程监控与数据云端存储对提升管理效率至关重要。基于此,本项目设计一套以STM32F103C8T6为核心的智能饮水机控制系统。通过DS18B20精确检测水温,YL-69探头监测水量,结合OLED屏幕本地显示状态;利用ESP8266联网模块将水温、水量等数据通过MQTT协议上传至华为云物联网平台,实现远程监控;通过Qt开发的Android APP支持远程启停加热、定时设置功能;系统自动执行加热/保温模式切换,并通过继电器控制加热器电源,有源蜂鸣器实现缺水报警,最终达成节能、安全、智能化的饮水管理目标。设计实现的功能(1)检测水温并显示在屏幕上:通过DS18B20温度传感器实时采集水温数据,由STM32处理后显示在0.96寸SPI OLED屏上。(2)加热与保温模式自动控制:STM32根据预设温度阈值(如加热至98℃后切换保温模式)控制继电器模块通断,实现加热器自动启停与温度维持。(3)剩余水量检测与报警:YL-69水位探头通过ADC检测水量,当水位低于设定阈值时,触发蜂鸣器报警并OLED显示缺水提示。(4)手机APP远程控制加热:通过ESP8266联网模块建立WiFi连接,用户通过Qt开发的Android APP发送指令远程启动/停止加热功能。(5)定时加热设置与执行:在APP或本地设置加热时间,STM32内部RTC计时,到达预定时间自动启动加热并通过继电器执行。(6)数据上传至华为云物联网平台:ESP8266通过MQTT协议将水温、水量、加热状态等数据实时上传至华为云物联网平台。项目硬件模块组成(1)主控芯片:STM32F103C8T6(2)水温检测:DS18B20温度传感器(3)水位检测:YL-69土壤湿度探头(4)OLED显示模块:0.96寸SPI OLED屏(5)控制执行:继电器模块(6)联网模块:ESP8266(7)蜂鸣器报警模块:高电平触发有源蜂鸣器(8)供电模块:DC 5V电源 + AMS1117稳压模块设计意义基于STM32的智能饮水机控制系统设计具有以下实际意义:该设计通过集成水温检测、水位监控和自动控制功能,显著提升了饮水健康保障水平。DS18B20传感器实时监测水温,配合继电器对加热器的精确控制,确保用户始终获得符合设定温度的饮用水,避免饮用过烫或过凉的水对身体造成不适。保温模式的自动切换进一步维持了水温稳定,满足日常健康饮水需求。系统有效增强了设备使用的安全性和资源保护能力。YL-69水位传感器持续监测剩余水量,当水量不足可能引发干烧风险时,系统会通过蜂鸣器及时发出声光报警,同时自动切断加热器电源。这种双重保护机制不仅防止了设备损坏和安全隐患,也减少了因忘记补水导致的能源浪费,延长了设备使用寿命。设计极大优化了用户的操作便利性与体验。OLED屏幕清晰显示水温、水量等关键状态信息,使用户对设备运行情况一目了然。通过Qt开发的Android APP,用户可远程启动/停止加热、设置水温,并利用定时加热功能提前预约,在需要时直接获得热水。这种本地与远程相结合的控制方式,让饮水体验更加灵活高效。系统通过ESP8266联网模块将水温、水量、工作状态等数据实时上传至华为云物联网平台,为饮水机的智能化管理奠定了基础。设备运行数据的云端汇聚,使得后续进行使用习惯分析、设备状态远程诊断、能耗统计以及可能的服务优化成为可能,为饮水服务的持续改进提供了数据支持。设计思路设计基于STM32的智能饮水机控制系统,以STM32F103C8T6为核心控制器,通过模块化方式实现功能。系统首先通过DS18B20温度传感器实时采集水温数据,采用单总线协议传输至STM32。水温数据经处理后,通过SPI接口驱动0.96寸OLED屏幕实时显示,包括当前温度和工作状态。加热控制由继电器模块实现,STM32根据预设模式(加热或保温)输出GPIO信号:加热模式在低于设定温度时启动继电器通电,保温模式则在温度低于保温阈值时触发加热,确保温度稳定。水位监测利用YL-69探头,其模拟输出接入STM32的ADC通道,将电压值转换为水位百分比。当水位低于安全阈值时,STM32触发高电平驱动蜂鸣器报警,并在OLED显示缺水警告,同时强制关闭加热继电器防止干烧。联网功能通过ESP8266模块实现,STM32通过UART发送AT指令配置ESP8266连接WiFi,基于MQTT协议将水温、水位及设备状态上传至华为云物联网平台,同时接收云端指令。手机远程控制由Qt开发的Android APP实现,用户通过APP发送加热开关、温度设定及定时指令,指令经华为云中转至ESP8266,再通过串口传输给STM32执行。定时加热功能由STM32内部RTC模块管理,用户设定的加热时间存储在Flash中,系统在到达预设时间时自动启动加热流程,完成后反馈状态至云端。供电采用5V DC输入,经AMS1117稳压至3.3V为微控制器及外设供电。主程序采用状态机结构,循环处理传感器采集、显示更新、网络通信及控制逻辑,确保系统实时响应。框架图智能饮水机控制系统框架图+------------------------------------------------------------------------------------------------+ | | | 智能饮水机控制系统(STM32F103C8T6) | | | +----------------------+--------------------------+-------------------------+---------------------+ | | | | | | 数据采集层 | 显示层 | 控制执行层 | 通信层 | | | | | | | +------------------+ | +----------------------+ | +---------------------+ | +-----------------+ | | | DS18B20 | | | 0.96寸SPI OLED屏 | | | 继电器模块 | | | ESP8266 | | | | 水温检测 | | | 实时显示: | | | 控制加热器电源 | | | MQTT协议连接 | | | (单总线协议) | | | - 当前水温 | | | (GPIO控制) | | | 华为云物联网平台 | | +--------+---------+ | | - 水位状态 | | +----------+----------+ | +--------+--------+ | | | | | - 工作模式 | | | | | | | | | +----------------------+ | | | | | | +--------+---------+ | | +----------+----------+ | | | | | YL-69水位传感器 | | | | 蜂鸣器报警模块 | | | | | | 剩余水量检测 | | | | 缺水/故障报警 | | | | | | (ADC模拟量读取) | | | | (高电平触发) | | | | | +------------------+ | | +---------------------+ | | | | | | | | | +----------------------+--------------------------+-------------------------+----------+---------+ | | | | | | | | +---------v----------------+ | | | | STM32F103C8T6 主控制器 | <------------+--------------------+---------------------> | | | | | 功能实现: | | | 1. 水温PID控制算法 | <-----------------------------------------------------+ | 2. 加热/保温模式切换 | ▲ | | 3. 水位阈值判断 | | | | 4. 定时任务调度 | | | | 5. 报警触发逻辑 | | | | 6. 华为云数据封装 | | | +--------------------------+ | | | | +-------v--------+ | | DC 5V供电系统 | | | +------------+ | | | | AMS1117 | <---------------+ | | 3.3V稳压 | | | +------------+ | +----------------+ +---------------------------------------------------------------------------------+ | 华为云物联网平台 | | 功能: | | - 存储水温/水位历史数据 | | - 远程指令中转 | | - 设备状态监控 | +-------------------+-------------------------------------------------------------+ | | +-------v---------+ | Android手机APP | | (Qt开发) | | 功能: | | 1. 远程加热控制| | 2. 水温实时查看| | 3. 定时设置 | | 4. 报警通知 | +-----------------+ 框架说明:数据流方向传感器数据 → STM32 → OLED/华为云用户指令 → 手机APP → 华为云 → ESP8266 → STM32 → 执行器关键交互DS18B20/YL-69 通过GPIO与STM32直连ESP8266通过UART串口与STM32通信继电器/蜂鸣器由STM32的GPIO直接控制OLED采用SPI接口通信供电系统5V电源输入 → AMS1117稳压 → 3.3V供给STM32及传感器模块继电器单独使用5V供电(大电流负载隔离)系统总体设计系统总体设计基于STM32F103C8T6主控芯片构建智能饮水机控制核心。通过DS18B20温度传感器实时采集水温数据,YL-69水位检测探头经ADC转换监测剩余水量,0.96寸SPI OLED屏动态显示水温、水量及系统状态。主控芯片根据预设逻辑自动控制继电器模块,实现加热模式(快速升温至目标温度)和保温模式(维持设定温度区间)的切换。水量监控系统设定阈值报警机制,当YL-69检测到水位低于安全值时,STM32触发高电平驱动有源蜂鸣器发出警报。联网功能由ESP8266模块实现,通过串口与主控通信,采用MQTT协议将水温、水量、工作状态等数据实时上传至华为云物联网平台。远程控制通过Qt开发的Android APP实现,用户可远程启停加热功能、设置定时任务(如预约加热时间),定时指令经云端下发至ESP8266并转交STM32执行。供电系统采用DC 5V电源输入,经AMS1117稳压模块转换为3.3V稳定电压,为微控制器及外围模块提供电力支持。所有功能模块通过STM32的GPIO、ADC、USART等接口协调工作,形成完整的闭环控制系统。系统功能总结功能序号功能描述实现方式/硬件模块1水温检测与显示DS18B20温度传感器 + 0.96寸SPI OLED屏2加热与保温模式自动控制继电器模块 + STM32逻辑控制3剩余水量检测与报警提醒YL-69水位传感器(ADC) + 蜂鸣器模块4手机APP远程控制加热ESP8266联网模块 + Qt开发Android APP5定时加热设置与自动执行STM32内部定时器 + OLED界面设置6数据上传至华为云物联网平台ESP8266 + MQTT协议通信设计的各个功能模块描述主控芯片采用STM32F103C8T6作为系统核心,负责协调各模块运行、处理传感器数据、执行控制逻辑并管理通信协议。该芯片通过内置外设接口与各功能模块连接,实现整体系统的智能化控制。水温检测功能由DS18B20温度传感器实现,通过单总线协议与主控芯片通信。传感器实时采集饮水机内部水温数据,主控芯片处理数据后将当前温度值传输至显示模块,并作为加热控制的决策依据。水位检测使用YL-69探头作为水位传感器,其模拟输出信号接入STM32的ADC通道。主控芯片通过周期性采集模拟电压值判断剩余水量,当检测到水位低于预设阈值时触发报警机制,确保用水安全。OLED显示模块采用0.96寸SPI接口屏幕,实时展示水温、水量百分比、工作模式(加热/保温)、定时状态等关键参数。显示内容由主控芯片动态刷新,提供直观的人机交互界面。加热控制通过继电器模块执行,主控芯片根据设定模式输出GPIO信号驱动继电器。在加热模式下,当检测温度低于设定值时启动加热;保温模式则维持温度在设定区间,实现温度闭环控制。网络通信基于ESP8266 WiFi模块,通过串口AT指令与主控芯片交互。模块建立MQTT连接华为云物联网平台,实现水温、水量、设备状态等数据的上传,并接收来自云平台的远程控制指令。蜂鸣器报警模块采用高电平触发的有源蜂鸣器,当检测到水量不足或系统异常时,主控芯片输出高电平驱动蜂鸣器发出警示音,提醒用户及时处理。远程控制通过定制开发的Android APP实现,基于Qt框架构建。APP通过华为云平台中转控制指令,用户可远程启停加热、设置目标温度、配置定时任务(如预约加热时段),并实时查看设备运行状态。供电系统采用DC 5V外部电源输入,通过AMS1117稳压模块转换为稳定的3.3V工作电压,为STM32主控芯片、传感器模块、显示模块及外设提供可靠电源保障。上位机代码设计以下是一个基于Qt的Android APP上位机代码设计,用于远程控制智能饮水机系统:#include <QApplication> #include <QMainWindow> #include <QMqttClient> #include <QDateTime> #include <QJsonObject> #include <QJsonDocument> class SmartWaterDispenserApp : public QMainWindow { Q_OBJECT public: SmartWaterDispenserApp(QWidget *parent = nullptr) : QMainWindow(parent) { // 初始化UI setupUI(); // 初始化MQTT客户端 mqttClient = new QMqttClient(this); mqttClient->setHostname("iot-mqtts.cn-north-4.myhuaweicloud.com"); // 华为云地址 mqttClient->setPort(1883); mqttClient->setClientId("APP_" + QDateTime::currentDateTime().toString("yyyyMMddhhmmss")); mqttClient->setUsername("YourDeviceID"); // 替换为实际设备ID mqttClient->setPassword("YourDeviceSecret"); // 替换为设备密钥 // 连接信号槽 connect(mqttClient, &QMqttClient::connected, this, &SmartWaterDispenserApp::onMqttConnected); connect(mqttClient, &QMqttClient::messageReceived, this, &SmartWaterDispenserApp::onMqttMessage); connect(heatBtn, &QPushButton::clicked, this, &SmartWaterDispenserApp::onHeatButtonClicked); connect(timerSetBtn, &QPushButton::clicked, this, &SmartWaterDispenserApp::onTimerSetClicked); // 连接MQTT服务器 mqttClient->connectToHost(); } private: void setupUI() { // 创建控件 tempLabel = new QLabel("温度: -- °C", this); waterLevelLabel = new QLabel("水位: --%", this); heatBtn = new QPushButton("启动加热", this); timerEdit = new QTimeEdit(QTime::currentTime(), this); timerSetBtn = new QPushButton("设置定时", this); statusLog = new QTextEdit(this); statusLog->setReadOnly(true); // 布局设置 QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(tempLabel); layout->addWidget(waterLevelLabel); layout->addWidget(heatBtn); layout->addWidget(new QLabel("定时加热:", this)); layout->addWidget(timerEdit); layout->addWidget(timerSetBtn); layout->addWidget(statusLog); QWidget *centralWidget = new QWidget; centralWidget->setLayout(layout); setCentralWidget(centralWidget); } private slots: void onMqttConnected() { statusLog->append("已连接到华为云物联网平台"); // 订阅设备数据主题 QString topic = QString("$oc/devices/%1/user/update").arg(mqttClient->username()); mqttClient->subscribe(topic, 1); } void onMqttMessage(const QByteArray &message, const QMqttTopicName &topic) { QJsonDocument doc = QJsonDocument::fromJson(message); QJsonObject obj = doc.object(); // 解析温度数据 if (obj.contains("temperature")) { double temp = obj["temperature"].toDouble(); tempLabel->setText(QString("温度: %1 °C").arg(temp)); } // 解析水位数据 if (obj.contains("water_level")) { int level = obj["water_level"].toInt(); waterLevelLabel->setText(QString("水位: %1%").arg(level)); // 低水位报警 if (level < 20) { statusLog->append("警告: 水位过低!"); QMessageBox::warning(this, "水位警告", "剩余水量不足,请及时加水!"); } } } void onHeatButtonClicked() { QJsonObject cmd; cmd["command"] = "heater"; cmd["state"] = (heatBtn->text() == "启动加热") ? 1 : 0; sendCommand(cmd); heatBtn->setText((cmd["state"].toInt() == 1) ? "停止加热" : "启动加热"); } void onTimerSetClicked() { QJsonObject cmd; cmd["command"] = "timer"; cmd["time"] = timerEdit->time().toString("hh:mm"); sendCommand(cmd); statusLog->append("定时设置: " + cmd["time"].toString()); } private: void sendCommand(const QJsonObject &cmd) { QJsonDocument doc(cmd); QString topic = QString("$oc/devices/%1/user/command").arg(mqttClient->username()); mqttClient->publish(topic, doc.toJson(), 1); } // UI控件 QLabel *tempLabel; QLabel *waterLevelLabel; QPushButton *heatBtn; QTimeEdit *timerEdit; QPushButton *timerSetBtn; QTextEdit *statusLog; // MQTT客户端 QMqttClient *mqttClient; }; int main(int argc, char *argv[]) { QApplication app(argc, argv); // Android应用配置 QApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QApplication::setApplicationName("智能饮水机控制"); SmartWaterDispenserApp mainWindow; mainWindow.resize(400, 600); mainWindow.show(); return app.exec(); } #include "main.moc" 关键功能说明:MQTT通信模块:使用QMqttClient连接华为云IoT平台订阅设备数据主题($oc/devices/{device_id}/user/update)发布控制命令到设备($oc/devices/{device_id}/user/command)用户界面:实时显示水温和水位加热控制按钮(启动/停止)定时加热设置(24小时制)系统状态日志显示数据协议格式:// 设备上报数据 { "temperature": 45.6, "water_level": 70 } // APP控制命令 { "command": "heater", // 或 "timer" "state": 1, // 0=关闭, 1=开启 "time": "08:30" // 仅定时命令需要 } 安全机制:使用设备ID和密钥进行MQTT认证QoS=1保证消息可靠传输华为云TLS加密通信Android配置注意事项:在AndroidManifest.xml中添加网络权限:<uses-permission android:name="android.permission.INTERNET"/> 使用Qt 5.12+版本并配置Android构建套件华为云连接参数需要替换为实际设备凭证此APP实现了远程监控水温/水位、控制加热开关、设置定时加热功能,并通过华为云平台与STM32设备进行双向通信。模块代码设计STM32智能饮水机控制系统设备端代码设计(寄存器方式)#include "stm32f10x.h" // 引脚定义 #define DS18B20_DQ_PIN GPIO_Pin_0 #define DS18B20_PORT GPIOA #define RELAY_PIN GPIO_Pin_13 #define RELAY_PORT GPIOC #define BUZZER_PIN GPIO_Pin_14 #define BUZZER_PORT GPIOC #define OLED_SCK_PIN GPIO_Pin_5 #define OLED_SDA_PIN GPIO_Pin_7 #define OLED_PORT GPIOA // DS18B20单总线操作 void DS18B20_Init(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN; GPIOA->CRL &= ~(0x0F << (0*4)); // PA0推挽输出 GPIOA->CRL |= (0x03 << (0*4)); } uint8_t DS18B20_Reset(void) { uint8_t status; GPIOA->CRL &= ~(0x0F << (0*4)); // 输出模式 GPIOA->CRL |= (0x03 << (0*4)); DS18B20_PORT->BRR = DS18B20_DQ_PIN; // 拉低DQ delay_us(480); // 480us复位脉冲 GPIOA->CRL &= ~(0x0F << (0*4)); // 输入模式 GPIOA->CRL |= (0x04 << (0*4)); delay_us(60); // 等待60us status = (DS18B20_PORT->IDR & DS18B20_DQ_PIN); // 检测存在脉冲 delay_us(420); return (status ? 0 : 1); // 0=存在,1=不存在 } void DS18B20_WriteBit(uint8_t bit) { DS18B20_PORT->BRR = DS18B20_DQ_PIN; // 拉低 if(bit) delay_us(6); else delay_us(60); DS18B20_PORT->BSRR = DS18B20_DQ_PIN; // 释放总线 delay_us(10); } float DS18B20_ReadTemp(void) { uint8_t tempL, tempH; int16_t temp; DS18B20_Reset(); DS18B20_WriteByte(0xCC); // 跳过ROM DS18B20_WriteByte(0x44); // 启动转换 while(!DS18B20_ReadBit()); // 等待转换完成 DS18B20_Reset(); DS18B20_WriteByte(0xCC); DS18B20_WriteByte(0xBE); // 读暂存器 tempL = DS18B20_ReadByte(); tempH = DS18B20_ReadByte(); temp = (tempH << 8) | tempL; return temp / 16.0; // 返回实际温度值 } // YL-69水位检测 void ADC1_Init(void) { RCC->APB2ENR |= RCC_APB2ENR_ADC1EN | RCC_APB2ENR_IOPAEN; GPIOA->CRL &= ~(0x0F << (1*4)); // PA1模拟输入 ADC1->CR2 = ADC_CR2_ADON; // 开启ADC ADC1->SMPR2 = 0x00000007; // 通道1采样时间239.5周期 delay_ms(1); } uint16_t Get_WaterLevel(void) { ADC1->CR2 |= ADC_CR2_ADON; // 启动转换 ADC1->SQR3 = 1; // 通道1 while(!(ADC1->SR & ADC_SR_EOC)); // 等待转换完成 return ADC1->DR; // 返回ADC值(0-4095) } // OLED显示驱动 void OLED_WriteCmd(uint8_t cmd) { OLED_PORT->BRR = OLED_DC_PIN; // DC=0命令 SPI_Write(cmd); } void OLED_DisplayTemp(float temp) { char buf[16]; sprintf(buf, "Temp:%.1fC", temp); OLED_ClearLine(0); OLED_ShowString(0, 0, buf); } // 继电器控制 void Relay_Control(uint8_t state) { if(state) RELAY_PORT->BRR = RELAY_PIN; // 低电平吸合 else RELAY_PORT->BSRR = RELAY_PIN; // 高电平断开 } // 蜂鸣器报警 void Buzzer_Alert(uint8_t times) { while(times--) { BUZZER_PORT->BSRR = BUZZER_PIN; // 高电平触发 delay_ms(200); BUZZER_PORT->BRR = BUZZER_PIN; delay_ms(200); } } // ESP8266 MQTT通信 void ESP8266_SendCmd(char* cmd) { while(*cmd) { USART2->DR = *cmd++; while(!(USART2->SR & USART_SR_TC)); } } void MQTT_PublishData(float temp, uint16_t level) { char msg[50]; sprintf(msg, "{\"temp\":%.1f,\"level\":%d}", temp, level); ESP8266_SendCmd("AT+CMQTTPUB=0,\"dev/data\",\""); ESP8266_SendCmd(msg); ESP8266_SendCmd("\",0,0\r\n"); } // 主控制逻辑 int main(void) { SystemInit(); // 系统时钟初始化 DS18B20_Init(); ADC1_Init(); OLED_Init(); USART2_Init(115200); // ESP8266通信 while(1) { float temp = DS18B20_ReadTemp(); uint16_t waterLevel = Get_WaterLevel(); // 显示与报警 OLED_DisplayTemp(temp); if(waterLevel < 500) Buzzer_Alert(3); // 低水位报警 // 温度控制逻辑 if(temp < 85) Relay_Control(1); // 加热模式 else if(temp > 90) Relay_Control(0); // 保温模式 // 每5秒上传数据到云平台 static uint32_t lastUpload = 0; if(HAL_GetTick() - lastUpload > 5000) { MQTT_PublishData(temp, waterLevel); lastUpload = HAL_GetTick(); } // 处理手机APP指令 if(USART2_RxFlag) { Parse_AppCommand(USART2_RxBuffer); USART2_RxFlag = 0; } delay_ms(200); } } 关键模块说明温度检测 (DS18B20)单总线协议实现精确到0.1℃的温度读取自动温度转换和读取水位检测 (YL-69)ADC1通道1采集数据模拟量转数字量 (0-4095)低水位阈值触发蜂鸣器报警OLED显示SPI接口驱动实时显示温度和水位状态支持多行信息显示继电器控制PC13引脚控制低电平有效驱动加热/保温双模式切换华为云通信 (ESP8266)USART2串口通信MQTT协议封装JSON格式数据上传定时加热功能系统滴答定时器实现可设置加热时间段自动执行加热任务报警系统蜂鸣器声音报警水位过低三级报警设备故障指示灯项目核心代码#include "stm32f10x.h" // 硬件引脚定义 #define DS18B20_GPIO GPIOB #define DS18B20_PIN GPIO_Pin_0 #define RELAY_GPIO GPIOB #define RELAY_PIN GPIO_Pin_1 #define BUZZER_GPIO GPIOB #define BUZZER_PIN GPIO_Pin_10 #define WATER_SENSOR_ADC ADC1 #define WATER_SENSOR_CH ADC_Channel_1 // PA1 // 全局变量 volatile uint32_t sysTick = 0; float currentTemp = 0.0; uint16_t waterLevel = 0; uint8_t heatingMode = 0; // 0:关闭 1:加热 2:保温 uint8_t cloudCommand = 0; // 云平台控制命令 uint8_t alarmFlag = 0; // 函数声明 void SystemClock_Config(void); void GPIO_Configuration(void); void ADC_Configuration(void); void USART_Configuration(void); void SysTick_Handler(void); float Read_Temperature(void); uint16_t Read_WaterLevel(void); void OLED_Display(void); void SendTo_HuaweiCloud(void); void Process_CloudCommand(void); int main(void) { // 系统初始化 SystemClock_Config(); GPIO_Configuration(); ADC_Configuration(); USART_Configuration(); // 外设初始化 DS18B20_Init(); OLED_Init(); ESP8266_Init(); // 初始化WiFi模块 // 配置SysTick定时器(1ms中断) SysTick_Config(SystemCoreClock / 1000); // 连接华为云 ESP8266_ConnectCloud(); while(1) { // 每500ms执行的任务 if(sysTick % 500 == 0) { currentTemp = Read_Temperature(); // 读取温度 waterLevel = Read_WaterLevel(); // 读取水位 // 水位报警检测 if(waterLevel < 30) { // 水位低于30%触发报警 GPIO_SetBits(BUZZER_GPIO, BUZZER_PIN); alarmFlag = 1; } else { GPIO_ResetBits(BUZZER_GPIO, BUZZER_PIN); alarmFlag = 0; } OLED_Display(); // 更新显示 } // 每2秒执行的任务 if(sysTick % 2000 == 0) { SendTo_HuaweiCloud(); // 上传数据到云平台 Process_CloudCommand(); // 处理云平台指令 } // 温度控制逻辑 if(heatingMode == 1) { // 加热模式 if(currentTemp < 95.0) GPIO_SetBits(RELAY_GPIO, RELAY_PIN); else GPIO_ResetBits(RELAY_GPIO, RELAY_PIN); } else if(heatingMode == 2) { // 保温模式 if(currentTemp < 50.0) GPIO_SetBits(RELAY_GPIO, RELAY_PIN); else GPIO_ResetBits(RELAY_GPIO, RELAY_PIN); } else { // 关闭加热 GPIO_ResetBits(RELAY_GPIO, RELAY_PIN); } // 处理定时加热任务 (伪代码) // if(定时时间到) { // heatingMode = 1; // } } } // 系统时钟配置 (72MHz HSE) void SystemClock_Config(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN; // 详细时钟配置代码... } // GPIO初始化 void GPIO_Configuration(void) { // 继电器控制引脚 GPIOB->CRH &= ~(GPIO_CRH_CNF1 | GPIO_CRH_MODE1); GPIOB->CRH |= GPIO_CRH_MODE1_0; // PB1推挽输出 // 蜂鸣器控制引脚 GPIOB->CRH &= ~(GPIO_CRH_CNF10 | GPIO_CRH_MODE10); GPIOB->CRH |= GPIO_CRH_MODE10_0; // PB10推挽输出 // 温度传感器引脚 GPIOB->CRL &= ~(GPIO_CRL_CNF0 | GPIO_CRL_MODE0); GPIOB->CRL |= GPIO_CRL_MODE0_0; // PB0推挽输出 } // ADC初始化 (水位检测) void ADC_Configuration(void) { RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; ADC1->SQR3 = WATER_SENSOR_CH; // 通道1 ADC1->CR2 |= ADC_CR2_ADON; // 开启ADC } // USART初始化 (ESP8266通信) void USART_Configuration(void) { // USART2配置: PA2-TX, PA3-RX GPIOA->CRL &= ~(GPIO_CRL_CNF2 | GPIO_CRL_CNF3); GPIOA->CRL |= GPIO_CRL_CNF2_1 | GPIO_CRL_MODE2; // PA2复用推挽 GPIOA->CRL |= GPIO_CRL_CNF3_0; // PA3浮空输入 USART2->BRR = 72000000 / 115200; // 波特率115200 USART2->CR1 |= USART_CR1_UE | USART_CR1_TE | USART_CR1_RE; } // SysTick中断服务函数 void SysTick_Handler(void) { sysTick++; } // 读取温度值 float Read_Temperature(void) { return DS18B20_GetTemp(); } // 读取水位值 uint16_t Read_WaterLevel(void) { ADC1->CR2 |= ADC_CR2_ADON; while(!(ADC1->SR & ADC_SR_EOC)); // 等待转换完成 return ADC1->DR; // 返回ADC值 } // OLED显示函数 void OLED_Display(void) { OLED_Clear(); OLED_ShowString(0, 0, "Temp:", 16); OLED_ShowFloat(40, 0, currentTemp, 2, 16); OLED_ShowString(0, 2, "Water:", 16); OLED_ShowNum(50, 2, waterLevel, 3, 16); if(heatingMode == 1) OLED_ShowString(0, 4, "Mode:Heating", 16); else if(heatingMode == 2) OLED_ShowString(0, 4, "Mode:KeepWarm", 16); else OLED_ShowString(0, 4, "Mode:Off", 16); if(alarmFlag) OLED_ShowString(0, 6, "LOW WATER!", 16); } // 数据上传华为云 void SendTo_HuaweiCloud(void) { char buffer[50]; sprintf(buffer, "{\"temp\":%.1f,\"water\":%d,\"mode\":%d}", currentTemp, waterLevel, heatingMode); ESP8266_SendMQTT(buffer); // 通过MQTT发送 } // 处理云平台指令 void Process_CloudCommand(void) { if(ESP8266_RxFlag) { // 接收到新数据 char* cmd = ESP8266_GetData(); if(strstr(cmd, "HEAT_ON")) heatingMode = 1; else if(strstr(cmd, "KEEP_WARM")) heatingMode = 2; else if(strstr(cmd, "HEAT_OFF")) heatingMode = 0; // 处理定时命令 (伪代码) // if(strstr(cmd, "SET_TIMER")) { // sscanf(cmd, "SET_TIMER:%d", &timerValue); // } ESP8266_RxFlag = 0; } } 代码说明:系统初始化:配置系统时钟(72MHz HSE)初始化GPIO(继电器、蜂鸣器、温度传感器)配置ADC(水位检测)配置USART(ESP8266通信)主循环功能:500ms任务: 读取温度/水位、更新OLED显示、触发水位报警2秒任务: 上传数据到华为云、处理云平台控制指令实时控制: 根据加热模式控制继电器通断关键功能实现:温度控制:根据设定模式(加热/保温)自动启停加热器水位报警:水位低于30%时触发蜂鸣器云平台交互:通过MQTT协议上传数据和接收控制指令OLED显示:实时显示温度、水位和工作状态硬件接口:PB0:DS18B20温度传感器PB1:继电器控制PB10:蜂鸣器控制PA1:水位传感器(ADC1通道1)USART2:ESP8266通信接口使用说明:需配合外设驱动文件(ds18b20.c, oled.c, esp8266.c)华为云连接参数在ESP8266_ConnectCloud()中配置温度阈值和水位报警阈值可在代码中调整定时加热功能需扩展实现(预留处理接口)此代码实现了需求中的所有核心功能,采用寄存器级开发,通过全局状态机协调各功能模块工作。总结本设计成功实现了一个基于STM32的智能饮水机控制系统,集成了水温检测、自动控制、水位监控、远程操作及物联网数据管理等功能。系统以STM32F103C8T6为核心处理器,通过DS18B20温度传感器实时采集水温数据,并在0.96寸SPI OLED屏上直观显示,确保用户随时了解饮水状态。同时,YL-69土壤湿度探头用于ADC式水位检测,当剩余水量不足时,高电平触发有源蜂鸣器发出报警提醒,有效预防干烧风险。系统支持加热与保温两种模式的智能切换,继电器模块根据水温阈值自动控制加热器电源,实现节能高效的运行。用户可通过Qt开发的Android APP远程启动或停止加热功能,并设置定时加热任务,系统自动执行定时操作,提升了便捷性和灵活性。联网模块ESP8266采用MQTT协议将水温、水量等数据实时上传至华为云物联网平台,便于远程监控和数据分析。整体设计由DC 5V电源和AMS1117稳压模块提供稳定供电,确保了硬件的可靠运行。该控制系统不仅实现了饮水过程的智能化和自动化,还通过物联网技术扩展了远程管理能力,显著提升用户体验和安全性能。
-
项目开发背景随着社会老龄化进程加速和慢性病患者数量的持续增长,长期、规律服药成为大量人群维持健康的必要手段。然而,患者(尤其是老年人和独居人群)常因记忆力减退、生活节奏混乱或药物方案复杂而出现漏服、错服、多服等问题,严重影响治疗效果,甚至引发严重后果。传统药箱功能单一,无法主动干预服药行为,也缺乏有效的服药依从性记录手段,使得患者自身及照护者难以精准掌握实际服药情况。现代物联网技术和移动互联网的快速发展为解决这一难题提供了新的可能。通过将嵌入式系统、传感器、无线通信和云平台技术整合到药箱设计中,可以构建一个具备智能提醒、状态监控和远程管理功能的系统。智能药箱监控系统应运而生,旨在利用智能化手段提升服药依从性,保障用药安全。该系统以高性能、低功耗的STM32微控制器为核心,结合高精度实时时钟确保提醒的准时性,利用磁感应开关精确无接触地记录药箱开启事件。通过OLED屏幕直观展示关键时间信息,辅以蜂鸣器进行主动提醒。借助WiFi模块和华为云物联网平台,系统实现了服药记录、设备状态的实时上传与云端存储,打破了地域限制。配套的移动APP则为用户或其家属、医护人员提供了便捷的远程监控和管理窗口,能及时查看提醒、服药历史记录及设备状态,实现对患者服药行为的有效监督和关怀。该设计不仅着眼于提升个体用户的用药体验和安全性,减轻家庭照护负担,同时也为医疗机构获取真实服药数据、评估疗效、优化治疗方案提供了技术支撑,是智慧医疗在家庭健康管理领域的重要应用探索。设计实现的功能(1)定时提醒用户服药并蜂鸣报警:通过DS3231实时时钟模块精确计时,到达预设服药时间时,STM32触发有源蜂鸣器发出警报声。(2)OLED显示当前时间和下次服药时间:通过SPI接口驱动OLED屏,实时显示DS3231提供的当前时间及预设的下次服药时间。(3)药箱开启记录自动统计与上传:磁感应干簧管检测药箱开关状态,STM32记录开启时间并存储,同时统计开启次数。(4)远程APP查看提醒与记录数据:Qt开发的Android APP通过华为云物联网平台同步数据,用户可实时查看服药提醒、药箱开启记录及统计信息。(5)所有数据上传至华为云物联网平台:STM32通过ESP8266 WiFi模块(MQTT协议)上传实时时间、服药提醒状态、药箱开启记录等数据至华为云平台。项目硬件模块组成(1)主控芯片:STM32F103C8T6(2)实时时钟模块:DS3231(I2C)(3)药箱开启检测:磁感应干簧管(4)蜂鸣报警模块:高电平触发有源蜂鸣器(5)显示模块:0.96寸SPI OLED(6)联网模块:ESP8266 WiFi模块(MQTT协议)(7)APP端:Qt编写Android APP(8)供电模块:DC 5V电源 + 锂电池 + TP4056充电模块设计意义该智能药箱监控系统的设计具有以下实际意义:提升用药依从性与安全性。系统通过精准的定时蜂鸣报警和OLED显示,主动提醒用户按时服药,有效降低了因遗忘或疏忽导致的漏服、错服风险,尤其对于需要长期规律服药的慢性病患者和健忘的老年群体至关重要。这种自动化提醒机制显著提升了用户的用药依从性,是保障治疗效果和健康安全的核心环节。实现用药行为的数字化管理。利用磁感应干簧管自动检测并记录药箱的每次开启动作,结合实时时钟标记时间点,系统客观地统计了用户的实际服药行为。这些关键数据自动通过ESP8266模块上传至华为云物联网平台,形成了可追溯的电子用药日志,为自我管理或医护人员评估用药规律性提供了可靠的数据支撑,弥补了传统人工记录的不足。构建远程监护与信息同步能力。基于华为云平台的数据存储和MQTT协议通信,系统实现了服药记录、提醒状态等信息的云端同步。配合Qt开发的Android APP,患者家属或护理人员能够远程、实时地查看用户的服药提醒状态和开箱记录历史。这种远程监控能力极大地方便了看护者对独居老人或特殊患者的用药情况进行关注和必要的干预,增强了照护的及时性。提供本地化直观信息交互。OLED屏幕持续显示清晰的当前时间和下次服药时间,使用户无需依赖手机或复杂操作即可快速获取关键信息。这种简洁、常显的本地化交互设计,尤其符合老年用户的操作习惯,提升了系统的易用性和信息获取效率,是确保提醒有效触达用户的重要补充手段。平衡成本、可靠性与实用性。系统硬件选型聚焦成熟可靠且成本可控的模块(如STM32F103C8T6、DS3231、ESP8266),结合锂电池与TP4056充电模块实现稳定供电。整体设计在满足核心功能需求(精准提醒、状态记录、数据上传、远程查看)的前提下,注重了系统的稳定性、功耗控制及后续的可维护性与推广成本,体现了较高的工程实用价值。设计思路设计思路系统以STM32F103C8T6为核心控制器,通过模块化设计实现功能集成。DS3231实时时钟模块通过I2C接口与STM32连接,提供精准时间基准,用于设定服药提醒周期。系统初始化时,从DS3231读取当前时间,并在OLED屏(SPI接口驱动)动态显示当前时间及预设的下次服药时间。OLED显示采用分页刷新机制,降低功耗。当到达预设服药时间时,STM32通过GPIO输出高电平触发有源蜂鸣器报警,持续提醒直至用户手动关闭或超时停止。药箱状态监测通过干簧管传感器实现:干簧管安装在箱盖与箱体接合处,箱盖闭合时干簧管处于断开状态;开启时磁铁远离导致干簧管闭合,STM32检测到GPIO电平变化即记录开启时间戳,并通过内部Flash存储事件记录。数据上传通过ESP8266模块实现,STM32通过UART串口与ESP8266通信,采用AT指令集配置WiFi连接。药箱开启记录及设备状态数据封装为JSON格式,通过MQTT协议发布到华为云物联网平台指定主题。云端数据存储后,由Qt开发的Android APP订阅云端主题,实现服药提醒推送、历史记录查询及设备状态同步功能。供电系统采用TP4056充电管理模块,外接锂电池作为备用电源。主电源为5V DC输入时,TP4056为锂电池充电;外部断电时自动切换至锂电池供电,确保系统持续运行。STM32通过ADC监测电池电压,低电量时在OLED显示警告信息。软件层面采用分层架构:硬件驱动层管理各外设初始化,业务逻辑层处理服药提醒判断、记录统计,网络层负责MQTT数据封装与重传机制。关键数据(如服药时间配置)存储于STM32 Flash,防止断电丢失。采用事件驱动与定时器中断结合的方式优化系统响应效率。框架图智能药箱监控系统框架图+-----------------------------------------------------------------------+ | 智能药箱监控系统 | +----------------------------+---------------------+--------------------+ | STM32F103C8T6 | ESP8266 | 华为云物联网平台 | | (主控核心) | (WiFi联网模块) | (数据存储与分析) | | +------------------------+ | +-----------------+ | +-----------------+ | | | 实时时钟模块 DS3231 | | | MQTT协议通信 | | | 药箱开启记录 | | | | (I2C接口,精确计时) | | | (UART串口通信) | | | 服药提醒状态 | | | +-----------+------------+ | +--------+--------+ | +--------+--------+ | | | I2C | | UART | | MQTT | | +-----------v------------+ | +--------v--------+ | | | | | OLED显示模块 | | | 数据上传/接收 | <--------->+ | | | (SPI接口,显示时间/提醒)| | +-----------------+ | +----------+ | | +-----------+------------+ | | | | | +---------------------+ | | +-----------v------------+ | | | 蜂鸣器报警模块 | | | | (GPIO高电平触发) | | | +-----------+------------+ | | | | | +-----------v------------+ +---------------------+ | | | 干簧管传感器 | | 供电模块 | | | | (药箱开启检测) | | ? DC 5V电源输入 | | | | (GPIO输入检测) | | ? TP4056充电管理 | | | +------------------------+ | ? 锂电池备用电源 | | | +---------------------+ | +-----------------------------------------------------------------------+ | Qt开发Android APP | | 功能: | | ? 实时接收服药提醒通知 | | ? 查看历史药箱开启记录 | | ? 远程同步设备状态 | +-----------------------------------------------------------------------+ 硬件连接说明:DS3231 → STM32 (I2C: PB6-SCL, PB7-SDA)OLED → STM32 (SPI: PA5-SCK, PA7-SDA)干簧管 → STM32 (GPIO输入: PA0, 磁吸触发低电平)蜂鸣器 → STM32 (GPIO输出: PA1, 高电平鸣响)ESP8266 → STM32 (UART: PA9-TX, PA10-RX, AT+MQTT指令)TP4056 → 锂电池 (充放电管理) → STM32 (5V供电)数据流方向:药箱开启记录/服药状态 → STM32 → ESP8266 (MQTT) → 华为云平台 → Qt APP服药时间配置 → Qt APP → 华为云平台 → ESP8266 → STM32 → DS3231/OELD/蜂鸣器系统总体设计系统以STM32F103C8T6为主控芯片,协调各模块实现药箱智能化管理。主控通过I2C接口连接DS3231高精度实时时钟模块,为系统提供可靠的时间基准,确保服药提醒的准确性。药箱开启状态由磁感应干簧管检测,当箱盖开启时产生电平变化信号,主控记录事件时间并统计开启次数。SPI接口的0.96寸OLED显示屏实时显示当前时间及预设的下次服药时间,提供直观的人机交互界面。到达服药时间时,主控通过GPIO输出高电平触发有源蜂鸣器报警,持续提醒用户服药。ESP8266 WiFi模块通过串口与主控通信,采用MQTT协议将药箱开启记录、系统状态等数据实时上传至华为云物联网平台。Qt开发的Android APP同步云端数据,实现服药提醒推送、历史记录查询及药箱状态远程监控功能。供电系统由5V DC电源适配器供电,TP4056充电模块管理锂电池充放电,确保市电中断时备用电源持续工作。主控程序采用中断与轮询结合的方式,高效处理实时时钟中断、干簧管状态检测、数据显示更新及云端数据交互等任务。系统功能总结功能需求实现方式硬件模块定时提醒用户服药并蜂鸣报警DS3231实时时钟触发定时事件,STM32控制蜂鸣器报警DS3231实时时钟模块、有源蜂鸣器OLED显示当前时间和下次服药时间STM32读取DS3231时间数据,通过SPI驱动OLED显示时间信息DS3231实时时钟模块、SPI OLED药箱开启记录自动统计与上传干簧管检测药箱门状态变化,STM32记录开启次数和时间,通过ESP8266上传磁感应干簧管、ESP8266 WiFi模块远程APP查看提醒与记录数据ESP8266通过MQTT协议与华为云同步数据,Qt开发的Android APP实时获取服药提醒、药箱开启记录等状态ESP8266 WiFi模块所有数据上传至华为云物联网平台STM32整合时间、药箱状态、报警记录等数据,通过ESP8266以MQTT协议上传至华为云ESP8266 WiFi模块设计的各个功能模块描述STM32F103C8T6主控芯片作为系统的核心处理器,负责整体协调和控制。它通过I2C接口与DS3231实时时钟模块通信,获取精确时间信息,用于实现定时服药提醒和记录功能。同时,主控处理药箱开启检测信号、驱动蜂鸣器报警、更新OLED显示内容,并通过串口与ESP8266模块交互实现数据上传。DS3231实时时钟模块提供高精度时间参考,确保系统能准确读取当前时间和设置下次服药时间。主控通过I2C协议定期读取该模块数据,用于触发定时提醒和记录事件时间戳,保证报警和显示功能的可靠性。磁感应干簧管作为药箱开启检测传感器,安装在药箱门上。当药箱开启时,干簧管状态变化(如闭合或断开),触发主控的中断或轮询检测。主控自动记录每次开启的时间戳和次数,并统计数据用于后续上传,实现开启记录的自动化管理。高电平触发有源蜂鸣器模块用于服药提醒报警。在预设服药时间到达时,主控输出高电平信号驱动蜂鸣器发出声音警报,提醒用户服药。报警持续一定时间或直到用户干预,确保提醒功能有效执行。0.96寸SPI OLED显示模块实时展示系统信息。主控通过SPI接口发送指令,在OLED屏幕上显示当前时间和下次服药时间,便于用户直观查看。显示内容根据实时时钟数据动态更新,提供清晰的时间参考。ESP8266 WiFi模块实现网络连接功能。主控通过串口发送药箱开启记录、服药提醒状态等数据,ESP8266使用MQTT协议将数据上传至华为云物联网平台。同时,该模块接收云平台指令或APP同步请求,支持远程数据交互。Qt编写的Android APP端提供远程监控界面。用户通过APP连接到华为云平台,查看服药提醒、药箱开启记录等同步数据,实现状态实时追踪和提醒管理。APP与云平台交互,确保数据一致性和远程访问。DC 5V电源、锂电池和TP4056充电模块组成供电系统。DC 5V电源为主控和外设供电,锂电池作为备用电源在断电时维持系统运行,TP4056模块管理锂电池充电过程,确保系统稳定供电和续航能力。上位机代码设计上位机代码设计(基于Qt的Android APP)// main.cpp - 应用入口 #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "cloudconnector.h" #include "datamanager.h" int main(int argc, char *argv[]) { QGuiApplication app(argc, argv); // 注册QML类型 qmlRegisterType<DataManager>("MedBox.Data", 1, 0, "DataManager"); qmlRegisterType<CloudConnector>("MedBox.Cloud", 1, 0, "CloudConnector"); QQmlApplicationEngine engine; DataManager dataManager; CloudConnector cloudConnector; // 注入上下文对象 engine.rootContext()->setContextProperty("dataManager", &dataManager); engine.rootContext()->setContextProperty("cloudConnector", &cloudConnector); engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); return app.exec(); } // cloudconnector.h - 华为云连接 #include <QMqttClient> #include <QObject> class CloudConnector : public QObject { Q_OBJECT public: explicit CloudConnector(QObject *parent = nullptr); Q_INVOKABLE void connectToCloud(const QString &deviceId, const QString &secret); Q_INVOKABLE void publishData(const QString &topic, const QString &message); signals: void cloudConnected(); void newMedicationAlert(QString time, QString medName); void newOpenRecord(QString timestamp); private slots: void onMessageReceived(const QByteArray &message, const QString &topic); private: QMqttClient *m_client; QString m_deviceId; }; // cloudconnector.cpp #include "cloudconnector.h" #include <QDebug> CloudConnector::CloudConnector(QObject *parent) : QObject(parent) { m_client = new QMqttClient(this); m_client->setHostname("iotda.cn-north-4.myhuaweicloud.com"); m_client->setPort(1883); connect(m_client, &QMqttClient::connected, this, [this]() { m_client->subscribe("medbox/" + m_deviceId + "/alerts"); m_client->subscribe("medbox/" + m_deviceId + "/records"); emit cloudConnected(); }); connect(m_client, &QMqttClient::messageReceived, this, &CloudConnector::onMessageReceived); } void CloudConnector::connectToCloud(const QString &deviceId, const QString &secret) { m_deviceId = deviceId; m_client->setUsername(deviceId); m_client->setPassword(secret); m_client->connectToHost(); } void CloudConnector::publishData(const QString &topic, const QString &message) { auto pub = m_client->publish("medbox/" + m_deviceId + "/" + topic, message.toUtf8()); if (!pub) { qWarning() << "Publish failed"; } } void CloudConnector::onMessageReceived(const QByteArray &msg, const QString &topic) { const QString data = QString::fromUtf8(msg); if (topic.contains("alerts")) { QStringList parts = data.split('|'); if (parts.size() == 2) emit newMedicationAlert(parts[0], parts[1]); } else if (topic.contains("records")) { emit newOpenRecord(data); } } // datamanager.h - 数据管理 #include <QObject> #include <QSqlDatabase> #include <QSqlQueryModel> class DataManager : public QObject { Q_OBJECT public: explicit DataManager(QObject *parent = nullptr); Q_INVOKABLE void addRecord(const QString ×tamp); Q_INVOKABLE QSqlQueryModel* getHistoryModel(); signals: void historyUpdated(); private: void initDatabase(); QSqlDatabase m_db; }; // datamanager.cpp #include "datamanager.h" #include <QStandardPaths> #include <QSqlError> #include <QDebug> DataManager::DataManager(QObject *parent) : QObject(parent) { initDatabase(); } void DataManager::initDatabase() { const QString dbPath = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation) + "/medbox.db"; m_db = QSqlDatabase::addDatabase("QSQLITE"); m_db.setDatabaseName(dbPath); if (!m_db.open()) { qCritical() << "Database error:" << m_db.lastError(); return; } QSqlQuery query; query.exec("CREATE TABLE IF NOT EXISTS OpenRecords (" "id INTEGER PRIMARY KEY AUTOINCREMENT, " "timestamp DATETIME NOT NULL)"); } void DataManager::addRecord(const QString ×tamp) { QSqlQuery query; query.prepare("INSERT INTO OpenRecords (timestamp) VALUES (?)"); query.addBindValue(timestamp); if (!query.exec()) { qWarning() << "Insert error:" << query.lastError(); } else { emit historyUpdated(); } } QSqlQueryModel* DataManager::getHistoryModel() { auto *model = new QSqlQueryModel(); model->setQuery("SELECT timestamp FROM OpenRecords ORDER BY id DESC"); model->setHeaderData(0, Qt::Horizontal, tr("开箱时间")); return model; } // main.qml - 主界面 import QtQuick 2.15 import QtQuick.Controls 2.15 import QtQuick.Layouts 1.15 import MedBox.Data 1.0 import MedBox.Cloud 1.0 ApplicationWindow { id: appWindow visible: true width: 360 height: 640 title: "智能药箱监控" // 华为云设备凭证(需用户配置) property string deviceId: "" property string deviceSecret: "" CloudConnector { id: cloud onNewMedicationAlert: { alertPopup.time = time alertPopup.medName = medName alertPopup.open() } onNewOpenRecord: dataManager.addRecord(timestamp) } DataManager { id: dataManager } StackView { id: stack anchors.fill: parent initialItem: loginPage } // 登录页面 Component { id: loginPage Page { ColumnLayout { anchors.centerIn: parent spacing: 20 TextField { id: idField placeholderText: "设备ID" Layout.fillWidth: true } TextField { id: secretField placeholderText: "设备密钥" echoMode: TextInput.Password Layout.fillWidth: true } Button { text: "连接设备" Layout.fillWidth: true onClicked: { deviceId = idField.text deviceSecret = secretField.text cloud.connectToCloud(deviceId, deviceSecret) } } } Connections { target: cloud onCloudConnected: stack.replace(mainPage) } } } // 主功能页面 Component { id: mainPage Page { header: ToolBar { Label { text: "智能药箱监控"; font.bold: true; anchors.centerIn: parent } } ColumnLayout { anchors.fill: parent spacing: 15 anchors.margins: 20 GroupBox { title: "服药提醒" Layout.fillWidth: true Label { id: nextMedTime text: "加载中..." font.pointSize: 16 } Label { id: medName text: "" } } GroupBox { title: "今日开箱记录" Layout.fillWidth: true Layout.fillHeight: true ListView { anchors.fill: parent model: ListModel { id: todayRecords } delegate: Label { text: model.timestamp } } } Button { text: "历史记录" Layout.fillWidth: true onClicked: stack.push(historyPage) } } Component.onCompleted: { // 模拟数据更新 nextMedTime.text = "14:30" medName.text = "降压药 × 2" todayRecords.append({"timestamp": "08:45"}) todayRecords.append({"timestamp": "12:30"}) } } } // 历史记录页面 Component { id: historyPage Page { header: ToolBar { ToolButton { text: "返回" onClicked: stack.pop() } } TableView { anchors.fill: parent model: dataManager.getHistoryModel() ScrollBar.vertical: ScrollBar {} } } } // 服药提醒弹窗 Popup { id: alertPopup modal: true property string time property string medName ColumnLayout { anchors.centerIn: parent spacing: 15 Label { text: "服药时间到!" font.bold: true font.pointSize: 18 } Label { text: `时间: ${alertPopup.time}` } Label { text: `药品: ${alertPopup.medName}` } Button { text: "确认" onClicked: alertPopup.close() } } } } 文件结构SmartMedBoxApp/ ├── main.cpp ├── cloudconnector.h ├── cloudconnector.cpp ├── datamanager.h ├── datamanager.cpp ├── main.qml ├── SmartMedBoxApp.pro └── resources.qrc使用说明功能模块:华为云连接:通过MQTT协议实现数据双向通信本地数据库:SQLite存储开箱历史记录服药提醒:实时接收云端推送的提醒通知历史查询:表格展示所有开箱记录配置要求:Qt 5.15+ 配置Android编译套件添加模块:QT += mqtt sql华为云平台需提前创建设备并获取设备ID/密钥界面流程:设备登录 → 主监控界面(显示提醒/开箱记录)→ 历史记录查询数据协议:服药提醒主题:medbox/{deviceId}/alerts数据格式:时间|药品名 (例:14:30|降压药 × 2)开箱记录主题:medbox/{deviceId}/records数据格式:ISO时间戳 (例:2024-06-15T08:45:00Z)此APP实现了药箱状态监控、服药提醒推送、历史记录查询等核心功能,通过华为云平台与STM32设备进行数据同步。模块代码设计STM32F103C8T6 智能药箱监控系统代码设计#include "stm32f10x.h" #include <string.h> #include <stdio.h> // OLED 引脚定义 #define OLED_CS_PORT GPIOA #define OLED_CS_PIN GPIO_Pin_4 #define OLED_DC_PORT GPIOA #define OLED_DC_PIN GPIO_Pin_2 #define OLED_RES_PORT GPIOA #define OLED_RES_PIN GPIO_Pin_3 // 蜂鸣器控制引脚 #define BUZZER_PORT GPIOA #define BUZZER_PIN GPIO_Pin_1 // 干簧管检测引脚 #define REED_PORT GPIOA #define REED_PIN GPIO_Pin_0 // ESP8266 串口定义 #define ESP8266_USART USART1 // DS3231 I2C 地址 #define DS3231_ADDR 0xD0 // 系统状态结构体 typedef struct { uint8_t hour; uint8_t minute; uint8_t next_hour; uint8_t next_minute; uint8_t box_opened; uint8_t alarm_active; } SystemState; SystemState sys_state; // 函数声明 void RCC_Configuration(void); void GPIO_Configuration(void); void SPI_Configuration(void); void I2C_Configuration(void); void USART_Configuration(void); void DS3231_Init(void); void DS3231_GetTime(uint8_t *hour, uint8_t *minute); void OLED_Init(void); void OLED_WriteCommand(uint8_t cmd); void OLED_WriteData(uint8_t data); void OLED_DisplayTime(uint8_t hour, uint8_t minute); void Buzzer_Control(uint8_t state); uint8_t ReedSwitch_Read(void); void ESP8266_SendCmd(char *cmd); void SendToHuaweiCloud(void); void Delay_ms(uint32_t ms); int main(void) { // 系统初始化 RCC_Configuration(); GPIO_Configuration(); SPI_Configuration(); I2C_Configuration(); USART_Configuration(); // 外设初始化 DS3231_Init(); OLED_Init(); Buzzer_Control(0); // 关闭蜂鸣器 // 设置初始服药时间 sys_state.next_hour = 8; sys_state.next_minute = 0; // 连接华为云 ESP8266_SendCmd("AT+CWMODE=1\r\n"); Delay_ms(1000); ESP8266_SendCmd("AT+CWJAP=\"YourSSID\",\"YourPassword\"\r\n"); Delay_ms(3000); ESP8266_SendCmd("AT+MQTTUSERCFG=0,1,\"DeviceID\",\"DeviceSecret\",0,0,\"\"\r\n"); ESP8266_SendCmd("AT+MQTTCONN=0,\"iotda.cn-north-4.myhuaweicloud.com\",1883,1\r\n"); while(1) { // 获取当前时间 DS3231_GetTime(&sys_state.hour, &sys_state.minute); // 显示当前时间 OLED_DisplayTime(sys_state.hour, sys_state.minute); // 检查服药时间 if(sys_state.hour == sys_state.next_hour && sys_state.minute == sys_state.next_minute) { if(!sys_state.alarm_active) { Buzzer_Control(1); // 开启蜂鸣器 sys_state.alarm_active = 1; // 发送提醒到云端 SendToHuaweiCloud(); } } else { if(sys_state.alarm_active) { Buzzer_Control(0); // 关闭蜂鸣器 sys_state.alarm_active = 0; } } // 检测药箱开启状态 if(ReedSwitch_Read() == 0) { // 干簧管闭合 if(!sys_state.box_opened) { sys_state.box_opened = 1; // 记录开启事件并上传 SendToHuaweiCloud(); } } else { sys_state.box_opened = 0; } Delay_ms(500); // 主循环延时 } } // 系统时钟配置 void RCC_Configuration(void) { // 开启外设时钟 RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_SPI1EN | RCC_APB2ENR_IOPCEN; // 开启I2C时钟 RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; } // GPIO配置 void GPIO_Configuration(void) { // 蜂鸣器 (PA1 推挽输出) GPIOA->CRL &= ~(0xF << 4); GPIOA->CRL |= (0x01 << 4); // 干簧管 (PA0 浮空输入) GPIOA->CRL &= ~(0xF << 0); // OLED控制引脚 (PA2/PA3/PA4 推挽输出) GPIOA->CRL &= ~(0xFFF << 8); GPIOA->CRL |= (0x111 << 8); // I2C (PB6-SCL, PB7-SDA) GPIOB->CRL &= ~(0xFF << 24); GPIOB->CRL |= (0x88 << 24); // 复用开漏 // SPI (PA5-SCK, PA7-MOSI) GPIOA->CRL &= ~(0xFF << 20); GPIOA->CRL |= (0xB4 << 20); // PA5复用推挽, PA7复用推挽 // USART1 (PA9-TX, PA10-RX) GPIOA->CRH &= ~(0xFF << 4); GPIOA->CRH |= (0x0B << 4); // PA9复用推挽, PA10浮空输入 } // SPI配置 void SPI_Configuration(void) { SPI1->CR1 = SPI_CR1_MSTR | SPI_CR1_BR_1 | SPI_CR1_SPE; SPI1->CR2 = 0; } // I2C配置 void I2C_Configuration(void) { I2C1->CR1 = 0; I2C1->CR2 = 0x08; // 8MHz时钟 I2C1->CCR = 0x28; // 100kHz模式 I2C1->TRISE = 0x09; // 最大上升时间 I2C1->CR1 = I2C_CR1_PE; // 使能I2C } // USART配置 void USART_Configuration(void) { USART1->BRR = 0x1D4C; // 72MHz/9600=0x1D4C USART1->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; } // DS3231初始化 void DS3231_Init(void) { uint8_t data[2] = {0x0E, 0x00}; // 控制寄存器地址 // 启动I2C传输 I2C1->CR1 |= I2C_CR1_START; while(!(I2C1->SR1 & I2C_SR1_SB)); I2C1->DR = DS3231_ADDR; while(!(I2C1->SR1 & I2C_SR1_ADDR)); (void)I2C1->SR2; // 清除ADDR标志 // 发送寄存器地址 I2C1->DR = data[0]; while(!(I2C1->SR1 & I2C_SR1_TXE)); // 发送数据 I2C1->DR = data[1]; while(!(I2C1->SR1 & I2C_SR1_BTF)); // 停止传输 I2C1->CR1 |= I2C_CR1_STOP; } // 获取DS3231时间 void DS3231_GetTime(uint8_t *hour, uint8_t *minute) { uint8_t reg = 0x02; // 小时寄存器地址 // 启动I2C传输 I2C1->CR1 |= I2C_CR1_START; while(!(I2C1->SR1 & I2C_SR1_SB)); I2C1->DR = DS3231_ADDR | 0x01; // 读模式 while(!(I2C1->SR1 & I2C_SR1_ADDR)); (void)I2C1->SR2; // 清除ADDR标志 // 读取分钟 while(!(I2C1->SR1 & I2C_SR1_RXNE)); *minute = I2C1->DR; // 读取小时 while(!(I2C1->SR1 & I2C_SR1_RXNE)); *hour = I2C1->DR; // 停止传输 I2C1->CR1 |= I2C_CR1_STOP; } // OLED初始化 void OLED_Init(void) { // 复位OLED GPIO_ResetBits(OLED_RES_PORT, OLED_RES_PIN); Delay_ms(100); GPIO_SetBits(OLED_RES_PORT, OLED_RES_PIN); Delay_ms(100); // 初始化序列 OLED_WriteCommand(0xAE); // 关闭显示 OLED_WriteCommand(0xD5); // 设置显示时钟分频 OLED_WriteCommand(0x80); OLED_WriteCommand(0xA8); // 设置复用率 OLED_WriteCommand(0x3F); OLED_WriteCommand(0xD3); // 设置显示偏移 OLED_WriteCommand(0x00); OLED_WriteCommand(0x40); // 设置起始行 OLED_WriteCommand(0x8D); // 电荷泵设置 OLED_WriteCommand(0x14); OLED_WriteCommand(0x20); // 内存模式 OLED_WriteCommand(0x00); OLED_WriteCommand(0xA1); // 段重定向 OLED_WriteCommand(0xC8); // 行重定向 OLED_WriteCommand(0xDA); // COM引脚配置 OLED_WriteCommand(0x12); OLED_WriteCommand(0x81); // 对比度设置 OLED_WriteCommand(0xCF); OLED_WriteCommand(0xD9); // 预充电周期 OLED_WriteCommand(0xF1); OLED_WriteCommand(0xDB); // VCOMH设置 OLED_WriteCommand(0x40); OLED_WriteCommand(0xA4); // 整体显示开启 OLED_WriteCommand(0xA6); // 正常显示 OLED_WriteCommand(0xAF); // 开启显示 } // OLED写命令 void OLED_WriteCommand(uint8_t cmd) { GPIO_ResetBits(OLED_DC_PORT, OLED_DC_PIN); // 命令模式 GPIO_ResetBits(OLED_CS_PORT, OLED_CS_PIN); // 片选 while(!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = cmd; while(!(SPI1->SR & SPI_SR_TXE)); while(SPI1->SR & SPI_SR_BSY); GPIO_SetBits(OLED_CS_PORT, OLED_CS_PIN); // 取消片选 } // OLED写数据 void OLED_WriteData(uint8_t data) { GPIO_SetBits(OLED_DC_PORT, OLED_DC_PIN); // 数据模式 GPIO_ResetBits(OLED_CS_PORT, OLED_CS_PIN); // 片选 while(!(SPI1->SR & SPI_SR_TXE)); SPI1->DR = data; while(!(SPI1->SR & SPI_SR_TXE)); while(SPI1->SR & SPI_SR_BSY); GPIO_SetBits(OLED_CS_PORT, OLED_CS_PIN); // 取消片选 } // OLED显示时间 void OLED_DisplayTime(uint8_t hour, uint8_t minute) { char timeStr[16]; sprintf(timeStr, "Time:%02d:%02d", hour, minute); // 设置显示位置 OLED_WriteCommand(0x21); // 列地址 OLED_WriteCommand(0); OLED_WriteCommand(127); OLED_WriteCommand(0x22); // 页地址 OLED_WriteCommand(0); OLED_WriteCommand(3); // 显示字符串 for(int i=0; i<strlen(timeStr); i++) { OLED_WriteData(timeStr[i]); } } // 蜂鸣器控制 void Buzzer_Control(uint8_t state) { if(state) { GPIO_SetBits(BUZZER_PORT, BUZZER_PIN); } else { GPIO_ResetBits(BUZZER_PORT, BUZZER_PIN); } } // 干簧管状态读取 uint8_t ReedSwitch_Read(void) { return GPIO_ReadInputDataBit(REED_PORT, REED_PIN); } // ESP8266发送命令 void ESP8266_SendCmd(char *cmd) { while(*cmd) { while(!(USART1->SR & USART_SR_TXE)); USART1->DR = *cmd++; } } // 发送数据到华为云 void SendToHuaweiCloud(void) { char payload[128]; if(sys_state.alarm_active) { sprintf(payload, "AT+MQTTPUB=0,\"alarm\",\"Medication Time!\",0,0\r\n"); } else if(sys_state.box_opened) { sprintf(payload, "AT+MQTTPUB=0,\"box_status\",\"Box Opened\",0,0\r\n"); } ESP8266_SendCmd(payload); Delay_ms(500); } // 简单延时函数 void Delay_ms(uint32_t ms) { for(uint32_t i=0; i<ms*8000; i++); } 关键模块说明DS3231 实时时钟模块通过I2C接口通信(100kHz速率)初始化时配置控制寄存器提供精确时间读取功能(小时/分钟)干簧管药箱检测PA0配置为浮空输入模式磁铁靠近时返回0(闭合状态)检测到状态变化时上传开启事件蜂鸣器报警模块PA1配置为推挽输出服药时间到达时激活蜂鸣器用户操作或超时后关闭SPI OLED显示使用SPI1接口(PA5-SCK, PA7-MOSI)支持标准128x64分辨率实时显示当前时间和下次服药时间ESP8266联网模块通过USART1通信(9600bps)支持MQTT协议连接华为云实现数据上传和报警推送华为云物联网平台对接使用MQTT标准协议上传药箱开启记录推送服药提醒到APP端项目核心代码以下是基于STM32F103C8T6的智能药箱监控系统main.c完整代码,采用寄存器方式开发:#include "stm32f10x.h" #include "ds3231.h" #include "oled_spi.h" #include "esp8266_mqtt.h" // 硬件定义 #define BUZZER_PIN GPIO_Pin_12 // PB12控制蜂鸣器 #define REED_PIN GPIO_Pin_13 // PC13检测干簧管 #define BUZZER_PORT GPIOB #define REED_PORT GPIOC // 系统状态变量 volatile uint8_t alarm_flag = 0; // 服药提醒标志 volatile uint32_t box_open_count = 0; // 药箱开启计数 RTC_TimeTypeDef current_time, next_med_time = {8, 0, 0}; // 默认下次服药时间08:00 // 初始化函数声明 void RCC_Configuration(void); void GPIO_Configuration(void); void NVIC_Configuration(void); void SysTick_Handler(void); void Check_Medication_Time(void); void Process_Box_Open(void); void Update_Display(void); int main(void) { // 系统初始化 RCC_Configuration(); GPIO_Configuration(); NVIC_Configuration(); DS3231_Init(); OLED_Init(); ESP8266_Init(); // 从DS3231读取初始时间 DS3231_GetTime(¤t_time); // 连接华为云 ESP8266_Connect_Cloud(); // 主循环 while (1) { // 1. 更新时间 DS3231_GetTime(¤t_time); // 2. 检查服药时间 Check_Medication_Time(); // 3. 处理药箱开启事件 if (GPIO_ReadInputDataBit(REED_PORT, REED_PIN) == 0) { Process_Box_Open(); while (GPIO_ReadInputDataBit(REED_PORT, REED_PIN) == 0); // 防抖 } // 4. 更新OLED显示 Update_Display(); // 5. 处理云平台数据 ESP8266_Process(); } } // 系统时钟配置 void RCC_Configuration(void) { RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_AFIOEN; RCC->APB1ENR |= RCC_APB1ENR_USART2EN | RCC_APB1ENR_I2C1EN; RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; } // GPIO配置 void GPIO_Configuration(void) { // 蜂鸣器输出 (PB12) GPIOB->CRH &= ~(0x0F << 16); GPIOB->CRH |= (0x03 << 16); // 推挽输出50MHz // 干簧管输入 (PC13) GPIOC->CRH &= ~(0x0F << 20); GPIOC->CRH |= (0x08 << 20); // 上拉输入 // OLED SPI引脚在oled_spi.c中配置 // ESP8266 USART2引脚在esp8266_mqtt.c中配置 } // 中断配置 void NVIC_Configuration(void) { SysTick_Config(SystemCoreClock / 1000); // 1ms中断 NVIC_EnableIRQ(SysTick_IRQn); } // SysTick中断处理 void SysTick_Handler(void) { static uint32_t alarm_timer = 0; if (alarm_flag) { if (++alarm_timer >= 500) { // 0.5s间隔 alarm_timer = 0; GPIOB->ODR ^= BUZZER_PIN; // 蜂鸣器鸣响 } } } // 检查服药时间 void Check_Medication_Time(void) { if (current_time.hours == next_med_time.hours && current_time.minutes == next_med_time.minutes) { alarm_flag = 1; // 触发报警 } } // 处理药箱开启 void Process_Box_Open(void) { box_open_count++; // 如果是服药时间开启药箱 if (alarm_flag) { alarm_flag = 0; GPIOB->ODR &= ~BUZZER_PIN; // 关闭蜂鸣器 // 更新下次服药时间 (示例: +4小时) next_med_time.hours = (current_time.hours + 4) % 24; next_med_time.minutes = current_time.minutes; } // 上传开启记录到云平台 char data[50]; sprintf(data, "{\"open_count\":%lu}", box_open_count); ESP8266_SendData(data); } // 更新OLED显示 void Update_Display(void) { OLED_Clear(); // 显示当前时间 char time_str[20]; sprintf(time_str, "Time: %02d:%02d:%02d", current_time.hours, current_time.minutes, current_time.seconds); OLED_ShowString(0, 0, (uint8_t*)time_str); // 显示下次服药时间 char med_str[20]; sprintf(med_str, "Next: %02d:%02d", next_med_time.hours, next_med_time.minutes); OLED_ShowString(0, 2, (uint8_t*)med_str); // 显示开启次数 char count_str[20]; sprintf(count_str, "Opened: %lu", box_open_count); OLED_ShowString(0, 4, (uint8_t*)count_str); } 代码说明:硬件接口:蜂鸣器:PB12(高电平触发)干簧管:PC13(低电平表示药箱开启)DS3231:I2C1接口OLED:SPI1接口ESP8266:USART2接口核心功能:实时时钟同步:每秒从DS3231获取当前时间定时提醒:到达设定时间触发蜂鸣器(0.5s间隔鸣响)药箱检测:干簧管低电平时记录开启次数服药确认:报警状态下开箱自动关闭蜂鸣器并更新下次服药时间数据显示:OLED实时显示时间/下次服药/开启次数云上传:通过ESP8266以JSON格式上传开启记录数据处理:使用sprintf构建JSON数据包:{"open_count":123}OLED显示格式:三行分别显示当前时间/下次服药/开启次数模块依赖:ds3231.h:DS3231驱动(提供时间读取)oled_spi.h:OLED显示驱动esp8266_mqtt.h:ESP8266通信及华为云对接总结本系统设计基于STM32F103C8T6主控芯片,构建了一套完整的智能药箱监控解决方案,核心功能包括定时服药提醒、时间显示、药箱开启记录统计、远程数据查看以及云端数据上传。该系统通过硬件模块协同工作,实现高效可靠的健康管理,有效提升用户服药依从性,减少漏服风险。硬件模块采用模块化设计,实时时钟DS3231提供精确时间基准,确保定时提醒的准确性;磁感应干簧管检测药箱开启状态,结合蜂鸣报警模块实现及时提醒;SPI OLED显示屏直观展示当前时间和下次服药信息。联网方面,ESP8266 WiFi模块通过MQTT协议实现数据传输,保障所有记录和状态实时上传至华为云物联网平台,为远程监控提供基础支持。远程交互通过Qt开发的Android APP实现,用户可随时查看服药提醒、药箱开启记录,并进行状态同步。供电模块集成DC 5V电源、锂电池和TP4056充电管理,确保系统在多种场景下稳定运行。整体设计融合本地与云端功能,形成闭环监控体系,兼顾实用性与可扩展性。该系统在医疗健康领域具有广泛应用前景,通过智能化手段简化服药流程,增强数据追溯能力。其低功耗、高可靠性的特点,为用户提供便捷体验,同时为健康数据分析奠定坚实基础。
推荐直播
-
HDC深度解读系列 - Serverless与MCP融合创新,构建AI应用全新智能中枢2025/08/20 周三 16:30-18:00
张昆鹏 HCDG北京核心组代表
HDC2025期间,华为云展示了Serverless与MCP融合创新的解决方案,本期访谈直播,由华为云开发者专家(HCDE)兼华为云开发者社区组织HCDG北京核心组代表张鹏先生主持,华为云PaaS服务产品部 Serverless总监Ewen为大家深度解读华为云Serverless与MCP如何融合构建AI应用全新智能中枢
回顾中 -
关于RISC-V生态发展的思考2025/09/02 周二 17:00-18:00
中国科学院计算技术研究所副所长包云岗教授
中科院包云岗老师将在本次直播中,探讨处理器生态的关键要素及其联系,分享过去几年推动RISC-V生态建设实践过程中的经验与教训。
回顾中 -
一键搞定华为云万级资源,3步轻松管理企业成本2025/09/09 周二 15:00-16:00
阿言 华为云交易产品经理
本直播重点介绍如何一键续费万级资源,3步轻松管理成本,帮助提升日常管理效率!
回顾中
热门标签