• 方案介紹
    • 一、項(xiàng)目介紹
    • 二、設(shè)計(jì)思路總結(jié)
    • 三、部署華為云物聯(lián)網(wǎng)平臺
    • 四、上位機(jī)開發(fā)
    • 五、代碼實(shí)現(xiàn)
  • 附件下載
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

基于STM32+華為云IOT設(shè)計(jì)的智能衣柜

12小時(shí)前
307
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點(diǎn)資訊討論

更多詳細(xì)資料請聯(lián)系.docx

共1個(gè)文件

一、項(xiàng)目介紹

隨著智能家居的發(fā)展,人們對于家居設(shè)備的智能化遠(yuǎn)程控制需求越來越高。智能衣柜作為智能家居的一部分,可以提供衣物存儲和保護(hù)的功能,并通過傳感器互聯(lián)網(wǎng)技術(shù)實(shí)現(xiàn)對衣柜內(nèi)部環(huán)境的監(jiān)測和控制,為用戶提供更好的使用體驗(yàn)。

本項(xiàng)目基于STM32F103ZET6主控芯片設(shè)計(jì)了一個(gè)智能衣柜系統(tǒng),主要功能包括溫度和濕度的監(jiān)測以及烘干控制。為了實(shí)現(xiàn)溫濕度的監(jiān)測,采用了DHT11傳感器,可以準(zhǔn)確地測量環(huán)境的溫度和濕度。通過將傳感器連接到STM32F103ZET6,可以實(shí)時(shí)獲取衣柜內(nèi)部的溫濕度數(shù)據(jù)。

為了實(shí)現(xiàn)烘干功能,系統(tǒng)使用加熱絲和小風(fēng)扇來制造熱氣并循環(huán)衣柜內(nèi)部的空氣,以去除濕氣并防止衣物發(fā)霉。加熱絲的控制采用繼電器來控制加熱絲的通斷,從而控制烘干的開關(guān)。通過與STM32F103ZET6的連接,可以實(shí)現(xiàn)對加熱絲和小風(fēng)扇的控制。

為了實(shí)現(xiàn)遠(yuǎn)程監(jiān)控和控制,系統(tǒng)采用了ESP8266-WIFI模塊將采集到的溫濕度數(shù)據(jù)上傳到華為云物聯(lián)網(wǎng)平臺。用戶可以通過在Android手機(jī)上開發(fā)的Qt應(yīng)用程序遠(yuǎn)程查看衣柜的實(shí)時(shí)溫度和濕度,并設(shè)置濕度閥值。如果濕度超出閥值,系統(tǒng)會通過本地蜂鳴器報(bào)警和手機(jī)APP提示用戶,以防止衣物發(fā)霉。此外,用戶還可以通過手機(jī)APP遠(yuǎn)程控制衣柜的烘干系統(tǒng),去除濕氣,防止衣物發(fā)霉或出現(xiàn)霉味。

整個(gè)系統(tǒng)通過將傳感器、主控芯片、繼電器、ESP8266-WIFI模塊和手機(jī)APP進(jìn)行集成,實(shí)現(xiàn)了智能衣柜的溫濕度監(jiān)測和遠(yuǎn)程控制功能,為用戶提供了便捷、智能的衣物存儲和保護(hù)解決方案。

image-20230728132232626

二、設(shè)計(jì)思路總結(jié)

2.1 硬件選型

在該項(xiàng)目中,以下是一些可能的硬件選型:

【1】主控芯片:STM32F103ZET6,它是一款性能強(qiáng)大的32位ARM Cortex-M3微控制器,具有豐富的外設(shè)和存儲器,適合用作智能衣柜系統(tǒng)的主控芯片。

【2】溫濕度傳感器:DHT11,能夠準(zhǔn)確地測量環(huán)境的溫度和濕度。

【3】網(wǎng)絡(luò)通信模塊:ESP8266-WIFI模塊,可以實(shí)現(xiàn)與互聯(lián)網(wǎng)的連接,用于將采集到的溫濕度數(shù)據(jù)上傳到華為云物聯(lián)網(wǎng)平臺。

【4】繼電器:用于控制加熱絲的通斷,從而控制烘干的開關(guān)。選擇合適的繼電器型號和規(guī)格,以適應(yīng)加熱絲的電流和電壓要求。

【5】蜂鳴器:用于本地報(bào)警,當(dāng)濕度超出閥值時(shí)發(fā)出報(bào)警聲音。

【5】Android手機(jī):作為用戶界面,通過Qt開發(fā)的Android手機(jī)APP實(shí)現(xiàn)遠(yuǎn)程查看和控制衣柜的溫濕度以及烘干系統(tǒng)的開關(guān)控制。

2.2 硬件設(shè)計(jì)

  • 使用STM32F103ZET6作為主控芯片,連接溫濕度傳感器DHT11,繼電器,蜂鳴器和ESP8266-WIFI模塊。
  • 將DHT11傳感器連接到主控芯片的GPIO口,以實(shí)時(shí)獲取衣柜內(nèi)部的溫濕度數(shù)據(jù)。
  • 通過繼電器控制加熱絲的通斷,以控制烘干系統(tǒng)的開關(guān)。
  • 連接蜂鳴器到主控芯片的GPIO口,當(dāng)濕度超出閥值時(shí)發(fā)出報(bào)警聲音。
  • 將ESP8266-WIFI模塊連接到主控芯片的串口,以實(shí)現(xiàn)與華為云物聯(lián)網(wǎng)平臺的通信。

2.3 軟件設(shè)計(jì)

  • 使用STM32的開發(fā)環(huán)境進(jìn)行固件開發(fā),編寫相應(yīng)的代碼來實(shí)現(xiàn)溫濕度傳感器的讀取、繼電器的控制和蜂鳴器的報(bào)警功能。
  • 編寫與ESP8266-WIFI模塊通信的代碼,實(shí)現(xiàn)將采集到的溫濕度數(shù)據(jù)上傳到華為云物聯(lián)網(wǎng)平臺。
  • 在華為云物聯(lián)網(wǎng)平臺上創(chuàng)建相應(yīng)的設(shè)備和數(shù)據(jù)通道,以接收和存儲來自智能衣柜的溫濕度數(shù)據(jù)。
  • 開發(fā)基于Qt的Android手機(jī)APP,通過與華為云物聯(lián)網(wǎng)平臺的接口,實(shí)現(xiàn)遠(yuǎn)程查看衣柜的實(shí)時(shí)溫濕度和控制烘干系統(tǒng)的開關(guān)。
  • 在手機(jī)APP上設(shè)置濕度閥值,當(dāng)濕度超出閥值時(shí),觸發(fā)本地蜂鳴器報(bào)警和手機(jī)APP的提示功能。

2.4 系統(tǒng)交互流程

  • STM32主控芯片讀取DHT11傳感器的溫濕度數(shù)據(jù)。
  • 根據(jù)采集到的數(shù)據(jù),控制繼電器開關(guān)加熱絲和小風(fēng)扇,實(shí)現(xiàn)烘干功能。
  • 將溫濕度數(shù)據(jù)通過ESP8266-WIFI模塊上傳到華為云物聯(lián)網(wǎng)平臺。
  • 用戶通過Qt開發(fā)的Android手機(jī)APP遠(yuǎn)程訪問華為云物聯(lián)網(wǎng)平臺,獲取衣柜的實(shí)時(shí)溫濕度數(shù)據(jù)。
  • 如果濕度超出設(shè)定的閥值,系統(tǒng)發(fā)出本地蜂鳴器報(bào)警和手機(jī)APP的提示,提醒用戶。
  • 用戶可以通過手機(jī)APP遠(yuǎn)程控制烘干系統(tǒng)的開關(guān),去除濕氣,防止衣物發(fā)霉或出現(xiàn)霉味。

通過上述系統(tǒng)設(shè)計(jì)思路,實(shí)現(xiàn)了智能衣柜的溫濕度監(jiān)測和遠(yuǎn)程控制功能,提供了更智能、便捷的衣物存儲和保護(hù)解決方案。

三、部署華為云物聯(lián)網(wǎng)平臺

華為云官網(wǎng): https://www.huaweicloud.com/

打開官網(wǎng),搜索物聯(lián)網(wǎng),就能快速找到 設(shè)備接入IoTDA

image-20221204193824815

3.1 物聯(lián)網(wǎng)平臺介紹

華為云物聯(lián)網(wǎng)平臺(IoT 設(shè)備接入云服務(wù))提供海量設(shè)備的接入和管理能力,將物理設(shè)備聯(lián)接到云,支撐設(shè)備數(shù)據(jù)采集上云和云端下發(fā)命令給設(shè)備進(jìn)行遠(yuǎn)程控制,配合華為云其他產(chǎn)品,幫助我們快速構(gòu)筑物聯(lián)網(wǎng)解決方案。

使用物聯(lián)網(wǎng)平臺構(gòu)建一個(gè)完整的物聯(lián)網(wǎng)解決方案主要包括3部分:物聯(lián)網(wǎng)平臺、業(yè)務(wù)應(yīng)用和設(shè)備。

物聯(lián)網(wǎng)平臺作為連接業(yè)務(wù)應(yīng)用和設(shè)備的中間層,屏蔽了各種復(fù)雜的設(shè)備接口,實(shí)現(xiàn)設(shè)備的快速接入;同時(shí)提供強(qiáng)大的開放能力,支撐行業(yè)用戶構(gòu)建各種物聯(lián)網(wǎng)解決方案。

設(shè)備可以通過固網(wǎng)、2G/3G/4G/5G、NB-IoT、Wifi等多種網(wǎng)絡(luò)接入物聯(lián)網(wǎng)平臺,并使用LWM2M/CoAP、MQTT、HTTPS協(xié)議將業(yè)務(wù)數(shù)據(jù)上報(bào)到平臺,平臺也可以將控制命令下發(fā)給設(shè)備。

業(yè)務(wù)應(yīng)用通過調(diào)用物聯(lián)網(wǎng)平臺提供的API,實(shí)現(xiàn)設(shè)備數(shù)據(jù)采集、命令下發(fā)、設(shè)備管理等業(yè)務(wù)場景。

img

3.2 開通物聯(lián)網(wǎng)服務(wù)

地址: https://www.huaweicloud.com/product/iothub.html

image-20221204194233414

進(jìn)來默認(rèn)會提示開通標(biāo)準(zhǔn)版,在2023的1月1號年之后沒有基礎(chǔ)版了。

image-20230313171325183

開通之后,點(diǎn)擊總覽,查看接入信息。 我們當(dāng)前設(shè)備準(zhǔn)備采用MQTT協(xié)議接入華為云平臺,這里可以看到MQTT協(xié)議的地址和端口號等信息。

總結(jié):

端口號:   MQTT (1883)| MQTTS (8883)   
接入地址: 7445c6bcd3.st1.iotda-app.cn-north-4.myhuaweicloud.com

根據(jù)域名地址得到IP地址信息:

Microsoft Windows [版本 10.0.19044.2728]
(c) Microsoft Corporation。保留所有權(quán)利。

C:Users11266>ping 7445c6bcd3.st1.iotda-device.cn-north-4.myhuaweicloud.com

正在 Ping 7445c6bcd3.st1.iotda-device.cn-north-4.myhuaweicloud.com [117.78.5.125] 具有 32 字節(jié)的數(shù)據(jù):
來自 117.78.5.125 的回復(fù): 字節(jié)=32 時(shí)間=42ms TTL=30
來自 117.78.5.125 的回復(fù): 字節(jié)=32 時(shí)間=35ms TTL=30
來自 117.78.5.125 的回復(fù): 字節(jié)=32 時(shí)間=36ms TTL=30
來自 117.78.5.125 的回復(fù): 字節(jié)=32 時(shí)間=36ms TTL=30

117.78.5.125 的 Ping 統(tǒng)計(jì)信息:
    數(shù)據(jù)包: 已發(fā)送 = 4,已接收 = 4,丟失 = 0 (0% 丟失),
往返行程的估計(jì)時(shí)間(以毫秒為單位):
    最短 = 35ms,最長 = 42ms,平均 = 37ms

C:Users11266>

image-20230321161044723

MQTT協(xié)議接入端口號有兩個(gè),1883是非加密端口,8883是證書加密端口,單片機(jī)無法加載證書,所以使用1883端口比較合適。 接下來的ESP8266就采用1883端口連接華為云物聯(lián)網(wǎng)平臺。

3.3 創(chuàng)建產(chǎn)品

(1)創(chuàng)建產(chǎn)品

點(diǎn)擊產(chǎn)品頁,再點(diǎn)擊左上角創(chuàng)建產(chǎn)品。

image-20230313171503547

(2)填寫產(chǎn)品信息

根據(jù)自己產(chǎn)品名字填寫。

image-20230728130901496

(3)產(chǎn)品創(chuàng)建成功

image-20230728130915809

(4)添加自定義模型

產(chǎn)品創(chuàng)建完成之后,點(diǎn)擊進(jìn)入產(chǎn)品詳情頁面,翻到最下面可以看到模型定義。

先點(diǎn)擊自定義模型。

image-20230313171815860

再創(chuàng)建一個(gè)服務(wù)ID。

接著點(diǎn)擊新增屬性。

3.4 添加設(shè)備

產(chǎn)品是屬于上層的抽象模型,接下來在產(chǎn)品模型下添加實(shí)際的設(shè)備。添加的設(shè)備最終需要與真實(shí)的設(shè)備關(guān)聯(lián)在一起,完成數(shù)據(jù)交互。

(1)注冊設(shè)備

image-20230313173158883

(2)根據(jù)自己的設(shè)備填寫

image-20230728131025569

(3)保存設(shè)備信息

創(chuàng)建完畢之后,點(diǎn)擊保存并關(guān)閉,得到創(chuàng)建的設(shè)備密匙信息。該信息在后續(xù)生成MQTT三元組的時(shí)候需要使用。

image-20230728131051244

(4) 設(shè)備創(chuàng)建完成

image-20230728131104843

3.5 MQTT協(xié)議主題訂閱與發(fā)布

(1)MQTT協(xié)議介紹

當(dāng)前的設(shè)備是采用MQTT協(xié)議與華為云平臺進(jìn)行通信。

MQTT是一個(gè)物聯(lián)網(wǎng)傳輸協(xié)議,它被設(shè)計(jì)用于輕量級的發(fā)布/訂閱式消息傳輸,旨在為低帶寬和不穩(wěn)定的網(wǎng)絡(luò)環(huán)境中的物聯(lián)網(wǎng)設(shè)備提供可靠的網(wǎng)絡(luò)服務(wù)。MQTT是專門針對物聯(lián)網(wǎng)開發(fā)的輕量級傳輸協(xié)議。MQTT協(xié)議針對低帶寬網(wǎng)絡(luò),低計(jì)算能力的設(shè)備,做了特殊的優(yōu)化,使得其能適應(yīng)各種物聯(lián)網(wǎng)應(yīng)用場景。目前MQTT擁有各種平臺和設(shè)備上的客戶端,已經(jīng)形成了初步的生態(tài)系統(tǒng)。

MQTT是一種消息隊(duì)列協(xié)議,使用發(fā)布/訂閱消息模式,提供一對多的消息發(fā)布,解除應(yīng)用程序耦合,相對于其他協(xié)議,開發(fā)更簡單;MQTT協(xié)議是工作在TCP/IP協(xié)議上;由TCP/IP協(xié)議提供穩(wěn)定的網(wǎng)絡(luò)連接;所以,只要具備TCP協(xié)議棧的網(wǎng)絡(luò)設(shè)備都可以使用MQTT協(xié)議。 本次設(shè)備采用的ESP8266就具備TCP協(xié)議棧,能夠建立TCP連接,所以,配合STM32代碼里封裝的MQTT協(xié)議,就可以與華為云平臺完成通信。

華為云的MQTT協(xié)議接入幫助文檔在這里: https://support.huaweicloud.com/devg-iothub/iot_02_2200.html

img

業(yè)務(wù)流程:

img

(2)華為云平臺MQTT協(xié)議使用限制

描述 限制
支持的MQTT協(xié)議版本 3.1.1
與標(biāo)準(zhǔn)MQTT協(xié)議的區(qū)別 支持Qos 0和Qos 1支持Topic自定義不支持QoS2不支持will、retain msg
MQTTS支持的安全等級 采用TCP通道基礎(chǔ) + TLS協(xié)議(最高TLSv1.3版本)
單帳號每秒最大MQTT連接請求數(shù) 無限制
單個(gè)設(shè)備每分鐘支持的最大MQTT連接數(shù) 1
單個(gè)MQTT連接每秒的吞吐量,即帶寬,包含直連設(shè)備和網(wǎng)關(guān) 3KB/s
MQTT單個(gè)發(fā)布消息最大長度,超過此大小的發(fā)布請求將被直接拒絕 1MB
MQTT連接心跳時(shí)間建議值 心跳時(shí)間限定為30至1200秒,推薦設(shè)置為120秒
產(chǎn)品是否支持自定義Topic 支持
消息發(fā)布與訂閱 設(shè)備只能對自己的Topic進(jìn)行消息發(fā)布與訂閱
每個(gè)訂閱請求的最大訂閱數(shù) 無限制

(3)主題訂閱格式

幫助文檔地址:https://support.huaweicloud.com/devg-iothub/iot_02_2200.html

image-20221207153310037

對于設(shè)備而言,一般會訂閱平臺下發(fā)消息給設(shè)備 這個(gè)主題。

設(shè)備想接收平臺下發(fā)的消息,就需要訂閱平臺下發(fā)消息給設(shè)備 的主題,訂閱后,平臺下發(fā)消息給設(shè)備,設(shè)備就會收到消息。

如果設(shè)備想要知道平臺下發(fā)的消息,需要訂閱上面圖片里標(biāo)注的主題。

以當(dāng)前設(shè)備為例,最終訂閱主題的格式如下:
$oc/devices/{device_id}/sys/messages/down

最終的格式:
$oc/devices/6419627e40773741f9fbdac7_dev1/sys/messages/down

?(4)主題發(fā)布格式

對于設(shè)備來說,主題發(fā)布表示向云平臺上傳數(shù)據(jù),將最新的傳感器數(shù)據(jù),設(shè)備狀態(tài)上傳到云平臺。

這個(gè)操作稱為:屬性上報(bào)。

幫助文檔地址:https://support.huaweicloud.com/usermanual-iothub/iot_06_v5_3010.html

image-20221207153637391

根據(jù)幫助文檔的介紹, 當(dāng)前設(shè)備發(fā)布主題,上報(bào)屬性的格式總結(jié)如下:

發(fā)布的主題格式:
$oc/devices/{device_id}/sys/properties/report
 
最終的格式:
$oc/devices/6419627e40773741f9fbdac7_dev1/sys/properties/report
發(fā)布主題時(shí),需要上傳數(shù)據(jù),這個(gè)數(shù)據(jù)格式是JSON格式。

上傳的JSON數(shù)據(jù)格式如下:

{
  "services": [
    {
      "service_id": <填服務(wù)ID>,
      "properties": {
        "<填屬性名稱1>": <填屬性值>,
        "<填屬性名稱2>": <填屬性值>,
        ..........
      }
    }
  ]
}
根據(jù)JSON格式,一次可以上傳多個(gè)屬性字段。 這個(gè)JSON格式里的,服務(wù)ID,屬性字段名稱,屬性值類型,在前面創(chuàng)建產(chǎn)品的時(shí)候就已經(jīng)介紹了,不記得可以翻到前面去查看。

根據(jù)這個(gè)格式,組合一次上傳的屬性數(shù)據(jù):
{"services": [{"service_id": "stm32","properties":{"DS18B20":18,"motor_water":1,"motor_oxygen":1,"temp_max":10,"water_hp":130,"motor_food":0,"time_food":0,"oxygen_food":3}}]}

3.6 MQTT三元組

MQTT協(xié)議登錄需要填用戶ID,設(shè)備ID,設(shè)備密碼等信息,就像我們平時(shí)登錄QQ,微信一樣要輸入賬號密碼才能登錄。MQTT協(xié)議登錄的這3個(gè)參數(shù),一般稱為MQTT三元組。

接下來介紹,華為云平臺的MQTT三元組參數(shù)如何得到。

(1)MQTT服務(wù)器地址

要登錄MQTT服務(wù)器,首先記得先知道服務(wù)器的地址是多少,端口是多少。

幫助文檔地址:https://console.huaweicloud.com/iotdm/?region=cn-north-4#/dm-portal/home

image-20230302135718882

MQTT協(xié)議的端口支持1883和8883,它們的區(qū)別是:8883 是加密端口更加安全。但是單片機(jī)上使用比較困難,所以當(dāng)前的設(shè)備是采用1883端口進(jìn)連接的。

根據(jù)上面的域名和端口號,得到下面的IP地址和端口號信息: 如果設(shè)備支持填寫域名可以直接填域名,不支持就直接填寫IP地址。 (IP地址就是域名解析得到的)

華為云的MQTT服務(wù)器地址:114.116.232.138
域名:7445c6bcd3.st1.iotda-device.cn-north-4.myhuaweicloud.com
華為云的MQTT端口號:1883

(2)生成MQTT三元組

華為云提供了一個(gè)在線工具,用來生成MQTT鑒權(quán)三元組: https://iot-tool.obs-website.cn-north-4.myhuaweicloud.com/

打開這個(gè)工具,填入設(shè)備的信息(也就是剛才創(chuàng)建完設(shè)備之后保存的信息),點(diǎn)擊生成,就可以得到MQTT的登錄信息了。

下面是打開的頁面:

image-20221207154917230

填入設(shè)備的信息: (上面兩行就是設(shè)備創(chuàng)建完成之后保存得到的)

直接得到三元組信息。

image-20230321160708924

image-20230321160718302

得到三元組之后,設(shè)備端通過MQTT協(xié)議登錄鑒權(quán)的時(shí)候,填入?yún)?shù)即可。

ClientId 6419627e40773741f9fbdac7_dev1_0_0_2023032108
Username 6419627e40773741f9fbdac7_dev1
Password 861ac9e6a579d36888b2aaf97714be7af6c77017b017162884592bd68b086a6e

3.7 模擬設(shè)備登錄測試

經(jīng)過上面的步驟介紹,已經(jīng)創(chuàng)建了產(chǎn)品,設(shè)備,數(shù)據(jù)模型,得到MQTT登錄信息。 接下來就用MQTT客戶端軟件模擬真實(shí)的設(shè)備來登錄平臺。測試與服務(wù)器通信是否正常。

(1)填入登錄信息

打開MQTT客戶端軟件,對號填入相關(guān)信息(就是上面的文本介紹)。然后,點(diǎn)擊登錄,訂閱主題,發(fā)布主題。

image-20230321161132971

(2)打開網(wǎng)頁查看

完成上面的操作之后,打開華為云網(wǎng)頁后臺,可以看到設(shè)備已經(jīng)在線了。

點(diǎn)擊詳情頁面,可以看到上傳的數(shù)據(jù)。

到此,云平臺的部署已經(jīng)完成,設(shè)備已經(jīng)可以正常上傳數(shù)據(jù)了。

四、上位機(jī)開發(fā)

為了方便查看設(shè)備上傳的數(shù)據(jù),對設(shè)備進(jìn)行遠(yuǎn)程控制,接下來利用Qt開發(fā)一款A(yù)ndroid和windows系統(tǒng)的上位機(jī)。

使用華為云平臺提供的API接口獲取設(shè)備上傳的數(shù)據(jù),也可以給設(shè)備下發(fā)指令,控制設(shè)備。

為了方便查看設(shè)備上傳的數(shù)據(jù),對設(shè)備進(jìn)行遠(yuǎn)程控制,接下來利用Qt開發(fā)一款A(yù)ndroid和windows系統(tǒng)的上位機(jī)。

使用華為云平臺提供的API接口獲取設(shè)備上傳的數(shù)據(jù),也可以給設(shè)備下發(fā)指令,控制設(shè)備。

4.1 Qt開發(fā)環(huán)境安裝

Qt的中文官網(wǎng): https://www.qt.io/zh-cn/

QT5.12.6的下載地址:https://download.qt.io/archive/qt/5.12/5.12.6

打開下載鏈接后選擇下面的版本進(jìn)行下載:

qt-opensource-windows-x86-5.12.6.exe 13-Nov-2019 07:28 3.7G Details

軟件安裝時(shí)斷網(wǎng)安裝,否則會提示輸入賬戶。

安裝的時(shí)候,第一個(gè)復(fù)選框里勾選一個(gè)mingw 32編譯器即可,其他的不管默認(rèn)就行,直接點(diǎn)擊下一步繼續(xù)安裝。

image-20221203151742653

說明: 我這里只是介紹PC端的環(huán)境搭建(這個(gè)比較簡單)。 Android的開發(fā)環(huán)境比較麻煩,可以去我的博客里看詳細(xì)文章。

選擇MinGW 32-bit 編譯器:

image-20221203151750344

4.2 創(chuàng)建IAM賬戶

創(chuàng)建一個(gè)IAM賬戶,因?yàn)榻酉聛黹_發(fā)上位機(jī),需要使用云平臺的API接口,這些接口都需要token進(jìn)行鑒權(quán)。簡單來說,就是身份的認(rèn)證。 調(diào)用接口獲取Token時(shí),就需要填寫IAM賬號信息。所以,接下來演示一下過程。

地址: https://console.huaweicloud.com/iam/?region=cn-north-4#/iam/users

獲取Token時(shí),除了AIM賬號外,還需要項(xiàng)目憑證:

faa0973835ab409ab48182e2590f4ad3

image-20230321161348409

image-20230321161414487

鼠標(biāo)點(diǎn)擊自己昵稱,點(diǎn)擊統(tǒng)一身份認(rèn)證。

image-20230321161433209

點(diǎn)擊左上角創(chuàng)建用戶。

image-20230321161450557

image-20221207161209880

image-20221207161308917

創(chuàng)建成功:

image-20221212174359962

image-20221212174412097

image-20230321161557848

4.3 獲取影子數(shù)據(jù)

幫助文檔:https://support.huaweicloud.com/api-iothub/iot_06_v5_0079.html

設(shè)備影子介紹:

設(shè)備影子是一個(gè)用于存儲和檢索設(shè)備當(dāng)前狀態(tài)信息的JSON文檔。
每個(gè)設(shè)備有且只有一個(gè)設(shè)備影子,由設(shè)備ID唯一標(biāo)識
設(shè)備影子僅保存最近一次設(shè)備的上報(bào)數(shù)據(jù)和預(yù)期數(shù)據(jù)
無論該設(shè)備是否在線,都可以通過該影子獲取和設(shè)置設(shè)備的屬性

簡單來說:設(shè)備影子就是保存,設(shè)備最新上傳的一次數(shù)據(jù)。

我們設(shè)計(jì)的軟件里,如果想要獲取設(shè)備的最新狀態(tài)信息,就采用設(shè)備影子接口。

如果對接口不熟悉,可以先進(jìn)行在線調(diào)試:https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=ShowDeviceShadow

在線調(diào)試接口,可以請求影子接口,了解請求,與返回的數(shù)據(jù)格式。

image-20230321161636567

image-20230321161701419

設(shè)備影子接口返回的數(shù)據(jù)如下:

{
 "device_id": "6419627e40773741f9fbdac7_dev1",
 "shadow": [
  {
   "service_id": "stm32",
   "desired": {
    "properties": null,
    "event_time": null
   },
   "reported": {
    "properties": {
     "DS18B20": 18,
     "motor_water": 1,
     "motor_oxygen": 1,
     "temp_max": 10,
     "water_hp": 130,
     "motor_food": 0,
     "time_food": 0,
     "oxygen_food": 3
    },
    "event_time": "20230321T081126Z"
   },
   "version": 0
  }
 ]
}

4.4 修改設(shè)備屬性

地址: https://support.huaweicloud.com/api-iothub/iot_06_v5_0034.html

接口說明

設(shè)備的產(chǎn)品模型中定義了物聯(lián)網(wǎng)平臺可向設(shè)備下發(fā)的屬性,應(yīng)用服務(wù)器可調(diào)用此接口向指定設(shè)備下發(fā)屬性。平臺負(fù)責(zé)將屬性以同步方式發(fā)送給設(shè)備,并將設(shè)備執(zhí)行屬性結(jié)果同步返回。

修改設(shè)備屬性的接口,可以讓服務(wù)器給設(shè)備下發(fā)指令,如果需要控制設(shè)備。

在線調(diào)試地址:

https://apiexplorer.developer.huaweicloud.com/apiexplorer/doc?product=IoTDA&api=UpdateProperties

修改設(shè)備屬性是屬于同步命令,需要設(shè)備在線才可以進(jìn)行調(diào)試,先使用MQTT客戶端登錄服務(wù)器,模擬設(shè)備上線。

然后進(jìn)行調(diào)試,測試數(shù)據(jù)遠(yuǎn)程下發(fā)給設(shè)備。

【1】利用MQTT客戶端先登錄設(shè)備 (這是同步命令,必須在線才能調(diào)試)

image-20230321161923007

【2】點(diǎn)擊調(diào)試

{"services":{"temp_max":100}}

【4】可以看到,MQTT客戶端軟件上已經(jīng)收到了服務(wù)器下發(fā)的消息

image-20230313175819901

由于是同步命令,服務(wù)器必須要收到設(shè)備的響應(yīng)才能順利完成一個(gè)流程,設(shè)備響應(yīng)了服務(wù)器才能確定數(shù)據(jù)下發(fā)成功。

MQTT設(shè)備端如何響應(yīng)呢?

設(shè)備響應(yīng)格式說明:https://support.huaweicloud.com/api-iothub/iot_06_v5_3008.html

下面進(jìn)行實(shí)操:

當(dāng)服務(wù)器通過在線調(diào)試,發(fā)送指令下來之后,客戶端將請求ID復(fù)制下來,添加到發(fā)布主題的格式里,再回復(fù)回去,服務(wù)器收到了響應(yīng),一次屬性修改就完美完成了。

image-20230321162053263

就是成功的狀態(tài):

image-20230321162026282

**下面是請求的總結(jié): ** (響應(yīng)服務(wù)器的修改設(shè)備屬性請求)

上報(bào)主題的格式:$oc/devices/{device_id}/sys/properties/set/response/request_id=

$oc/devices/6419627e40773741f9fbdac7_dev1/sys/properties/set/response/request_id=

響應(yīng)的數(shù)據(jù):
{"result_code": 0,"result_desc": "success"}

4.5 設(shè)計(jì)上位機(jī)

前面2講解了需要用的API接口,接下來就使用Qt設(shè)計(jì)上位機(jī),設(shè)計(jì)界面,完成整體上位機(jī)的邏輯設(shè)計(jì)。

【1】新建Qt工程

image-20230302144331541

選擇工程路徑,放在英文路徑下。

image-20230321162532573

 

image-20230313180451177

image-20230313180504518

image-20230321162620141

創(chuàng)建完畢。

新建Android的模板:

 

 

image-20230321162741791

image-20230321162812486

【2】界面設(shè)計(jì)

image-20230728132051169

【4】代碼設(shè)計(jì):配置參數(shù)讀取與保存

/*
功能: 保存數(shù)據(jù)到文件
*/
void Widget::SaveDataToFile(QString text)
{
    /*保存數(shù)據(jù)到文件,方便下次加載*/
    QString file;
    file=QCoreApplication::applicationDirPath()+"/"+ConfigFile;
    QFile filesrc(file);
    filesrc.open(QIODevice::WriteOnly);
    QDataStream out(&filesrc);
    out << text;  //序列化寫字符串
    filesrc.flush();
    filesrc.close();
}


/*
功能: 從文件讀取數(shù)據(jù)
*/
QString Widget::ReadDataFile(void)
{
    //讀取配置文件
    QString text,data;
    text=QCoreApplication::applicationDirPath()+"/"+ConfigFile;

    //判斷文件是否存在
    if(QFile::exists(text))
    {
        QFile filenew(text);
        filenew.open(QIODevice::ReadOnly);
        QDataStream in(&filenew); // 從文件讀取序列化數(shù)據(jù)
        in >> data; //提取寫入的數(shù)據(jù)
        filenew.close();
    }
    return data; //返回值讀取的值
}

【3】代碼設(shè)計(jì):云端數(shù)據(jù)解析

//解析反饋結(jié)果
void Widget::replyFinished(QNetworkReply *reply)
{
    QString displayInfo;

    int statusCode = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();

    //讀取所有數(shù)據(jù)
    QByteArray replyData = reply->readAll();

    qDebug()<<"狀態(tài)碼:"<<statusCode;
    qDebug()<<"反饋的數(shù)據(jù):"<<QString(replyData);

    //更新token
    if(function_select==3)
    {
        displayInfo="token 更新失敗.";
        //讀取HTTP響應(yīng)頭的數(shù)據(jù)
        QList<QNetworkReply::RawHeaderPair> RawHeader=reply->rawHeaderPairs();
        qDebug()<<"HTTP響應(yīng)頭數(shù)量:"<<RawHeader.size();
        for(int i=0;i<RawHeader.size();i++)
        {
            QString first=RawHeader.at(i).first;
            QString second=RawHeader.at(i).second;
            if(first=="X-Subject-Token")
            {
                Token=second.toUtf8();
                displayInfo="token 更新成功.";

                //保存到文件
                SaveDataToFile(Token);
                break;
            }
        }
        QMessageBox::information(this,"提示",displayInfo,QMessageBox::Ok,QMessageBox::Ok);
        return;
    }

    //判斷狀態(tài)碼
    if(200 != statusCode)
    {
        //解析數(shù)據(jù)
        QJsonParseError json_error;
        QJsonDocument document = QJsonDocument::fromJson(replyData, &json_error);
        if(json_error.error == QJsonParseError::NoError)
        {
            //判斷是否是對象,然后開始解析數(shù)據(jù)
            if(document.isObject())
            {
                QString error_str="";
                QJsonObject obj = document.object();
                QString error_code;
                //解析錯(cuò)誤代碼
                if(obj.contains("error_code"))
                {
                    error_code=obj.take("error_code").toString();
                    error_str+="錯(cuò)誤代碼:";
                    error_str+=error_code;
                    error_str+="n";
                }
                if(obj.contains("error_msg"))
                {
                    error_str+="錯(cuò)誤消息:";
                    error_str+=obj.take("error_msg").toString();
                    error_str+="n";
                }

                //顯示錯(cuò)誤代碼
                QMessageBox::information(this,"提示",error_str,QMessageBox::Ok,QMessageBox::Ok);
            }
         }
        return;
    }

    //設(shè)置屬性
    if(function_select==12 || function_select==13)
    {
        //解析數(shù)據(jù)
        QJsonParseError json_error;
        QJsonDocument document = QJsonDocument::fromJson(replyData, &json_error);
        if(json_error.error == QJsonParseError::NoError)
        {
            //判斷是否是對象,然后開始解析數(shù)據(jù)
            if(document.isObject())
            {
                QJsonObject obj = document.object();
                if(obj.contains("response"))
                {
                    QJsonObject obj1=obj.take("response").toObject();
                    int val=0;
                    QString success;
                    if(obj1.contains("result_code"))
                    {
                         val=obj1.take("result_code").toInt();
                    }
                    if(obj1.contains("result_desc"))
                    {
                         success=obj1.take("result_desc").toString();
                    }

                    if(val==0 && success =="success")
                    {
                        //顯示狀態(tài)
                        QMessageBox::information(this,"提示","遠(yuǎn)程命令操作完成.",QMessageBox::Ok,QMessageBox::Ok);
                        return;
                    }
                    else
                    {
                        //顯示狀態(tài)
                        QMessageBox::information(this,"提示","設(shè)備未正確回應(yīng).請檢查設(shè)備網(wǎng)絡(luò).",QMessageBox::Ok,QMessageBox::Ok);
                        return;
                    }
                }
            }
         }
    }

    //查詢設(shè)備屬性
    if(function_select==0)
    {
        //解析數(shù)據(jù)
        QJsonParseError json_error;
        QJsonDocument document = QJsonDocument::fromJson(replyData, &json_error);
        if(json_error.error == QJsonParseError::NoError)
        {
            //判斷是否是對象,然后開始解析數(shù)據(jù)
            if(document.isObject())
            {
                QJsonObject obj = document.object();
                if(obj.contains("shadow"))
                {
                    QJsonArray array=obj.take("shadow").toArray();
                    for(int i=0;i<array.size();i++)
                    {
                        QJsonObject obj2=array.at(i).toObject();
                        if(obj2.contains("reported"))
                        {
                            QJsonObject obj3=obj2.take("reported").toObject();


                            if(obj3.contains("properties"))
                            {
                                QJsonObject properties=obj3.take("properties").toObject();

                                qDebug()<<"開始解析數(shù)據(jù)....";
                            }
                        }
                    }
                }
            }
         }
        return;
    }
}

五、代碼實(shí)現(xiàn)

5.1 ESP8266連接云平臺實(shí)現(xiàn)代碼

以下是使用STM32F103ZET6和ESP8266連接華為云物聯(lián)網(wǎng)平臺,通過MQTT協(xié)議實(shí)現(xiàn)設(shè)備登錄、主題訂閱和主題發(fā)布的實(shí)現(xiàn)代碼:

#include "stm32f10x.h"
#include "stdio.h"
#include "string.h"

// 定義ESP8266的串口
USART_TypeDef* ESP_USARTx = USART1;

// 定義MQTT服務(wù)器的地址和端口
const char* MQTT_SERVER = "mqtt.eclipse.org";
const int MQTT_PORT = 1883;

// 定義設(shè)備ID和設(shè)備密碼
const char* DEVICE_ID = "your_device_id";
const char* DEVICE_PASSWORD = "your_device_password";

// 定義訂閱的主題
const char* SUBSCRIBE_TOPIC = "your_subscribe_topic";

// 定義發(fā)布的主題
const char* PUBLISH_TOPIC = "your_publish_topic";

// 定義接收緩沖區(qū)和發(fā)送緩沖區(qū)的大小
#define RX_BUFFER_SIZE 1024
#define TX_BUFFER_SIZE 1024

// 定義接收緩沖區(qū)和發(fā)送緩沖區(qū)
char rxBuffer[RX_BUFFER_SIZE];
char txBuffer[TX_BUFFER_SIZE];

// 定義接收緩沖區(qū)的索引和標(biāo)志位
volatile uint16_t rxIndex = 0;
volatile uint8_t rxComplete = 0;

// 發(fā)送數(shù)據(jù)到ESP8266
void ESP8266_SendData(const char* data) {
    sprintf(txBuffer, "%srn", data);
    USART_SendData(ESP_USARTx, (uint16_t)'r');
    USART_SendData(ESP_USARTx, (uint16_t)'n');
    USART_SendData(ESP_USARTx, (uint16_t)'r');
    USART_SendData(ESP_USARTx, (uint16_t)'n');
    USART_SendData(ESP_USARTx, (uint16_t)'r');
    USART_SendData(ESP_USARTx, (uint16_t)'n');
    USART_SendData(ESP_USARTx, (uint16_t)'r');
    USART_SendData(ESP_USARTx, (uint16_t)'n');
    USART_SendData(ESP_USARTx, (uint16_t)'r');
    USART_SendData(ESP_USARTx, (uint16_t)'n');
    USART_SendData(ESP_USARTx, (uint16_t)'r');
    USART_SendData(ESP_USARTx, (uint16_t)'n');
    USART_SendData(ESP_USARTx, (uint16_t)'r');
    USART_SendData(ESP_USARTx, (uint16_t)'n');
    USART_SendData(ESP_USARTx, (uint16_t)'r');
    USART_SendData(ESP_USARTx, (uint16_t)'n');
}

// 從ESP8266接收數(shù)據(jù)
void ESP8266_ReceiveData(uint16_t size) {
    while (size--) {
        rxBuffer[rxIndex++] = USART_ReceiveData(ESP_USARTx);
    }
    if (rxIndex >= RX_BUFFER_SIZE) {
        rxComplete = 1;
        rxIndex = 0;
    }
}

// 處理接收到的數(shù)據(jù)
void ProcessReceivedData() {
    // TODO: 根據(jù)接收到的數(shù)據(jù)進(jìn)行處理
}

// ESP8266串口中斷處理函數(shù)
void USART1_IRQHandler(void) {
    if (USART_GetITStatus(ESP_USARTx, USART_IT_RXNE) != RESET) {
        ESP8266_ReceiveData(1);
    }
}

// 連接到MQTT服務(wù)器
void MQTT_Connect() {
    // 發(fā)送連接請求
    sprintf(txBuffer, "AT+CIPSTART="TCP","%s",%drn", MQTT_SERVER, MQTT_PORT);
    ESP8266_SendData(txBuffer);
    // 等待連接成功
    while (!strstr(rxBuffer, "CONNECTED")) {
        if (rxComplete) {
            ProcessReceivedData();
            rxComplete = 0;
        }
    }
    // 發(fā)送MQTT連接請求
    sprintf(txBuffer, "AT+MQTTCONNECT="%s","%s"rn", DEVICE_ID, DEVICE_PASSWORD);
    ESP8266_SendData(txBuffer);
    // 等待連接成功
    while (!strstr(rxBuffer, "CONNECTED")) {
        if (rxComplete) {
            ProcessReceivedData();
            rxComplete = 0;
        }
    }
}

// 訂閱主題
void MQTT_Subscribe() {
    sprintf(txBuffer, "AT+MQTTSUBSCRIBE="%s"rn", SUBSCRIBE_TOPIC);
    ESP8266_SendData(txBuffer);
}

// 發(fā)布消息
void MQTT_Publish(const char* message) {
    sprintf(txBuffer, "AT+MQTTPUBLISH="%s","%s"rn", PUBLISH_TOPIC, message);
    ESP8266_SendData(txBuffer);
}

int main(void) {
    // 初始化ESP8266的串口
    USART_InitTypeDef USART_InitStructure;
    USART_InitStructure.USART_BaudRate = 115200;
    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(ESP_USARTx, &USART_InitStructure);
    USART_Cmd(ESP_USARTx, ENABLE);
    USART_ITConfig(ESP_USARTx, USART_IT_RXNE, ENABLE);
    NVIC_EnableIRQ(USART1_IRQn);

    // 連接到MQTT服務(wù)器
    MQTT_Connect();

    // 訂閱主題
    MQTT_Subscribe();

    while (1) {
        if (rxComplete) {
            ProcessReceivedData();
            rxComplete = 0;
        }
        
        // TODO: 處理其他業(yè)務(wù)邏輯
        
        // 發(fā)布消息
        MQTT_Publish("Hello, MQTT!");
        
        // 延時(shí)一段時(shí)間
        delay_ms(1000);
    }
}

以上代碼用于演示使用STM32F103ZET6和ESP8266連接華為云物聯(lián)網(wǎng)平臺,通過MQTT協(xié)議實(shí)現(xiàn)設(shè)備登錄、主題訂閱和主題發(fā)布的基本功能。

5.2 ESP8266的MQTT協(xié)議指令

ESP8266通過MQTT協(xié)議連接到服務(wù)器的相關(guān)AT指令主要有以下幾個(gè):

【1】AT+CIPSTART:建立TCP連接

  • 功能:使用TCP協(xié)議連接到遠(yuǎn)程服務(wù)器
  • 用法:AT+CIPSTART=“TCP”,“<服務(wù)器地址>”,<服務(wù)器端口>
  • 示例:AT+CIPSTART=“TCP”,“mqtt.eclipse.org”,1883

【2】AT+MQTTCONNECT:連接到MQTT服務(wù)器

  • 功能:使用MQTT協(xié)議連接到MQTT服務(wù)器
  • 用法:AT+MQTTCONNECT=“<設(shè)備ID>”,“<設(shè)備密碼>”
  • 示例:AT+MQTTCONNECT=“your_device_id”,“your_device_password”

【3】AT+MQTTPUBLISH:發(fā)布消息

  • 功能:向指定主題發(fā)布消息
  • 用法:AT+MQTTPUBLISH=“<主題>”,“<消息內(nèi)容>”
  • 示例:AT+MQTTPUBLISH=“your_publish_topic”,“Hello, MQTT!”

【4】AT+MQTTSUBSCRIBE:訂閱主題

  • 功能:訂閱指定的主題
  • 用法:AT+MQTTSUBSCRIBE=“<主題>”
  • 示例:AT+MQTTSUBSCRIBE=“your_subscribe_topic”

【5】AT+CIPCLOSE:關(guān)閉TCP連接

  • 功能:關(guān)閉當(dāng)前的TCP連接
  • 用法:AT+CIPCLOSE

這些AT指令可以通過串口與ESP8266進(jìn)行通信,實(shí)現(xiàn)與MQTT服務(wù)器的連接、消息發(fā)布和訂閱等功能。通過這些指令,可以在嵌入式設(shè)備上實(shí)現(xiàn)與云端的通信和數(shù)據(jù)交換,從而實(shí)現(xiàn)物聯(lián)網(wǎng)應(yīng)用。

5.3 讀取DHT11傳感器的溫濕度數(shù)據(jù)

以下是使用STM32F103ZET6讀取DHT11傳感器的溫濕度數(shù)據(jù)的實(shí)現(xiàn)代碼:

#include "stm32f10x.h"
#include "dht11.h"

int main(void)
{
    // 初始化DHT11傳感器
    DHT11_Init();

    while (1)
    {
        // 讀取DHT11傳感器的溫濕度數(shù)據(jù)
        DHT11_Result result = DHT11_Read();

        if (result.status == DHT11_OK)
        {
            // 溫度數(shù)據(jù)
            uint8_t temperature = result.temperature;
            // 濕度數(shù)據(jù)
            uint8_t humidity = result.humidity;

            // 在這里進(jìn)行溫濕度數(shù)據(jù)的處理和使用
            // ...

            // 延時(shí)一段時(shí)間后再次讀取
            DelayMs(2000);
        }
        else
        {
            // 讀取失敗,可以進(jìn)行相應(yīng)的錯(cuò)誤處理
            // ...
        }
    }
}

在主函數(shù)中,通過循環(huán)不斷讀取DHT11傳感器的溫濕度數(shù)據(jù)。如果讀取成功,可以從result結(jié)構(gòu)體中獲取溫度和濕度數(shù)據(jù),并進(jìn)行相應(yīng)的處理。如果讀取失敗,可以根據(jù)需要進(jìn)行錯(cuò)誤處理。

5.4 DHT11.c和DHT11.h代碼

dht11.h:

#ifndef DHT11_H
#define DHT11_H

#include "stm32f10x.h"

typedef struct
{
    uint8_t status;      // 讀取狀態(tài),0表示成功,其他表示失敗
    uint8_t humidity;    // 濕度值
    uint8_t temperature; // 溫度值
} DHT11_Result;

void DHT11_Init(void);
DHT11_Result DHT11_Read(void);

#endif

dht11.c:

#include "dht11.h"

#define DHT11_PORT GPIOA
#define DHT11_PIN GPIO_Pin_0

static void DHT11_Delay(uint32_t us)
{
    uint32_t count = us * 8;
    while (count--)
    {
        __NOP();
    }
}

static void DHT11_SetOutput(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
}

static void DHT11_SetInput(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(DHT11_PORT, &GPIO_InitStructure);
}

static uint8_t DHT11_ReadByte(void)
{
    uint8_t byte = 0;
    for (uint8_t i = 0; i < 8; i++)
    {
        while (!GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN))
        {
            // 等待低電平結(jié)束
        }
        DHT11_Delay(30);
        if (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN))
        {
            byte |= (1 << (7 - i));
        }
        while (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN))
        {
            // 等待高電平結(jié)束
        }
    }
    return byte;
}

void DHT11_Init(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    GPIO_InitStructure.GPIO_Pin = DHT11_PIN;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(DHT11_PORT, &GPIO_InitStructure);

    GPIO_SetBits(DHT11_PORT, DHT11_PIN);
}

DHT11_Result DHT11_Read(void)
{
    DHT11_Result result;
    result.status = 1;

    DHT11_SetOutput();
    GPIO_ResetBits(DHT11_PORT, DHT11_PIN);
    DHT11_Delay(18000);
    GPIO_SetBits(DHT11_PORT, DHT11_PIN);
    DHT11_Delay(20);
    DHT11_SetInput();

    if (!GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN))
    {
        while (!GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN))
        {
            // 等待低電平結(jié)束
        }
        while (GPIO_ReadInputDataBit(DHT11_PORT, DHT11_PIN))
        {
            // 等待高電平結(jié)束
        }

        uint8_t data[5];
        for (uint8_t i = 0; i < 5; i++)
        {
            data[i] = DHT11_ReadByte();
        }

        uint8_t sum = data[0] + data[1] + data[2] + data[3];
        if (sum == data[4])
        {
            result.status = 0;
            result.humidity = data[0];
            result.temperature = data[2];
        }
    }

    return result;
}

dht11.h文件定義了DHT11傳感器的初始化函數(shù)DHT11_Init()和讀取函數(shù)DHT11_Read(),以及DHT11_Result結(jié)構(gòu)體用于存儲讀取結(jié)果。

dht11.c文件實(shí)現(xiàn)了DHT11傳感器的初始化和讀取函數(shù)。在初始化函數(shù)中,配置了DHT11引腳的GPIO模式和速度。在讀取函數(shù)中,通過發(fā)送開始信號和接收數(shù)據(jù)的方式讀取DHT11傳感器的溫濕度數(shù)據(jù),并進(jìn)行校驗(yàn)。

  • 更多詳細(xì)資料請聯(lián)系.docx
    下載
意法半導(dǎo)體

意法半導(dǎo)體

意法半導(dǎo)體(ST)集團(tuán)于1987年6月成立,是由意大利的SGS微電子公司和法國Thomson半導(dǎo)體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改為意法半導(dǎo)體有限公司。意法半導(dǎo)體是世界最大的半導(dǎo)體公司之一,公司銷售收入在半導(dǎo)體工業(yè)五大高速增長市場之間分布均衡(五大市場占2007年銷售收入的百分比):通信(35%),消費(fèi)(17%),計(jì)算機(jī)(16%),汽車(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計(jì)數(shù)據(jù),意法半導(dǎo)體是全球第五大半導(dǎo)體廠商,在很多市場居世界領(lǐng)先水平。例如,意法半導(dǎo)體是世界第一大專用模擬芯片和電源轉(zhuǎn)換芯片制造商,世界第一大工業(yè)半導(dǎo)體和機(jī)頂盒芯片供應(yīng)商,而且在分立器件、手機(jī)相機(jī)模塊和車用集成電路領(lǐng)域居世界前列.

意法半導(dǎo)體(ST)集團(tuán)于1987年6月成立,是由意大利的SGS微電子公司和法國Thomson半導(dǎo)體公司合并而成。1998年5月,SGS-THOMSON Microelectronics將公司名稱改為意法半導(dǎo)體有限公司。意法半導(dǎo)體是世界最大的半導(dǎo)體公司之一,公司銷售收入在半導(dǎo)體工業(yè)五大高速增長市場之間分布均衡(五大市場占2007年銷售收入的百分比):通信(35%),消費(fèi)(17%),計(jì)算機(jī)(16%),汽車(16%),工業(yè)(16%)。 據(jù)最新的工業(yè)統(tǒng)計(jì)數(shù)據(jù),意法半導(dǎo)體是全球第五大半導(dǎo)體廠商,在很多市場居世界領(lǐng)先水平。例如,意法半導(dǎo)體是世界第一大專用模擬芯片和電源轉(zhuǎn)換芯片制造商,世界第一大工業(yè)半導(dǎo)體和機(jī)頂盒芯片供應(yīng)商,而且在分立器件、手機(jī)相機(jī)模塊和車用集成電路領(lǐng)域居世界前列.收起

查看更多

相關(guān)推薦

方案定制

去合作
方案開發(fā)定制化,2000+方案商即時(shí)響應(yīng)!