当前位置: 首页 > news >正文

网站开发时间进度表购买服务器做网站

网站开发时间进度表,购买服务器做网站,网站注册域名备案,华阴市住房和城乡建设局网站基于STM32F407NBIOT华为云IOT平台设计的环境检测系统实现的功能#xff1a; 【1】能够采集本地环境的温度、湿度、烟雾浓度#xff0c;火光信息#xff0c;在OLED显示屏上显示。 如果检测到烟雾、温度、火光超过阀值会触发蜂鸣器报警。 【2】能够通过NBIOT将本地设备采集的信…基于STM32F407NBIOT华为云IOT平台设计的环境检测系统实现的功能 【1】能够采集本地环境的温度、湿度、烟雾浓度火光信息在OLED显示屏上显示。 如果检测到烟雾、温度、火光超过阀值会触发蜂鸣器报警。 【2】能够通过NBIOT将本地设备采集的信息上传到华为云物联网云平台。 【3】通过Qt(C)开发Android手机APP从华为云物联网云平台获取设备最新的数据进行显示完成信息展示在手机APP上可以显示检测到的温度、湿度、烟雾报警、火光报警信息。硬件选型 【1】主控芯片选择STM32F407 【2】环境温湿度传感器采用SHT30 【3】烟雾传感器采用MQ2 【4】火焰检测传感器采用火光检测传感器 【5】NBIOT采用BC26 【6】电源采用USB接口5V供电。 【7】蜂鸣器采用高电平触发的有源蜂鸣器。 【8】显示屏采用0.96寸IIC协议OLED显示屏。文章目录 一、前言1.1 项目介绍【1】项目开发背景【2】设计实现的功能【3】项目硬件模块组成【4】摘要 1.2 设计思路1.3 系统功能总结1.4 开发工具的选择【1】设备端开发【2】上位机开发 二、硬件选型2.1 STM32F407系统板2.2 杜邦线2排2.3 SHT30温湿度模块2.4 OLED显示屏4线IIC接口2.5 MQ2 烟雾传感器2.6 火焰检测模块2.7 电源扩展接口(x2)2.8 蜂鸣器模块2.9 NBIOT模块 三、部署华为云物联网平台3.1 物联网平台介绍3.2 开通物联网服务3.3 创建产品1创建产品2填写产品信息3产品创建成功4添加自定义模型 3.4 添加设备1注册设备2根据自己的设备填写3保存设备信息4设备创建完成5设备详情 3.5 MQTT协议主题订阅与发布1MQTT协议介绍2华为云平台MQTT协议使用限制3主题订阅格式4主题发布格式 3.6 MQTT三元组1MQTT服务器地址2生成MQTT三元组 3.7 模拟设备登录测试1填入登录信息2打开网页查看3MQTT登录测试参数总结 3.8 创建IAM账户3.9 获取影子数据 四、STM32设备端代码设计4.1 BC26-NBIOT配置代码4.2 定时器代码封装4.3 串口配置代码 五、上位机开发5.1 Qt开发环境安装5.2 新建上位机工程5.3 设计UI界面与工程配置【1】打开UI文件【2】开始设计界面 5.5 编译Windows上位机5.6 配置Android环境【1】选择Android编译器【2】创建Android配置文件【3】配置Android图标与名称【3】编译Android上位机 六、 BC26-NBIOT模块调试过程6.1 模块调试接线6.2 测试模块6.3 上电初始化操作6.4 开启GPS定位 七、总结 一、前言 1.1 项目介绍 【1】项目开发背景 随着物联网技术的快速发展越来越多的设备和系统开始融入我们的生活和工作中。环境监测作为一个重要的应用领域对于保障人们的健康和安全具有重要意义。基于STM32F407NBIOT华为云IOT平台设计的环境检测系统实现对室内环境的实时监测并通过物联网技术将数据传输至云端为用户提供便捷的数据查询和远程监控功能。 该系统的主要功能包括 1采集本地环境的温度、湿度、烟雾浓度和火光信息并在OLED显示屏上显示。当检测到烟雾、温度或火光超过预设阈值时触发蜂鸣器报警以提醒用户采取相应措施。 2通过NBIOT技术将本地设备采集的信息上传至华为云物联网云平台实现数据的远程存储和管理。 3利用Qt(C)开发的Android手机APP从华为云物联网云平台获取设备最新的数据进行显示完成信息展示。在手机APP上可以显示检测到的温度、湿度、烟雾报警和火光报警信息。 硬件选型方面选择了以下组件 1主控芯片STM32F407具有较高的处理能力和丰富的外设接口适合作为本系统的控制核心。 2环境温湿度传感器SHT30具有高精度、低功耗等特点适用于室内环境监测。 3烟雾传感器MQ2能够检测空气中的烟雾浓度及时发现火灾隐患。 4火焰检测传感器火光检测传感器用于检测火焰产生的光辐射实现火焰报警功能。 5NBIOT模块BC26支持NBIOT网络通信实现数据的远程传输。 6电源采用USB接口5V供电方便设备接入各种电源环境。 7蜂鸣器高电平触发的有源蜂鸣器用于发出报警声音。 8显示屏0.96寸IIC协议OLED显示屏用于显示采集到的环境参数和报警信息。 【2】设计实现的功能 1环境参数采集 利用STM32F407微控制器集成的高精度ADC及数字信号处理能力系统能够实时采集SHT30温湿度传感器输出的温湿度数据以及MQ2烟雾传感器和火光检测传感器提供的烟雾浓度和火光信息。这些传感器的选择确保了对环境状态的全面监控。 2数据显示 采集到的数据通过I²C接口传输至0.96寸OLED显示屏上实时显示提供直观的温湿度读数、烟雾浓度指标和火光警告信息。OLED屏因其自发光特性即便在低光照环境下也能清晰显示数据。 3本地预警系统 设定合理的阈值当检测到的温度、湿度、烟雾浓度或火光强度超过预设安全范围时系统将自动激活高电平触发的有源蜂鸣器发出报警声即时提醒现场人员注意潜在的环境危险。 4NBIOT通信 通过集成BC26 NBIOT模块系统能够将本地采集的环境数据通过窄带物联网技术远程上传至华为云物联网平台。NBIOT技术因其低功耗、广覆盖的特点特别适合于远程、低速数据传输的应用场景。 5云端数据处理与存储 上传至华为云的环境监测数据会被自动接收并存储华为云物联网平台提供强大的数据管理和分析能力支持用户通过云端界面查看历史数据趋势设置告警规则等。 6Android手机APP开发 利用Qt框架C开发的Android手机应用程序用户可以远程实时查看连接到华为云物联网平台的环境监测设备的最新数据。APP界面友好直观展示当前的温度、湿度、烟雾报警状态和火光报警信息使用户无论身在何处都能及时了解环境状况。 7交互性与控制 手机APP除了被动接收数据展示外还可以进一步设计实现远程控制功能如调整报警阈值、查询历史记录或发送指令给STM32F407控制端进行特定操作增强系统的互动性和管理效率。 本项目不仅实现了对环境参数的精准监测与本地预警还通过NBIOT技术与华为云物联网平台的结合提供了远程监控和数据分析的能力配以定制化的移动端应用极大地提升了环境监测的智能化和便捷性。 【3】项目硬件模块组成 1主控单元 - STM32F407微控制器 作为整个系统的核心STM32F407是一款高性能的32位ARM Cortex-M4内核微控制器具备丰富的外设资源和高速处理能力负责数据采集、处理、显示控制以及与外部模块的通信协调。 2温湿度传感器 - SHT30 用于测量环境中的温度和湿度通过I²C接口与STM32F407通信提供高精度的温湿度数据是环境监测的基础组成部分。 3烟雾传感器 - MQ2 用于检测环境中烟雾浓度能对多种气体敏感包括烟雾、LPG、甲烷等通过模拟信号输出至STM32F407用于评估火灾风险。 4火光检测传感器 专门设计用于探测火焰或高强度光源通过其光电效应产生电信号经处理后由STM32F407判断是否有火光存在实现火灾的早期预警。 5NBIOT通信模组 - BC26 负责将STM32F407处理后的环境监测数据通过NBIOT网络上传至华为云物联网平台。BC26模组支持低功耗、远程连接为系统提供稳定的数据传输通道。 6电源模块 采用USB接口5V供电为整个系统提供稳定可靠的能源。设计中需考虑电源管理以优化系统能耗延长电池续航或确保持续稳定供电。 7蜂鸣器报警模块 高电平触发的有源蜂鸣器当STM32F407检测到环境参数超过设定阈值时通过GPIO输出高电平信号激活蜂鸣器发出报警声音实现本地即时警告。 8OLED显示屏 采用0.96英寸I²C接口OLED显示屏用于实时显示温湿度、烟雾浓度和火光报警等信息。OLED屏具有自发光、视角宽、响应速度快等特点适合在不同光照条件下清晰展示数据。 【4】摘要 本项目设计并实现一款基于STM32F407微控制器、结合NBIOT通信技术与华为云物联网平台的智能环境监测系统。系统整合了SHT30温湿度传感器、MQ2烟雾传感器以及火光检测传感器实现对环境的多维度监控包括温度、湿度、烟雾浓度和火光信息的实时采集。通过OLED显示屏现场展示监测数据并在检测到异常时启动蜂鸣器报警确保即时预警。利用BC26 NBIOT模块系统将监测数据远程传输至华为云物联网平台借助云平台的强大数据处理能力实现数据的远程访问、存储与分析。此外项目还开发了基于Qt框架的Android手机APP方便用户通过移动设备远程查看实时环境数据及历史记录提升环境管理的便捷性和效率。本系统有效融合了物联网、云计算与移动应用技术为环境保护、火灾预防等应用场景提供了智能化解决方案。 关键字 STM32F407NBIOT通信华为云物联网平台环境监测系统温湿度传感器(SHT30)烟雾传感器(MQ2)火光检测OLED显示屏Qt/C移动应用开发智能预警系统 1.2 设计思路 1模块化设计 将系统划分为多个独立但相互协作的模块包括数据采集模块温湿度、烟雾、火光、数据处理与控制模块STM32F407、本地显示模块OLED、远程通信模块NBIOT BC26、报警模块蜂鸣器和移动应用模块Android APP。这种设计便于系统维护、升级和故障排查同时也利于模块复用和扩展新功能。 2高效数据采集与处理 选用高精度的SHT30温湿度传感器和灵敏的MQ2烟雾传感器结合火光检测传感器确保数据采集的准确性。STM32F407作为主控芯片利用其强大计算能力和丰富的外设接口负责实时处理采集数据执行逻辑判断控制报警与显示。 3低功耗远程通信策略 采用NBIOT技术通过BC26模组实现数据的远程传输看重其在低功耗、广覆盖方面的优势特别适合于长时间运行、部署位置偏远的环境监测设备确保数据传输的稳定性和经济性。 4云端数据管理与分析 利用华为云物联网平台强大的数据处理能力实现数据的远程存储、实时分析与可视化展示为用户提供历史数据查询、趋势分析等功能同时支持设置报警规则通过云端平台实现对多个监测点的集中管理和远程监控。 5移动终端交互体验优化 开发基于Qt的Android手机APP注重用户体验设计提供简洁直观的操作界面让用户能够随时随地查看环境监测数据接收报警通知甚至进行远程配置和控制提升系统的实用性和用户参与度。 1.3 系统功能总结 功能模块具体功能描述数据采集- 使用SHT30温湿度传感器实时监测并采集环境温度与湿度数据。- 利用MQ2烟雾传感器监测烟雾浓度支持多种气体检测。- 火光检测传感器对环境中的火光或强光源进行实时监测。数据处理与控制- STM32F407微控制器负责数据处理、逻辑判断及系统控制。- 实现数据阈值判断当检测值超限时触发报警机制。本地显示- 通过0.96寸OLED显示屏实时展示温湿度、烟雾浓度、火光报警信息。远程通信- BC26 NBIOT模块实现与华为云物联网平台的数据上传。云端服务- 华为云物联网平台存储、处理接收到的环境数据。- 支持数据的历史记录查询、统计分析与可视化展示。移动端监控- Qt开发的Android手机APP远程查看实时环境监测数据。- 显示温度、湿度、烟雾浓度报警状态及火光报警信息。- 用户可设置报警阈值、查看历史记录等。安全与可靠性- 数据传输采用加密技术保障云端数据安全。- 设备内置错误处理与恢复机制提高系统稳定性。可扩展性- 系统设计预留接口支持未来接入更多类型传感器。- 通信方式和技术框架易于升级以适应技术发展和应用需求变化。 1.4 开发工具的选择 【1】设备端开发 STM32的编程语言选择C语言C语言执行效率高大学里主学的C语言C语言编译出来的可执行文件最接近于机器码汇编语言执行效率最高但是汇编的移植性比较差目前在一些操作系统内核里还有一些低配的单片机使用的较多平常的单片机编程还是以C语言为主。C语言的执行效率仅次于汇编语法理解简单、代码通用性强也支持跨平台在嵌入式底层、单片机编程里用的非常多当前的设计就是采用C语言开发。 开发工具选择Keilkeil是一家世界领先的嵌入式微控制器软件开发商在2015年keil被ARM公司收购。因为当前芯片选择的是STM32F103系列STMF103是属于ARM公司的芯片构架、Cortex-M3内核系列的芯片所以使用Kile来开发STM32是有先天优势的而keil在各大高校使用的也非常多很多教科书里都是以keil来教学开发51单片机、STM32单片机等等。目前作为MCU芯片开发的软件也不只是keil一家独大IAR在MCU微处理器开发领域里也使用的非常多IAR扩展性更强也支持STM32开发也支持其他芯片比如CC2530,51单片机的开发。从软件的使用上来讲IAR比keil更加简洁功能相对少一些。如果之前使用过keil而且使用频率较多已经习惯再使用IAR是有点不适应界面的。 【2】上位机开发 上位机的开发选择Qt框架编程语言采用CQt是一个1991年由Qt Company开发的跨平台C图形用户界面应用程序开发框架。它既可以开发GUI程序也可用于开发非GUI程序比如控制台工具和服务器。Qt是面向对象的框架使用特殊的代码生成扩展称为元对象编译器(Meta Object Compiler, moc)以及一些宏Qt很容易扩展并且允许真正地组件编程。Qt能轻松创建具有原生C性能的连接设备、用户界面UI和应用程序。它功能强大且结构紧凑拥有直观的工具和库。 二、硬件选型 2.1 STM32F407系统板 链接https://item.taobao.com/item.htm?spma21n57.1.item.6.3406523cr317uxpriceTId213e38bb17188687576681904e683butparam%7B%22aplus_abtest%22:%22781d5aaa75dd4af6ad2408d4a62768ea%22%7Did560814289385ns1abbucket12skuId4346181285287 2.2 杜邦线2排 作用 连接模块与单片机。 链接https://detail.tmall.com/item.htm?ali_refida3_430582_1006:1104520036:N:MsF9mE9KLTC2IibWJh%20K1A:adaa6d3d7abe6f1f07b87a36416ee4fbali_trackid1_adaa6d3d7abe6f1f07b87a36416ee4fbid14466195609skuId3108214440215spma230r.1.14.1 2.3 SHT30温湿度模块 链接 https://detail.tmall.com/item.htm?abbucket8id624272456739ns1skuId4420709624009spma21n57.1.item.4.5097523cBtlCji 2.4 OLED显示屏4线IIC接口 链接https://item.taobao.com/item.htm?spma21n57.1.0.0.2ad7523cyZF6lCid43639171586ns1abbucket18#detail 2.5 MQ2 烟雾传感器 链接https://detail.tmall.com/item.htm?abbucket5id17949567819ns1spma21n57.1.0.0.242b523cwrRqcBskuId4078848750990 2.6 火焰检测模块 1、可以检测火焰或者波长在760纳米1100纳米范围内的光源打火机测试火焰距离为80cm对火焰越大测试距离越远 2、探测角度60度左右,对火焰光谱特别灵敏3、灵敏度可调图中蓝色数字电位器调节) 4、比较器输出,信号干净,波形好,驱动能力强,超过15mA 5、配可调精密电位器调节灵敏度 6、工作电压3.3V-5V 7、输出形式do数字开关量输出(o和1)和ao模拟电压输出 链接https://detail.tmall.com/item.htm?abbucket12id41197526279ns1spma230r.1.14.13.82631c79yq9mvAskuId3954176793928 2.7 电源扩展接口(x2) 买电源扩展板方便扩展5v电源 和 3.3V电源。 链接https://item.taobao.com/item.htm?id647681090119skuId4672158745999spma1z0d.6639537/tb.1997196601.4.754374841n18eN 2.8 蜂鸣器模块 链接https://detail.tmall.com/item.htm?ali_refida3_430582_1006:1104520036:N:X/YIdD%20/nzZWyWHIKhozj3ahdFvQYGOd:09a834d50903c653d8893f1f618eb321ali_trackid1_09a834d50903c653d8893f1f618eb321id21124132861spma230r.1.14.1skuId4319138558993 2.9 NBIOT模块 链接https://item.taobao.com/item.htm?abbucket3id583282366803ns1skuId4749833023376spma21n57.1.item.3.1ed9523cnUBQwb 三、部署华为云物联网平台 华为云官网: https://www.huaweicloud.com/ 打开官网搜索物联网就能快速找到 设备接入IoTDA。 3.1 物联网平台介绍 华为云物联网平台IoT 设备接入云服务提供海量设备的接入和管理能力将物理设备联接到云支撑设备数据采集上云和云端下发命令给设备进行远程控制配合华为云其他产品帮助我们快速构筑物联网解决方案。 使用物联网平台构建一个完整的物联网解决方案主要包括3部分物联网平台、业务应用和设备。 物联网平台作为连接业务应用和设备的中间层屏蔽了各种复杂的设备接口实现设备的快速接入同时提供强大的开放能力支撑行业用户构建各种物联网解决方案。 设备可以通过固网、2G/3G/4G/5G、NB-IoT、Wifi等多种网络接入物联网平台并使用LWM2M/CoAP、MQTT、HTTPS协议将业务数据上报到平台平台也可以将控制命令下发给设备。 业务应用通过调用物联网平台提供的API实现设备数据采集、命令下发、设备管理等业务场景。 3.2 开通物联网服务 地址 https://www.huaweicloud.com/product/iothub.html 点击立即创建。 正在创建标准版实例需要等待片刻。 创建完成之后点击实例名称。 可以看到标准版实例的设备接入端口和地址。 在上面也能看到 免费单元的限制。 开通之后点击总览也能查看接入信息。 我们当前设备准备采用MQTT协议接入华为云平台这里可以看到MQTT协议的地址和端口号等信息。 总结: 端口号 MQTT (1883)| MQTTS (8883) 接入地址ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com**根据域名地址得到IP地址信息: ** 打开Windows电脑的命令行控制台终端使用ping 命令。ping一下即可。 Microsoft Windows [版本 10.0.19045.4170] (c) Microsoft Corporation。保留所有权利。C:\Users\11266ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com正在 Ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com [117.78.5.125] 具有 32 字节的数据: 来自 117.78.5.125 的回复: 字节32 时间35ms TTL93 来自 117.78.5.125 的回复: 字节32 时间36ms TTL93 来自 117.78.5.125 的回复: 字节32 时间36ms TTL93 来自 117.78.5.125 的回复: 字节32 时间39ms TTL93117.78.5.125 的 Ping 统计信息:数据包: 已发送 4已接收 4丢失 0 (0% 丢失) 往返行程的估计时间(以毫秒为单位):最短 35ms最长 39ms平均 36msC:\Users\11266MQTT协议接入端口号有两个1883是非加密端口8883是证书加密端口单片机无法加载证书所以使用1883端口比较合适。 接下来的ESP8266就采用1883端口连接华为云物联网平台。 3.3 创建产品 1创建产品 2填写产品信息 根据自己产品名字填写下面的设备类型选择自定义类型。 3产品创建成功 创建完成之后点击查看详情。 4添加自定义模型 产品创建完成之后点击进入产品详情页面翻到最下面可以看到模型定义。 模型简单来说 就是存放设备上传到云平台的数据。 你可以根据自己的产品进行创建。 比如 烟雾可以叫 MQ2 温度可以叫 Temperature 湿度可以叫 humidity 火焰可以叫 flame 其他的传感器自己用单词简写命名即可。 这就是你的单片机设备端上传到服务器的数据名字。先点击自定义模型。 再创建一个服务ID。 接着点击新增属性。 3.4 添加设备 产品是属于上层的抽象模型接下来在产品模型下添加实际的设备。添加的设备最终需要与真实的设备关联在一起完成数据交互。 1注册设备 2根据自己的设备填写 3保存设备信息 创建完毕之后点击保存并关闭得到创建的设备密匙信息。该信息在后续生成MQTT三元组的时候需要使用。 4设备创建完成 5设备详情 3.5 MQTT协议主题订阅与发布 1MQTT协议介绍 当前的设备是采用MQTT协议与华为云平台进行通信。 MQTT是一个物联网传输协议它被设计用于轻量级的发布/订阅式消息传输旨在为低带宽和不稳定的网络环境中的物联网设备提供可靠的网络服务。MQTT是专门针对物联网开发的轻量级传输协议。MQTT协议针对低带宽网络低计算能力的设备做了特殊的优化使得其能适应各种物联网应用场景。目前MQTT拥有各种平台和设备上的客户端已经形成了初步的生态系统。 MQTT是一种消息队列协议使用发布/订阅消息模式提供一对多的消息发布解除应用程序耦合相对于其他协议开发更简单MQTT协议是工作在TCP/IP协议上由TCP/IP协议提供稳定的网络连接所以只要具备TCP协议栈的网络设备都可以使用MQTT协议。 本次设备采用的ESP8266就具备TCP协议栈能够建立TCP连接所以配合STM32代码里封装的MQTT协议就可以与华为云平台完成通信。 华为云的MQTT协议接入帮助文档在这里: https://support.huaweicloud.com/devg-iothub/iot_02_2200.html 业务流程 2华为云平台MQTT协议使用限制 描述限制支持的MQTT协议版本3.1.1与标准MQTT协议的区别支持Qos 0和Qos 1支持Topic自定义不支持QoS2不支持will、retain msgMQTTS支持的安全等级采用TCP通道基础 TLS协议最高TLSv1.3版本单帐号每秒最大MQTT连接请求数无限制单个设备每分钟支持的最大MQTT连接数1单个MQTT连接每秒的吞吐量即带宽包含直连设备和网关3KB/sMQTT单个发布消息最大长度超过此大小的发布请求将被直接拒绝1MBMQTT连接心跳时间建议值心跳时间限定为30至1200秒推荐设置为120秒产品是否支持自定义Topic支持消息发布与订阅设备只能对自己的Topic进行消息发布与订阅每个订阅请求的最大订阅数无限制 3主题订阅格式 帮助文档地址https://support.huaweicloud.com/devg-iothub/iot_02_2200.html 对于设备而言一般会订阅平台下发消息给设备 这个主题。 设备想接收平台下发的消息就需要订阅平台下发消息给设备 的主题订阅后平台下发消息给设备设备就会收到消息。 如果设备想要知道平台下发的消息需要订阅上面图片里标注的主题。 以当前设备为例最终订阅主题的格式如下: $oc/devices/{device_id}/sys/messages/down最终的格式: $oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down4主题发布格式 对于设备来说主题发布表示向云平台上传数据将最新的传感器数据设备状态上传到云平台。 这个操作称为属性上报。 帮助文档地址https://support.huaweicloud.com/usermanual-iothub/iot_06_v5_3010.html 根据帮助文档的介绍 当前设备发布主题上报属性的格式总结如下 发布的主题格式: $oc/devices/{device_id}/sys/properties/report最终的格式: $oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report 发布主题时需要上传数据这个数据格式是JSON格式。上传的JSON数据格式如下:{services: [{service_id: 填服务ID,properties: {填属性名称1: 填属性值,填属性名称2: 填属性值,..........}}] } 根据JSON格式一次可以上传多个属性字段。 这个JSON格式里的服务ID属性字段名称属性值类型在前面创建产品的时候就已经介绍了不记得可以翻到前面去查看。根据这个格式组合一次上传的属性数据: {services: [{service_id: stm32,properties:{DHT11_T:30,DHT11_H:10,BH1750:1,MQ135:0}}]}3.6 MQTT三元组 MQTT协议登录需要填用户ID设备ID设备密码等信息就像我们平时登录QQ微信一样要输入账号密码才能登录。MQTT协议登录的这3个参数一般称为MQTT三元组。 接下来介绍华为云平台的MQTT三元组参数如何得到。 1MQTT服务器地址 要登录MQTT服务器首先记得先知道服务器的地址是多少端口是多少。 帮助文档地址https://console.huaweicloud.com/iotdm/?regioncn-north-4#/dm-portal/home MQTT协议的端口支持1883和8883它们的区别是8883 是加密端口更加安全。但是单片机上使用比较困难所以当前的设备是采用1883端口进连接的。 根据上面的域名和端口号得到下面的IP地址和端口号信息 如果设备支持填写域名可以直接填域名不支持就直接填写IP地址。 IP地址就是域名解析得到的 华为云的MQTT服务器地址117.78.5.125 华为云的MQTT端口号1883如何得到IP地址如何域名转IP 打开Windows的命令行输入以下命令。 ping ad635970a1.st1.iotda-device.cn-north-4.myhuaweicloud.com2生成MQTT三元组 华为云提供了一个在线工具用来生成MQTT鉴权三元组 https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/ 打开这个工具填入设备的信息也就是刚才创建完设备之后保存的信息点击生成就可以得到MQTT的登录信息了。 下面是打开的页面 填入设备的信息 上面两行就是设备创建完成之后保存得到的 直接得到三元组信息。 得到三元组之后设备端通过MQTT协议登录鉴权的时候填入参数即可。 ClientId 663cb18871d845632a0912e7_dev1_0_0_2024050911 Username 663cb18871d845632a0912e7_dev1 Password 71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac2373.7 模拟设备登录测试 经过上面的步骤介绍已经创建了产品设备数据模型得到MQTT登录信息。 接下来就用MQTT客户端软件模拟真实的设备来登录平台。测试与服务器通信是否正常。 1填入登录信息 打开MQTT客户端软件对号填入相关信息就是上面的文本介绍。然后点击登录订阅主题发布主题。 2打开网页查看 完成上面的操作之后打开华为云网页后台可以看到设备已经在线了。 点击详情页面可以看到上传的数据 到此云平台的部署已经完成设备已经可以正常上传数据了。 3MQTT登录测试参数总结 MQTT服务器: 117.78.5.125 MQTT端口号: 183//物联网服务器的设备信息 #define MQTT_ClientID 663cb18871d845632a0912e7_dev1_0_0_2024050911 #define MQTT_UserName 663cb18871d845632a0912e7_dev1 #define MQTT_PassWord 71b82deae83e80f04c4269b5bbce3b2fc7c13f610948fe210ce18650909ac237//订阅与发布的主题 #define SET_TOPIC $oc/devices/663cb18871d845632a0912e7_dev1/sys/messages/down //订阅 #define POST_TOPIC $oc/devices/663cb18871d845632a0912e7_dev1/sys/properties/report //发布发布的数据: {services: [{service_id: stm32,properties:{DHT11_T:30,DHT11_H:10,BH1750:1,MQ135:0}}]} 3.8 创建IAM账户 创建一个IAM账户因为接下来开发上位机需要使用云平台的API接口这些接口都需要token进行鉴权。简单来说就是身份的认证。 调用接口获取Token时就需要填写IAM账号信息。所以接下来演示一下过程。 地址: https://console.huaweicloud.com/iam/?regioncn-north-4#/iam/users **【1】获取项目凭证 ** 点击左上角用户名选择下拉菜单里的我的凭证 项目凭证: 28add376c01e4a61ac8b621c714bf459【2】创建IAM用户 鼠标放在左上角头像上在下拉菜单里选择统一身份认证。 点击左上角创建用户。 创建成功 【3】创建完成 用户信息如下 主用户名 l19504562721 IAM用户 ds_abc 密码 DS123456783.9 获取影子数据 帮助文档https://support.huaweicloud.com/api-iothub/iot_06_v5_0079.html 设备影子介绍 设备影子是一个用于存储和检索设备当前状态信息的JSON文档。 每个设备有且只有一个设备影子由设备ID唯一标识 设备影子仅保存最近一次设备的上报数据和预期数据 无论该设备是否在线都可以通过该影子获取和设置设备的属性简单来说设备影子就是保存设备最新上传的一次数据。 我们设计的软件里如果想要获取设备的最新状态信息就采用设备影子接口。 如果对接口不熟悉可以先进行在线调试https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?productIoTDAapiShowDeviceShadow 在线调试接口可以请求影子接口了解请求与返回的数据格式。 调试完成看右下角的响应体就是返回的影子数据。 设备影子接口返回的数据如下 {device_id: 663cb18871d845632a0912e7_dev1,shadow: [{service_id: stm32,desired: {properties: null,event_time: null},reported: {properties: {DHT11_T: 18,DHT11_H: 90,BH1750: 38,MQ135: 70},event_time: 20240509T113448Z},version: 3}] }调试成功之后可以得到访问影子数据的真实链接接下来的代码开发中就采用Qt写代码访问此链接获取影子数据完成上位机开发。 链接如下 https://ad635970a1.st1.iotda-app.cn-north-4.myhuaweicloud.com:443/v5/iot/28add376c01e4a61ac8b621c714bf459/devices/663cb18871d845632a0912e7_dev1/shadow四、STM32设备端代码设计 4.1 BC26-NBIOT配置代码 #include ec20.h #include stdlib.h #include string.h #include usart.h #include iwdg.hint errcount 0; char atstr[BUFLEN]; char AtStrBuf[BUFLEN]; char *strx,*extstrx,*Readystrx; extern char AtRxBuffer[512],Rxcouter; char GPRMCSTR[128]; //转载GPS信息 GPRMC 经纬度存储的字符串 char GPRMCSTRLON[64]; //经度存储字符串 也就是119.20694 char GPRMCSTRLAT[64]; //维度存储字符串也就是26.06451 char IMEINUMBER[64];//CGSN: 869523052178994 //下面是纠正火星坐标的变量定义/ int Get_GPSdata(void); void Getdata_Change(char status);typedef struct { char UtcDate[6]; char longitude[11];//经度原数据 char Latitude[10];//纬度源数据 char longitudess[4];//整数部分 char Latitudess[3]; char longitudedd[8];//小数点部分 char Latitudedd[8]; char Truelongitude[12];//转换过数据 char TrueLatitude[11];//转换过数据 char getstautus;//获取到定位的标志状态 float gpsdata[2]; }LongLatidata; LongLatidata latdata;float tempdata[2]; char latStrAF[64]; //存放数据经纬度用来发送 char lonStrAF[64]; //存放数据经纬度用来显示 //火星纠偏结束///只要修改三要素/ #define PRODUCEKEY 6402ac07352830580e48ff7b_dev1_0_0_2023030403 //设备ID #define DEVICENAME 6402ac07352830580e48ff7b_dev1 //用户名 #define DEVICESECRET 517f1c8f18d6b7b2e4c134653dc892edd38c3e86153506df57f7c296d13b37f7 //密码void Clear_Buffer(void)//清空缓存 {u8 i;NBIOTSend_RecAccessMode();printf(AtRxBuffer);for(i0;iRxcouter;i)AtRxBuffer[i]0;//缓存Rxcouter0;}//初始化模块 void NBIOT_Init(void) {Uart2_SendStr(AT\r\n);delay_ms(500);strxstrstr((const char*)AtRxBuffer,(const char*)OK);//返回OKerrcount 0;while(strxNULL){errcount;printf(\r\n单片机正在连接到模块...\r\n);Clear_Buffer();Uart2_SendStr(AT\r\n);delay_ms(500);strxstrstr((const char*)AtRxBuffer,(const char*)OK);//返回OKif(errcount50) //防止死循环{errcount 0;reset_4g();__set_FAULTMASK(1); //关闭总中断NVIC_SystemReset(); //请求单片机重启break;}}Uart2_SendStr(ATE1\r\n); //回显delay_ms(500);Clear_Buffer();/Uart2_SendStr(ATCPIN?\r\n);//检查SIM卡是否在位delay_ms(500);strxstrstr((const char*)AtRxBuffer,(const char*)CPIN: READY);//查看是否返回readywhile(strxNULL){Clear_Buffer();Uart2_SendStr(ATCPIN?\r\n);delay_ms(500);strxstrstr((const char*)AtRxBuffer,(const char*)CPIN: READY);//检查SIM卡是否在位等待卡在位如果卡识别不到剩余的工作就没法做了}Clear_Buffer();///Uart2_SendStr(ATCSQ\r\n); //检查CSQdelay_ms(500);Clear_Buffer();Uart2_SendStr(ATI\r\n); //检查模块的版本号delay_ms(500);Clear_Buffer();///Uart2_SendStr(ATCREG?\r\n);//查看是否注册GSM网络delay_ms(500);Clear_Buffer();Uart2_SendStr(ATCEREG?\r\n);//查看注册到哪个运营商支持移动 联通 电信delay_ms(500);Clear_Buffer();Uart2_SendStr(ATCIMI\r\n);//获取卡号类似是否存在卡的意思比较重要。delay_ms(1000);strxstrstr((const char*)AtRxBuffer,(const char*)OK);//只要卡不错误 基本就成功if(strx){printf(\r\n我的卡号是 : %s \r\n\r\n,AtRxBuffer);delay_ms(1000);Clear_Buffer();}else{// printf(卡错误 : %s \r\n,AtRxBuffer);delay_ms(300);Clear_Buffer();}Clear_Buffer();Uart2_SendStr(ATCGSN\r\n);//激活网络PDPdelay_ms(300);strxstrstr((const char*)AtRxBuffer,(const char*)OK);//返OKClear_Buffer();Uart2_SendStr(ATCGATT?\r\n);//查询激活状态delay_ms(300);strxstrstr((const char*)AtRxBuffer,(const char*)CGATT: 1);//返1 表明激活成功 获取到IP地址了Clear_Buffer();errcount 0;while(strxNULL){errcount;Clear_Buffer();Uart2_SendStr(ATCGATT?\r\n);//获取激活状态delay_ms(300);strxstrstr((const char*)AtRxBuffer,(const char*)CGATT: 1);//返回1,表明注网成功if(errcount100) //防止死循环{errcount 0;reset_4g();__set_FAULTMASK(1); //关闭总中断NVIC_SystemReset(); //请求单片机重启break;}}Uart2_SendStr(ATQCCID\r\n);//获取当前卡的IP地址delay_ms(500);Clear_Buffer(); }void Start_GPS(void) {Clear_Buffer(); Uart2_SendStr(ATQGPS1\r\n);//查询激活状态delay_ms(300);strxstrstr((const char*)AtStrBuf,(const char*)OK);//返1if(strxNULL){//__set_FAULTMASK(1);//NVIC_SystemReset(); //超时重启delay_ms(300);}Clear_Buffer(); } //获取定位数据//* ATQGPSGNMEARMCQGPSGNMEA: $GNRMC,035645.00,A,2603.9111,N,11912.4140,E,0.336,,140821,,,A,V*19OK ATQGPSGNMEARMCQGPSGNMEA: $GPRMC,145620.00,A,2603.972207,N,11912.411739,E,0.0,0.0,171022,3.5,W,A*2F*/char *Get_GPS_RMC(char type) {Clear_Buffer(); memset(GPRMCSTR,0,128);Uart2_SendStr(ATQGPSGNMEA\RMC\\r\n);//查询激活状态delay_ms(300);strxstrstr((const char*)AtRxBuffer,(const char*)$GPRMC);//返1while(strxNULL){Clear_Buffer(); Uart2_SendStr(ATQGPSGNMEA\RMC\\r\n);//获取激活状态delay_ms(300);strxstrstr((const char*)AtRxBuffer,(const char*)$GPRMC);//返回1,表明注网成功}sprintf(GPRMCSTR,%s,strx);Clear_Buffer(); //打印收到的GPS信息GPRMCSTR[2] P;//printf(GETGPRMC\r\n%s,GPRMCSTR); //打印GPRMCif(GPRMCSTR[17]A){memset(latStrAF,0,64);memset(lonStrAF,0,64);Get_GPSdata();if(type1)return latStrAF;if(type2)return lonStrAF;}return 0; }/***************************************************** 下面是矫正火星坐标的 *****************************************************///解GPS析函数 //$GPRMC,134952.00,A,2603.9576,N,11912.4098,E,0.154,,280821,,,A,V*18 int Get_GPSdata() {int i0;strxstrstr((const char*)GPRMCSTR,(const char*)A,);//获取纬度的位置if(strx){for(i0;i9;i){latdata.Latitude[i]strx[i2];//获取纬度值2603.9576}strxstrstr((const char*)GPRMCSTR,(const char*)N,);//获取经度值if(strx){for(i0;i10;i) //获取经度 11912.4098{latdata.longitude[i]strx[i2];}} printf(latdata.Latitude ,%s \r\n,latdata.Latitude);printf(latdata.longitude ,%s \r\n,latdata.longitude);latdata.getstautus1;// }else{latdata.getstautus0;}Getdata_Change(latdata.getstautus);//数据换算Clear_Buffer();return 0;}/*************解析出经纬度数据,然后直接提交数据*******************/ void Getdata_Change(char status) {unsigned char i; if(status){for(i0;i3;i)latdata.longitudess[i]latdata.longitude[i];for(i3;i10;i)latdata.longitudedd[i-3]latdata.longitude[i];latdata.gpsdata[0](latdata.longitudess[0]-0x30)*100(latdata.longitudess[1]-0x30)*10(latdata.longitudess[2]-0x30)\((latdata.longitudedd[0]-0x30)*10(latdata.longitudedd[1]-0x30)(float)(latdata.longitudedd[3]-0x30)/10\(float)(latdata.longitudedd[4]-0x30)/100(float)(latdata.longitudedd[5]-0x30)/1000(float)(latdata.longitudedd[6]-0x30)/10000)/60.0;//获取完整的数据///for(i0;i2;i)latdata.Latitudess[i]latdata.Latitude[i];for(i2;i9;i)latdata.Latitudedd[i-2]latdata.Latitude[i]; latdata.gpsdata[1](float)(latdata.Latitudess[0]-0x30)*10(latdata.Latitudess[1]-0x30)\((latdata.Latitudedd[0]-0x30)*10(latdata.Latitudedd[1]-0x30)(float)(latdata.Latitudedd[3]-0x30)/10\(float)(latdata.Latitudedd[4]-0x30)/100(float)(latdata.Latitudedd[5]-0x30)/1000(float)(latdata.Latitudedd[6]-0x30)/10000)/60.0;//获取完整的数据bsprintf(latStrAF,%f,latdata.gpsdata[1]);sprintf(lonStrAF,%f,latdata.gpsdata[0]);printf(latStrAF,%s \r\n,latStrAF);printf(lonStrAF,%s \r\n,lonStrAF);}else{latdata.gpsdata[0]0;latdata.gpsdata[1]0;}}/***************************************************** 纠偏结束 *****************************************************//********************************************************************************* ** 函数名称 MakeOnenetPayload(char *Str,u8 Temp,u8 Humi) ** 函数功能 将温度与湿度封装成Onenet有效载荷包 ** 输 入 *str有效载荷保存的目标字符串, ** 输 入 Temp 温度值 ** 输 入 Humi 湿度值 ** 输 出 有效载荷字符串 ** 返 回 有效载荷字符串长度 *********************************************************************************/ char JsonBuf[256];//临时数据缓存 u8 MakeOnenetPayload(u8 *Str,u8 Temp,u8 Humi)//将温度与湿度封装成Onenet有效载荷包 {char Payload[] {\datastreams\:[{\id\:\Temp\,\datapoints\:[{\value\:%d}]},{\id\:\Humi\,\datapoints\:[{\value\:%d}]}]};//onenet有效载荷固定格式unsigned short StrLen;//有效载荷数据长度memset(JsonBuf,0,256);sprintf(JsonBuf,Payload,Temp,Humi);//合成数据有效载荷封装//printf(\r\n有效载荷(%d):[%s]\r\n,strlen(JsonBuf),(char *)JsonBuf);StrLen strlen(JsonBuf)/sizeof(char);//计算有效载荷的数据长度//printf(\r\n有效载荷长度(%d)\r\n,StrLen);Str[0] \x01;//报文第一个字节的固定显示//printf(\r\nStr[0]0X(%02X)\r\n,Str[0]);//报文第2个字节和第三个字节表示有效载荷的长度的固定显示Str[1] (StrLen 0XFF00) 8;//高位//printf(\r\nStr[1]0X(%02X)\r\n,Str[1]);Str[2] StrLen 0XFF;//低位//printf(\r\nStr[2]0X(%02X)\r\n,Str[2]);//拷贝有效载荷数据到Strmemcpy(Str3,JsonBuf,StrLen);//从第三个字节开始拷贝return (StrLen3);//返回长度 }u8 CSTX_4G_MQTT_Senddata(char *data) { u8 JsonLen;//Json包数据长度memset(AtStrBuf,0,BUFLEN);Clear_Buffer();sprintf(AtStrBuf,ATQMTPUB0,0,0,0,\$oc/devices/6402ac07352830580e48ff7b_dev1/sys/properties/report\\r\n);// printf(ATSTR %s \r\n,AtStrBuf);Uart2_SendStr(AtStrBuf);//mqtt提交delay_ms(300);strxstrstr((const char*)AtRxBuffer,(const char*));//准备发送数据errcount0;while(strxNULL){errcount;strxstrstr((const char*)AtRxBuffer,(const char*));//准备发送数据 模块的反馈delay_ms(30);if(errcount10) //超时退出{errcount 0;break;}}Clear_Buffer();USART2_Send((char *)data,strlen(data));//发送json数据UART2_send_byte(0x1A);delay_ms(300);errcount0;strxstrstr((const char*)AtRxBuffer,(const char*)QMTPUB: 0,0,0);//返SEND OK QMTPUB: 0,0,0while(strxNULL){errcount;strxstrstr((const char*)AtRxBuffer,(const char*)QMTPUB: 0,0,0);//返SEND OKdelay_ms(30);if(errcount10) //超时退出{errcount 0;break;}}Clear_Buffer();return 0; }u8 MakeOnenetPayloadGPS(u8* Str,char *latstr,char * lonstr)//将温度与湿度封装成Onenet有效载荷包 {char Payload[] {\datastreams\:[{\id\:\location\,\datapoints\:[{\value\:{\lon\:%s,\lat\:%s}}]}]};//onenet有效载荷固定格式unsigned short StrLen;//有效载荷数据长度memset(JsonBuf,0,256);sprintf(JsonBuf,Payload,lonstr,latstr);//合成数据有效载荷封装printf(JSONEND %s \r\n,JsonBuf);//printf(\r\n有效载荷(%d):[%s]\r\n,strlen(JsonBuf),(char *)JsonBuf);StrLen strlen(JsonBuf)/sizeof(char);//计算有效载荷的数据长度//printf(\r\n有效载荷长度(%d)\r\n,StrLen);Str[0] \x01;//报文第一个字节的固定显示//printf(\r\nStr[0]0X(%02X)\r\n,Str[0]);//报文第2个字节和第三个字节表示有效载荷的长度的固定显示Str[1] (StrLen 0XFF00) 8;//高位//printf(\r\nStr[1]0X(%02X)\r\n,Str[1]);Str[2] StrLen 0XFF;//低位//printf(\r\nStr[2]0X(%02X)\r\n,Str[2]);//拷贝有效载荷数据到Strmemcpy(Str3,JsonBuf,StrLen);//从第三个字节开始拷贝return (StrLen3);//返回长度 }void CSTX_4G_ONENETIOTSenddataGPS(char *latstr,char *lonstr)//上发数据上发的数据跟对应的插件有关系用户需要注意插件然后对应数据即可 { // int JsonLen 0; // memset(AtStrBuf,0,BUFLEN); // // Clear_Buffer(); //发送命令之前清空之前的模块反馈的数据 // sprintf(AtStrBuf,ATQMTPUB0,0,0,0,\$dp\\r\n); //发送ONENET命令 // printf(AtStrBuf %s \r\n,AtStrBuf); // Uart2_SendStr(AtStrBuf);//mqtt提交 // delay_ms(300); // strxstrstr((const char*)AtRxBuffer,(const char*));//模块反馈可以发送数据了 // errcount0; // while(strxNULL) // { // errcount; // strxstrstr((const char*)AtRxBuffer,(const char*));//模块反馈可以发送数据了 // delay_ms(30); // if(errcount100) //防止死循环跳出 // { // errcount 0; // break; // } // } // //命令发送成功下面就去发送数据了 // //Clear_Buffer();// JsonLen MakeOnenetPayloadGPS((u8*)Send_Json,latstr,lonstr); //组建CJSON数据 // USART2_Send((char *)Send_Json,JsonLen);//发送json 数据 // delay_ms(10); // UART2_send_byte(0x1A); // strxstrstr((const char*)AtRxBuffer,(const char*)QMTPUB: 0,0,0);//返发送成功 // errcount0; // while(strxNULL) // { // errcount; // strxstrstr((const char*)AtRxBuffer,(const char*)QMTPUB: 0,0,0);//返发送成功 // delay_ms(10); // if(errcount100) //超时退出死循环 表示服务器连接失败 // { // errcount 0; // break; // } // } // // Clear_Buffer();} 4.2 定时器代码封装 #include timer.h #include led.h//通用定时器3中断初始化 //arr自动重装值。 //psc时钟预分频数 //定时器溢出时间计算方法:Tout((arr1)*(psc1))/Ft us. //Ft定时器工作频率,单位:Mhz //这里使用的是定时器3! void TIM3_Int_Init(u16 arr,u16 psc) {TIM_TimeBaseInitTypeDef TIM_TimeBaseInitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3,ENABLE); ///使能TIM3时钟TIM_TimeBaseInitStructure.TIM_Period arr; //自动重装载值TIM_TimeBaseInitStructure.TIM_Prescalerpsc; //定时器分频TIM_TimeBaseInitStructure.TIM_CounterModeTIM_CounterMode_Up; //向上计数模式TIM_TimeBaseInitStructure.TIM_ClockDivisionTIM_CKD_DIV1; TIM_TimeBaseInit(TIM3,TIM_TimeBaseInitStructure);//初始化TIM3TIM_ITConfig(TIM3,TIM_IT_Update,ENABLE); //允许定时器3更新中断TIM_Cmd(TIM3,ENABLE); //使能定时器3NVIC_InitStructure.NVIC_IRQChannelTIM3_IRQn; //定时器3中断NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority0x01; //抢占优先级1NVIC_InitStructure.NVIC_IRQChannelSubPriority0x03; //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmdENABLE;NVIC_Init(NVIC_InitStructure);} int tnk 0; int timeSend 0; //定时器3中断服务函数 void TIM3_IRQHandler(void) {if(TIM_GetITStatus(TIM3,TIM_IT_Update)SET) //溢出中断{LED1!LED1;//DS1翻转tnk;if(tnk10){timeSend1;tnk 0;}}TIM_ClearITPendingBit(TIM3,TIM_IT_Update); //清除中断标志位 } 4.3 串口配置代码 #include sys.h #include usart.h u8 AtRxBuffer[512],Rxcouter; // //加入以下代码,支持printf函数,而不需要选择use MicroLIB #if 1 #pragma import(__use_no_semihosting) //标准库需要的支持函数 struct __FILE { int handle; }; FILE __stdout; //定义_sys_exit()以避免使用半主机模式 void _sys_exit(int x) { x x; } //重定义fputc函数 int fputc(int ch, FILE *f) { while((USART1-SR0X40)0);//循环发送,直到发送完毕USART1-DR (u8) ch;return ch; } #endif#if EN_USART1_RX //如果使能了接收 //串口1中断服务程序 //注意,读取USARTx-SR能避免莫名其妙的错误 u8 USART_RX_BUF[USART_REC_LEN]; //接收缓冲,最大USART_REC_LEN个字节. //接收状态 //bit15 接收完成标志 //bit14 接收到0x0d //bit13~0 接收到的有效字节数目 u16 USART_RX_STA0; //接收状态标记 //初始化IO 串口1 //bound:波特率 void uart_init(u32 bound){//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);//使能USART1时钟//串口1对应引脚复用映射GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1); //GPIOA9复用为USART1GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1); //GPIOA10复用为USART1//USART1端口配置GPIO_InitStructure.GPIO_Pin GPIO_Pin_9 | GPIO_Pin_10; //GPIOA9与GPIOA10GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF;//复用功能GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //速度50MHzGPIO_InitStructure.GPIO_OType GPIO_OType_PP; //推挽复用输出GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_UP; //上拉GPIO_Init(GPIOA,GPIO_InitStructure); //初始化PA9PA10//USART1 初始化设置USART_InitStructure.USART_BaudRate bound;//波特率设置USART_InitStructure.USART_WordLength USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; //收发模式USART_Init(USART1, USART_InitStructure); //初始化串口1USART_Cmd(USART1, ENABLE); //使能串口1 USART_ClearFlag(USART1, USART_FLAG_TC);#if EN_USART1_RX USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);//开启相关中断//Usart1 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel USART1_IRQn;//串口1中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority3;//抢占优先级3NVIC_InitStructure.NVIC_IRQChannelSubPriority 3; //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; //IRQ通道使能NVIC_Init(NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、#endif} void uart2_init(u32 bound) {//GPIO端口设置GPIO_InitTypeDef GPIO_InitStructure;USART_InitTypeDef USART_InitStructure;NVIC_InitTypeDef NVIC_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA,ENABLE); //使能GPIOA时钟RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);//使能USART2时钟//串口1对应引脚复用映射GPIO_PinAFConfig(GPIOA,GPIO_PinSource2,GPIO_AF_USART2); //GPIOA2复用为USART2GPIO_PinAFConfig(GPIOA,GPIO_PinSource3,GPIO_AF_USART2); //GPIOA3复用为USART2//USART1端口配置GPIO_InitStructure.GPIO_Pin GPIO_Pin_2 | GPIO_Pin_3; //GPIOA2与GPIOA3GPIO_InitStructure.GPIO_Mode GPIO_Mode_AF;//复用功能GPIO_InitStructure.GPIO_Speed GPIO_Speed_50MHz; //速度50MHzGPIO_InitStructure.GPIO_OType GPIO_OType_PP; //推挽复用输出GPIO_InitStructure.GPIO_PuPd GPIO_PuPd_UP; //上拉GPIO_Init(GPIOA,GPIO_InitStructure); //初始化PA2PA3//USART1 初始化设置USART_InitStructure.USART_BaudRate bound;//波特率设置USART_InitStructure.USART_WordLength USART_WordLength_8b;//字长为8位数据格式USART_InitStructure.USART_StopBits USART_StopBits_1;//一个停止位USART_InitStructure.USART_Parity USART_Parity_No;//无奇偶校验位USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None;//无硬件数据流控制USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx; //收发模式USART_Init(USART2, USART_InitStructure); //初始化串口2USART_Cmd(USART2, ENABLE); //使能串口2 USART_ClearFlag(USART2, USART_FLAG_TC);USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);//开启相关中断//Usart2 NVIC 配置NVIC_InitStructure.NVIC_IRQChannel USART2_IRQn;//串口2中断通道NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority1;//抢占优先级1NVIC_InitStructure.NVIC_IRQChannelSubPriority 3; //子优先级3NVIC_InitStructure.NVIC_IRQChannelCmd ENABLE; //IRQ通道使能NVIC_Init(NVIC_InitStructure); //根据指定的参数初始化VIC寄存器、} //配置来对串口2波特率进行修改 和模块通信 void USART_Config(uint32_t baud) { USART_InitTypeDef USART_InitStructure;USART_Cmd(USART2, DISABLE);USART_InitStructure.USART_BaudRate baud;USART_InitStructure.USART_WordLength USART_WordLength_8b;USART_InitStructure.USART_StopBits USART_StopBits_1;USART_InitStructure.USART_Parity USART_Parity_No;USART_InitStructure.USART_HardwareFlowControl USART_HardwareFlowControl_None;USART_InitStructure.USART_Mode USART_Mode_Rx | USART_Mode_Tx;USART_Init(USART2, USART_InitStructure);USART_Cmd(USART2, ENABLE); }//串口1接收中断 void USART1_IRQHandler(void) //串口1中断服务程序 {u8 Res;ResRes;if(USART_GetITStatus(USART1, USART_IT_RXNE) ! RESET) //接收中断{Res USART_ReceiveData(USART1);//(USART1-DR); //读取接收到的数据} } //串口2的接收中断函数 void USART2_IRQHandler(void) //串口2中断服务程序 {u8 Res;if(USART_GetITStatus(USART2, USART_IT_RXNE) ! RESET) //接收中断{Res USART_ReceiveData(USART2);//(USART1-DR); //读取接收到的数据AtRxBuffer[Rxcouter]Res;//} } void UART2_send_byte(char data) {while(USART_GetFlagStatus(USART2, USART_FLAG_TXE) RESET);USART_SendData(USART2, data); }/*-------------------------------------------------*/ /*函数名串口2 发送数组 */ /*参 数bound波特率 */ /*返回值无 */ /*-------------------------------------------------*/ void USART2_Send(char *Data,uint16_t Len) { uint16_t i;for(i0; iLen; i){UART2_send_byte(Data[i]);} }//串口2的发送函数 void Uart2_SendStr(char*SendBuf) //串口2打印数据 {while(*SendBuf){while((USART2-SR0X40)0);//等待发送完成USART2-DR (u8) *SendBuf;SendBuf;} }#endif 五、上位机开发 为了方便查看设备上传的数据接下来利用Qt开发一款Android手机APP 和 Windows上位机。 使用华为云平台提供的API接口获取设备上传的数据进行可视化显示以及远程控制设备。 5.1 Qt开发环境安装 Qt的中文官网 https://www.qt.io/zh-cn/ QT5.12.6的下载地址https://download.qt.io/archive/qt/5.12/5.12.6 打开下载链接后选择下面的版本进行下载 qt-opensource-windows-x86-5.12.6.exe 13-Nov-2019 07:28 3.7G Details 软件安装时断网安装否则会提示输入账户。 安装的时候第一个复选框里勾选一个mingw 32编译器即可其他的不管默认就行直接点击下一步继续安装。 选择MinGW 32-bit 编译器 一定要看清楚了 说明 我这里只是介绍PC端也就是Windows系统下的Qt环境搭建。 Android的开发环境比较麻烦如果想学习Android开发想编译Android程序的APP需要自己去搭建Android环境。 也可以看下面这篇文章不过这个文章是在Qt开发专栏里付费的需要订阅专栏才可以看。 如果不想付费看也可以自行找其他教程自己搭建好必须的环境就行了 Android环境搭建的博客链接 https://blog.csdn.net/xiaolong1126626497/article/details/117254453 5.2 新建上位机工程 前面2讲解了需要用的API接口接下来就使用Qt设计上位机设计界面完成整体上位机的逻辑设计。 【1】新建工程 【2】设置项目的名称。 【3】选择编译系统 【4】选择默认继承的类 【5】选择编译器 【6】点击完成 【7】工程创建完成 5.3 设计UI界面与工程配置 【1】打开UI文件 打开默认的界面如下 【2】开始设计界面 根据自己需求设计界面。 5.5 编译Windows上位机 点击软件左下角的绿色三角形按钮进行编译运行。 编译之后的效果 5.6 配置Android环境 如果想编译Android手机APP必须要先自己配置好自己的Android环境。搭建环境的过程可以自行百度搜索学习 然后才可以进行下面的步骤。 【1】选择Android编译器 【2】创建Android配置文件 创建完成。 【3】配置Android图标与名称 【3】编译Android上位机 Qt本身是跨平台的直接选择Android的编译器就可以将程序编译到Android平台。 然后点击构建。 成功之后在目录下可以看到生成的apk文件也就是Android手机的安装包电脑端使用QQ发送给手机QQ,手机登录QQ接收就能直接安装。 生成的apk的目录在哪里呢 编译完成之后在控制台会输出APK文件的路径。 知道目录在哪里之后在Windows的文件资源管理器里找到路径具体看下图找到生成的apk文件。 D:/linux-share-dir/QT/build-app_Huawei_Eco_tracking-Android_for_arm64_v8a_Clang_Qt_5_12_6_for_Android_ARM64_v8a-Release/android-build//build/outputs/apk/debug/android-build-debug.apk六、 BC26-NBIOT模块调试过程 6.1 模块调试接线 6.2 测试模块 第一步接上之后串口调试助手选择波特率为115200勾选软件上的发送新行选项。发送AT过去正常模块会返回OK。 只有收到了OK才表示模块工作正常。 6.3 上电初始化操作 【1】查询模块是否正常 ATOK【2】获取卡号,查询卡是否插好 ATCIMI460041052911195OK【3】激活网络 ATCGATT1OK【4】获取网络激活状态 ATCGATT?CGATT: 1OK【5】查询网络质量 ATCSQCSQ: 26,0OK【6】 检查网络状态 ATCEREG? // CEREG: 0,1 //找网成功 OK6.4 开启GPS定位 如果需要使用GPS定位就开不需要使用就不用管。 使用GPS定位还需要将模块上的GPS天线接好否则也是没有信号的。 官方文档 【1】激活GPS要等一段时间 ATQGNSSC1OK【2】查询激活状态1表示成功激活 ATQGNSSC?QGNSSC: 1OK【3】获取一次GPS定位语句 ATQGNSSRDNMEA/RMC QGNSSRD: $GNRMC,120715.00,A,3150.78179,N,11711.93433,E,0.000,,310818,,,A,V*19 OK七、总结 基于STM32F407、NBIOT模块BC26和华为云物联网云平台设计的环境检测系统是一个集环境数据采集、本地显示、远程监控和预警功能于一体的综合性系统。该系统通过STM32F407作为主控芯片实现环境参数的采集与处理包括使用SHT30传感器进行温湿度检测MQ2传感器进行烟雾浓度检测以及火焰检测传感器进行火光信息捕获。采集到的数据不仅能在本地通过0.96寸IIC协议OLED显示屏实时显示还能通过NBIOT模块BC26实时上传到华为云物联网云平台实现远程监控和数据存储。 当系统检测到环境中的烟雾浓度、温度或火光超过预设的阈值时会立即触发高电平触发的有源蜂鸣器进行声光报警以提醒用户注意环境安全。这种实时预警功能大大增强了系统的实用性和安全性。 为了使用户能够方便地获取环境检测数据并进行监控系统还开发了基于Qt(C)的Android手机APP。该APP能够从华为云物联网云平台获取设备最新的数据并以直观的方式展示给用户包括温度、湿度、烟雾报警和火光报警等信息。用户无需现场操作即可通过手机APP随时随地了解环境状况极大地提高了系统的便捷性和灵活性。 该环境检测系统通过整合先进的硬件设备和软件技术实现了环境参数的实时监测、数据远程上传和预警功能为用户提供了一个高效、便捷、安全的环境检测解决方案。无论是在家庭、办公室还是工业环境中该系统都具有广泛的应用前景和实用价值。
http://www.eeditor.cn/news/121520/

相关文章:

  • 课题组网站建设网站开发计算机语言的比较
  • 做买家秀的网站站酷网如何接单
  • 前端网站开发实例视频北京想象力网站建设公司
  • 商城网站制作多少钱宁波专业做网站的公司哪家好
  • 免费网站空间可上传网站建站历史查询
  • 深圳网站制作网络建设公司网络广告的类型
  • 深圳做网站外包公司有哪些企业小程序开发公司
  • 文登建设局网站网站建设费 账务处理
  • 做网站属于广告公司吗有效的网站建设
  • 中国建设银行遵义市分行网站网站如何做水晶按钮
  • 雷州网站地方门户系统 哪家好
  • 济南建设网站的公司蓬莱市住房和规划建设管理局网站
  • 购买的网站怎么看网站空间大小wordpress cookies
  • 关于com的网站外贸网站首页
  • 厦门建设与管理局网站wordpress不用缓存
  • 代做土木毕业设计网站网站加产品分类
  • 网站开发课程学习仓储设备东莞网站建设
  • 开发公司工程部经理述职报告做网站优化的话术
  • 房地产电商网站建设上海自贸区注册公司
  • 邯郸公司做网站如何创建wordpress数据库
  • 相亲网站什么叫网落营销
  • 用vps建网站备案长沙企业网站seo
  • 河南联通 网站备案商标设计怎么收费
  • 王建设个人网站数字营销是什么专业
  • 网站访问量统计工具做交通锁具网站碟刹锁
  • 请上传网站应用水印图片光伏电站建设的行业网站
  • 辽阳县住房和城乡建设局网站投资管理公司注册条件和要求
  • wordpress加关键词成都seo整站
  • 做网站的的广告词做影视网站违法不
  • 网站建设公司推荐乐云seowordpress 手机 自适应