STM32F103C8T6的智能醫療藥品存儲柜系統設計與華為云實現

項目開發背景

隨著現代醫療技術的快速發展,藥品的安全存儲與管理成為醫療質量控制中的重要環節。許多藥品對存儲環境的溫濕度具有嚴格的要求,一旦超出允許范圍,藥品的理化性質可能發生改變,甚至失效,直接影響患者的用藥安全與治療效果。然而,傳統的藥品存儲柜大多依賴人工巡檢和記錄,存在效率低、誤差大、實時性差等問題,難以滿足日益嚴格的藥品管理規范。

在此背景下,物聯網技術的興起為藥品存儲管理提供了新的解決方案。通過傳感器實時采集環境數據,結合無線通信技術將信息上傳至云平臺,能夠實現對藥品存儲狀態的遠程監控與智能預警。這不僅大大提高了藥品管理的自動化水平和數據準確性,也為醫療機構降低了人為管理成本與風險。

本項目基于STM32F103C8T6主控制器,融合溫濕度傳感、門狀態檢測、時鐘記錄與Wi-Fi通信等技術,構建了一套智能藥品存儲柜系統,并通過華為云實現數據的集中管理與分析。該系統具備環境監測、自動調控、數據追溯和遠程管理等功能,旨在為醫療機構提供一種可靠、高效的藥品存儲管理手段,提升藥品管理的智能化水平和醫療安全質量。

設計實現的功能

(1)實時監測藥品柜內溫濕度及門開關狀態。
(2)溫濕度超標時自動啟動溫控設備并報警。
(3)藥品存取記錄及環境數據上傳至華為云平臺。
(4)QT上位機實現藥品管理、環境數據查詢及報警信息處理。

項目開發背景

隨著醫療行業的快速發展,藥品的安全存儲成為保障患者用藥安全和治療效果的關鍵環節。許多藥品對存儲環境有嚴格的溫濕度要求,例如疫苗、胰島素等生物制劑需要在特定溫度范圍內保存,否則容易失效甚至產生有害物質。然而,傳統的藥品存儲柜往往依賴人工定期檢查,這種方式效率低下且容易因疏忽導致環境參數超標,無法實現實時監控和及時干預,從而增加了藥品變質和醫療風險的可能性。

此外,醫療機構的藥品管理還面臨著記錄不完整、追溯困難等問題。手動記錄藥品存取信息不僅耗時耗力,還容易出現錯誤或遺漏,這在緊急情況下可能影響藥品的快速調配和使用。隨著物聯網和云計算技術的興起,智能化的藥品存儲解決方案逐漸成為趨勢,它能夠通過自動化監測、數據遠程傳輸和智能報警,顯著提升藥品管理的效率和可靠性。

本項目旨在設計并實現一個基于STM32F103C8T6微控制器的智能醫療藥品存儲柜系統,結合華為云平臺,實現對柜內溫濕度、門開關狀態的實時監測,并在環境參數超標時自動啟動溫控設備并發出報警。通過集成Wi-Fi模塊,系統將藥品存取記錄和環境數據上傳至云平臺,便于遠程監控和數據分析;同時,QT上位機軟件提供友好的用戶界面,支持藥品管理、歷史查詢和報警處理,從而為醫療機構提供一套高效、安全且可擴展的智能存儲解決方案。

項目硬件模塊組成

(1)STM32F103C8T6最小系統核心板作為主控制器。
(2)DHT22溫濕度傳感器監測柜內環境。
(3)干簧管門磁傳感器檢測柜門開關狀態。
(4)DS1302時鐘模塊記錄藥品存取時間。
(5)ESP8266-01S Wi-Fi模塊實現云平臺通信。
(6)洞洞板焊接信號處理電路,杜邦線連接各傳感器。

設計意義

該智能醫療藥品存儲柜系統設計基于STM32F103C8T6主控制器,實現了對藥品存儲環境的精準監控與管理,具有重要的實際應用價值。系統通過集成溫濕度傳感器和門狀態檢測,確保了藥品在適宜的環境中存儲,防止因溫濕度波動導致的藥品變質或失效,從而保障醫療用藥的安全性和有效性。

系統具備自動溫控和報警功能,在環境參數超標時及時響應,減少了人為干預的需求,提高了運維效率。這不僅降低了藥品損失的風險,還增強了醫療機構的應急處理能力,為日常藥品管理提供了可靠的技術支持。

通過華為云平臺實現數據上傳和QT上位機進行遠程管理,系統實現了藥品存取記錄的數字化和環境的實時可追溯。這便于醫護人員查詢歷史數據、處理報警信息,并支持大數據分析,為優化藥品存儲策略和提升醫療服務質量奠定了基礎。整體設計提升了醫療資源管理的智能化水平,符合現代醫療信息化的發展趨勢。

設計實現的功能

(1)實時監測藥品柜內溫濕度及門開關狀態。
(2)溫濕度超標時自動啟動溫控設備并報警。
(3)藥品存取記錄及環境數據上傳至華為云平臺。
(4)QT上位機實現藥品管理、環境數據查詢及報警信息處理。

項目硬件模塊組成

(1)STM32F103C8T6最小系統核心板作為主控制器。
(2)DHT22溫濕度傳感器監測柜內環境。
(3)干簧管門磁傳感器檢測柜門開關狀態。
(4)DS1302時鐘模塊記錄藥品存取時間。
(5)ESP8266-01S Wi-Fi模塊實現云平臺通信。
(6)洞洞板焊接信號處理電路,杜邦線連接各傳感器。

設計思路

系統設計以STM32F103C8T6最小系統核心板作為主控制器,負責協調整個系統的運行。該控制器通過GPIO接口連接各傳感器模塊,初始化外設并設置中斷處理,確保實時性。系統上電后,STM32進入主循環,持續采集傳感器數據并執行控制邏輯,同時通過串口與Wi-Fi模塊通信,實現數據上傳和命令接收。

溫濕度監測由DHT22傳感器完成,STM32通過單總線協議讀取傳感器數據,定期采樣柜內環境參數。門開關狀態檢測使用干簧管門磁傳感器,連接至STM32的GPIO引腳并配置為輸入模式,利用中斷或輪詢方式實時監測門狀態變化,確保任何開門或關門事件都能及時捕獲。

數據處理部分包括溫濕度閾值判斷,當檢測到溫度或濕度超出預設范圍時,STM32自動啟動溫控設備如風扇或加熱器,并通過蜂鳴器或LED進行報警提示。控制邏輯基于簡單比較算法,確保響應快速且可靠,避免誤動作。

時間記錄依靠DS1302時鐘模塊,STM32通過SPI或類似接口讀取當前時間,為藥品存取事件添加時間戳。這些時間數據與傳感器數據一起存儲到本地緩沖區,并在需要時上傳,保證記錄的準確性和完整性。

云平臺通信通過ESP8266-01S Wi-Fi模塊實現,STM32通過串口AT指令與模塊交互,連接至華為云平臺。系統定期將溫濕度數據、門狀態事件以及藥品存取記錄打包為JSON格式,通過MQTT或HTTP協議上傳,同時支持從云平臺接收配置更新或查詢指令。

QT上位機作為用戶界面,運行于PC端,通過TCP/IP協議與云平臺或直接與STM32通信(需網絡配置)。它提供藥品管理功能如錄入和查詢存取記錄,實時顯示環境數據曲線,并處理報警信息,允許用戶確認和日志導出,增強系統的可管理性和可視化。

設計意義

智能醫療藥品存儲柜系統基于STM32F103C8T6主控制器設計,旨在提升藥品存儲的安全性和管理效率。該系統通過實時監測柜內溫濕度及門開關狀態,確保藥品處于適宜環境中,防止因溫濕度波動導致的藥品變質或失效,從而保障醫療用藥的有效性和患者安全。

溫濕度超標時自動啟動溫控設備并報警功能,能夠及時響應環境異常,減少人工干預的需求,避免藥品損壞風險。這種自動化控制不僅提高了系統的可靠性,還降低了醫療機構的運營成本,通過即時報警機制確保問題得到快速處理。

藥品存取記錄及環境數據上傳至華為云平臺,實現了數據的遠程存儲和可追溯性。這使得醫護人員能夠通過云平臺隨時訪問歷史數據,進行分析和審計,支持合規性管理和決策制定,同時增強了藥品管理的透明度和 accountability。

QT上位機軟件提供了友好的用戶界面,簡化了藥品管理、環境數據查詢和報警信息處理流程。它使操作人員能夠直觀地監控系統狀態,快速響應報警,并高效管理藥品庫存,提升了整體工作效率和用戶體驗。

硬件組成如DHT22傳感器、干簧管門磁和DS1302時鐘模塊,確保了數據采集的準確性和時序記錄的真實性。ESP8266-01S Wi-Fi模塊實現了穩定的云平臺通信,而洞洞板焊接和杜邦線連接則體現了系統的靈活性和成本效益,適用于各種醫療環境部署。

框架圖

+-------------------+      +-----------------+      +-----------------+
|                   |      |                 |      |                 |
|  DHT22 Sensor     |----->|                 |      |                 |
| (溫濕度監測)      |      |                 |      |                 |
+-------------------+      |                 |      |                 || STM32F103C8T6   |      | ESP8266-01S     |
+-------------------+      | (主控制器)      |----->| (Wi-Fi通信)     |
|                   |      |                 |      |                 |
|  Dry Reed Sensor  |----->|                 |      |                 |
| (門開關狀態檢測)  |      |                 |      |                 |
+-------------------+      |                 |      |                 ||                 |      |                 |
+-------------------+      |                 |      |                 |
|                   |      |                 |      |                 |
|  DS1302 Clock     |----->|                 |      |                 |
| (時間記錄)        |      |                 |      |                 |
+-------------------+      +-----------------+      +-----------------+|                         ||                         |v                         v+-----------------+      +-----------------+|                 |      |                 || 溫控設備        |      | 華為云平臺      || (風扇/加熱器)   |      | (數據存儲)      ||                 |      |                 |+-----------------+      +-----------------+|                         ||                         |v                         v+-----------------+      +-----------------+|                 |      |                 || 報警設備        |      | QT上位機        || (蜂鳴器/LED)    |      | (藥品管理)      ||                 |      |                 |+-----------------+      +-----------------+

設計思路

設計思路基于STM32F103C8T6最小系統核心板作為主控制器,負責協調整個系統的運行。該系統通過集成多種傳感器和執行器,實現智能醫療藥品存儲柜的自動化管理。核心板處理來自傳感器的數據,執行控制邏輯,并通過Wi-Fi模塊與云平臺通信,同時上位機軟件提供用戶界面進行監控和管理。

系統首先通過DHT22溫濕度傳感器實時監測柜內環境參數,傳感器數據通過GPIO引腳讀取,STM32進行ADC轉換或數字信號處理,確保數據的準確性。干簧管門磁傳感器用于檢測柜門開關狀態,通過中斷或輪詢方式讀取狀態變化,從而記錄門的開閉事件。DS1302時鐘模塊提供實時時間戳,用于標記藥品存取和環境數據的時間,確保記錄的可追溯性。

當溫濕度數據超出預設閾值時,STM32觸發控制邏輯,自動啟動溫控設備如風扇或加熱器,以調節環境條件,同時通過聲光報警裝置(如蜂鳴器和LED)發出警報,提醒用戶及時處理。這一過程基于軟件中的比較算法,實時監控數據并做出響應,確保藥品存儲環境的安全。

ESP8266-01S Wi-Fi模塊負責與華為云平臺通信,STM32通過UART接口與ESP8266交互,使用AT指令或自定義協議建立Wi-Fi連接。環境數據、門狀態事件和藥品存取記錄被封裝成JSON格式,通過MQTT或HTTP協議上傳到云平臺,實現數據的遠程存儲和監控。云平臺配置為接收和處理這些數據,支持后續的數據分析和告警推送。

QT上位機應用程序運行在PC端,通過串口或網絡與STM32系統通信,實現藥品管理功能,如添加、刪除和查詢藥品信息,同時可以實時查看環境數據歷史記錄和報警信息。上位機提供圖形化界面,方便用戶處理報警事件和生成報告,增強了系統的可用性和管理效率。整個系統的硬件連接采用洞洞板焊接信號處理電路,杜邦線連接各傳感器和模塊,確保電路的穩定性和可維護性。

系統總體設計

該系統基于STM32F103C8T6最小系統核心板作為主控制器,實現智能醫療藥品存儲柜的監控與管理。系統通過DHT22溫濕度傳感器實時采集柜內環境數據,并結合干簧管門磁傳感器檢測柜門的開關狀態,確保環境參數和門狀態得到持續監測。

當溫濕度數據超出預設閾值時,系統自動啟動溫控設備(如風扇或加熱器)進行調節,并觸發報警機制,例如通過蜂鳴器或LED指示,以提醒用戶及時處理異常情況,保障藥品存儲安全。

藥品存取記錄和環境數據通過DS1302時鐘模塊標記時間戳,并通過ESP8266-01S Wi-Fi模塊將數據上傳至華為云平臺,實現遠程數據存儲和訪問。硬件連接采用洞洞板焊接信號處理電路,并使用杜邦線靈活連接各傳感器和模塊,確保系統穩定性和可維護性。

此外,QT上位機軟件提供藥品管理、環境數據查詢和報警信息處理功能,用戶可以通過圖形界面直觀地查看歷史記錄、處理報警事件,并管理藥品庫存,提升系統的實用性和用戶體驗。整個設計注重實際應用,確保功能可靠且易于擴展。

框架圖

+-----------------------------+
|        傳感器層             |
|  +-----------------------+  |
|  | DHT22溫濕度傳感器     |---+
|  +-----------------------+  |   +-----------------------------+
|                             |   |        控制層               |
|  +-----------------------+  |   |  +-----------------------+  |
|  | 干簧管門磁傳感器      |---|-->|  | STM32F103C8T6主控制器 |  |
|  +-----------------------+  |   |  +-----------------------+  |
|                             |   |                             |
|  +-----------------------+  |   |  +-----------------------+  |
|  | DS1302時鐘模塊        |---|-->|  | 信號處理電路(洞洞板)|  |
|  +-----------------------+  |   |  +-----------------------+  |
+-----------------------------+   +-----------------------------+|| (控制信號)v
+-----------------------------+   +-----------------------------+
|        執行層               |   |        通信層               |
|  +-----------------------+  |   |  +-----------------------+  |
|  | 溫控設備(如風扇)     |<---|--|  | ESP8266-01S Wi-Fi模塊 |  |
|  +-----------------------+  |   |  +-----------------------+  |
|                             |   |                             |
|  +-----------------------+  |   |  (通過UART通信)            |
|  | 報警設備(如蜂鳴器)   |<---|--|                           |
|  +-----------------------+  |   +-----------------------------+
+-----------------------------+                 || (Wi-Fi)v+-----------------------------+|        云平臺層             ||  +-----------------------+  ||  | 華為云平臺            |  ||  +-----------------------+  |+-----------------------------+|| (數據API)v+-----------------------------+|        應用層               ||  +-----------------------+  ||  | QT上位機應用程序       |  ||  +-----------------------+  |+-----------------------------+

系統功能總結

功能描述實現方式
實時監測柜內溫濕度DHT22溫濕度傳感器
實時監測柜門開關狀態干簧管門磁傳感器
溫濕度超標自動控制與報警通過STM32控制溫控設備(如風扇/加熱器)并觸發報警裝置
記錄藥品存取時間DS1302時鐘模塊
上傳藥品存取記錄及環境數據至華為云平臺ESP8266-01S Wi-Fi模塊
藥品管理、環境數據查詢及報警信息處理QT上位機軟件
系統主控制與數據處理STM32F103C8T6最小系統核心板

系統總體設計

系統總體設計基于STM32F103C8T6最小系統核心板作為主控制器,負責協調整個智能醫療藥品存儲柜的運行。該系統通過集成多種傳感器和執行器,實現藥品存儲環境的實時監控和數據管理。硬件組成包括DHT22溫濕度傳感器用于采集柜內環境數據,干簧管門磁傳感器檢測門開關狀態,DS1302時鐘模塊提供準確的時間記錄,ESP8266-01S Wi-Fi模塊處理與華為云平臺的通信,所有電路通過洞洞板焊接和杜邦線連接確保穩定性和靈活性。

傳感器數據采集由STM32主控制器定期輪詢完成。DHT22傳感器實時測量溫濕度數值,干簧管門磁傳感器輸出門狀態信號,這些數據通過ADC和GPIO接口讀入STM32進行處理。DS1302時鐘模塊為每次事件提供時間戳,確保藥品存取記錄的準確性。主控制器對采集到的數據進行初步濾波和校驗,以消除噪聲并提高可靠性。

當溫濕度數據超出預設閾值時,系統自動觸發控制邏輯。STM32通過GPIO輸出信號啟動溫控設備(如風扇或加熱器),以調節柜內環境,同時激活報警裝置(如蜂鳴器或LED指示燈)進行本地警示。這一過程確保藥品存儲條件始終符合要求,防止環境異常導致的藥品變質。

所有環境數據和事件記錄(包括溫濕度、門狀態和時間戳)通過ESP8266-01S Wi-Fi模塊上傳至華為云平臺。STM32通過串口與Wi-Fi模塊通信,使用MQTT或HTTP協議將數據打包發送,實現遠程監控和存儲。云平臺負責數據持久化和分析,為上位機提供查詢基礎。

QT上位機軟件作為用戶界面,實現藥品管理、環境數據查詢和報警信息處理。它通過云平臺API獲取數據,顯示實時溫濕度曲線、門狀態歷史記錄和報警事件,并允許用戶配置閾值和管理藥品信息。上位機與STM32系統間接交互,通過云平臺同步數據,確保系統的遠程可管理性和用戶體驗。

設計的各個功能模塊描述

STM32F103C8T6最小系統核心板作為主控制器,負責協調整個系統的運行,包括采集傳感器數據、處理邏輯判斷、控制外部設備以及管理通信模塊。它通過GPIO接口連接各傳感器和執行器,實現實時數據采集和控制輸出。

DHT22溫濕度傳感器用于實時監測藥品柜內的溫度和濕度環境,其數字輸出信號直接連接到STM32的GPIO引腳,STM32定期讀取傳感器數據以進行環境監測和超標判斷。

干簧管門磁傳感器檢測柜門的開關狀態,當門打開或關閉時,傳感器狀態變化通過GPIO輸入到STM32,系統據此記錄門狀態事件并可能觸發相關操作如記錄存取時間。

DS1302時鐘模塊提供實時時間信息,用于精確記錄藥品存取事件的時間戳,STM32通過串行通信接口讀取時鐘數據,確保記錄準確性并支持時間相關功能。

ESP8266-01S Wi-Fi模塊實現與華為云平臺的通信,STM32通過串口將溫濕度數據、門狀態事件和存取記錄發送給ESP8266,由后者通過Wi-Fi網絡上傳數據到云平臺,同時接收可能的云指令。

洞洞板焊接的信號處理電路用于接口和信號調理,例如可能包括電平轉換或濾波電路,以確保傳感器信號穩定可靠地傳輸到STM32,杜邦線用于靈活連接各組件。

溫控設備在溫濕度超標時由STM32控制啟動,例如通過繼電器驅動風扇或加熱器,以調節柜內環境,同時系統會觸發報警機制如聲音或光指示,確保及時處理異常情況。

系統功能總結

功能實現方式
實時監測藥品柜內溫濕度使用DHT22溫濕度傳感器
實時監測門開關狀態使用干簧管門磁傳感器
溫濕度超標時自動啟動溫控設備并報警STM32F103C8T6控制溫控設備,觸發報警機制
記錄藥品存取時間使用DS1302時鐘模塊
藥品存取記錄及環境數據上傳至華為云平臺通過ESP8266-01S Wi-Fi模塊實現通信
QT上位機實現藥品管理、環境數據查詢及報警信息處理基于QT開發的上位機軟件

設計的各個功能模塊描述

STM32F103C8T6最小系統核心板作為主控制器,負責協調整個系統的運行。它通過讀取傳感器數據、處理邏輯控制指令以及管理外設模塊來實現功能需求。主控制器實時采集溫濕度傳感器和門狀態傳感器的信號,根據預設閾值判斷是否啟動溫控設備或觸發報警,同時記錄時間信息并通過Wi-Fi模塊上傳數據到云平臺。

DHT22溫濕度傳感器用于監測藥品柜內的環境參數,實時檢測溫度和濕度值。傳感器將采集到的數據以數字信號形式傳輸給主控制器,主控制器據此進行監控和決策,確保柜內環境符合藥品存儲要求,并在超標時采取相應措施。

干簧管門磁傳感器檢測柜門的開關狀態,當門打開或關閉時,傳感器會產生信號變化并通知主控制器。這一功能用于記錄藥品存取事件,并結合時鐘模塊提供時間戳,確保門狀態變化的準確記錄和報警觸發。

DS1302時鐘模塊提供實時時鐘功能,用于記錄藥品存取的具體時間。模塊與主控制器連接,確保時間數據的準確性和一致性,為上傳到云平臺的數據添加時間標簽,便于后續查詢和分析。

ESP8266-01S Wi-Fi模塊實現與華為云平臺的通信功能,負責將采集到的溫濕度數據、門狀態記錄以及報警信息上傳到云。模塊通過串口與主控制器交互,配置網絡參數并處理數據傳輸,確保數據的可靠性和實時性。

洞洞板焊接的信號處理電路用于穩定和調理傳感器信號,確保數據采集的準確性。電路可能包括濾波、電平轉換或保護元件,以適應不同傳感器的輸出特性,并通過杜邦線連接到主控制器和其他模塊。

杜邦線用于靈活連接各傳感器和模塊到主控制器,便于系統的組裝、調試和維護。這種連接方式提供了良好的可擴展性和可靠性,確保信號傳輸的穩定性。

上位機代碼設計

以下是基于Qt C++開發的智能醫療藥品存儲柜系統上位機代碼。代碼包括主窗口類,實現藥品管理、環境數據查詢和報警信息處理功能。使用QNetworkAccessManager與華為云平臺通信,假設API端點為硬編碼值(實際應用中應配置化)。

文件結構:

  • main.cpp:應用程序入口。
  • MainWindow.h:主窗口頭文件。
  • MainWindow.cpp:主窗口實現文件。
  • Medicine.h:藥品數據模型頭文件(可選,簡化處理)。
  • Medicine.cpp:藥品數據模型實現文件(可選,簡化處理)。

由于篇幅限制,這里提供核心代碼。藥品數據模型簡化處理,直接使用QList存儲藥品名稱。

main.cpp

#include "MainWindow.h"
#include <QApplication>int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}

MainWindow.h

#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QTabWidget>
#include <QListWidget>
#include <QPushButton>
#include <QLineEdit>
#include <QLabel>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QDateTime>class MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void onAddMedicine();void onDeleteMedicine();void onRefreshEnvironment();void onRefreshAlarms();void onEnvironmentReplyFinished(QNetworkReply *reply);void onAlarmsReplyFinished(QNetworkReply *reply);private:void setupUI();void fetchEnvironmentData();void fetchAlarmsData();QTabWidget *tabWidget;QListWidget *medicineList;QLineEdit *medicineInput;QPushButton *addButton;QPushButton *deleteButton;QListWidget *environmentList;QPushButton *refreshEnvButton;QListWidget *alarmsList;QPushButton *refreshAlarmsButton;QNetworkAccessManager *networkManager;QString baseUrl = "http://example.com/api/"; // 假設的API基URL,實際應配置
};#endif // MAINWINDOW_H

MainWindow.cpp

#include "MainWindow.h"
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QMessageBox>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), networkManager(new QNetworkAccessManager(this))
{setupUI();connect(networkManager, &QNetworkAccessManager::finished, this, &MainWindow::onEnvironmentReplyFinished);connect(networkManager, &QNetworkAccessManager::finished, this, &MainWindow::onAlarmsReplyFinished);fetchEnvironmentData();fetchAlarmsData();
}MainWindow::~MainWindow()
{
}void MainWindow::setupUI()
{setWindowTitle("智能醫療藥品存儲柜系統");setGeometry(100, 100, 800, 600);tabWidget = new QTabWidget(this);setCentralWidget(tabWidget);// 藥品管理標簽QWidget *medicineTab = new QWidget;QVBoxLayout *medicineLayout = new QVBoxLayout;medicineList = new QListWidget;medicineInput = new QLineEdit;medicineInput->setPlaceholderText("輸入藥品名稱");QHBoxLayout *inputLayout = new QHBoxLayout;addButton = new QPushButton("添加");deleteButton = new QPushButton("刪除");inputLayout->addWidget(medicineInput);inputLayout->addWidget(addButton);inputLayout->addWidget(deleteButton);medicineLayout->addWidget(medicineList);medicineLayout->addLayout(inputLayout);medicineTab->setLayout(medicineLayout);tabWidget->addTab(medicineTab, "藥品管理");// 環境數據標簽QWidget *envTab = new QWidget;QVBoxLayout *envLayout = new QVBoxLayout;environmentList = new QListWidget;refreshEnvButton = new QPushButton("刷新");envLayout->addWidget(environmentList);envLayout->addWidget(refreshEnvButton);envTab->setLayout(envLayout);tabWidget->addTab(envTab, "環境數據");// 報警信息標簽QWidget *alarmsTab = new QWidget;QVBoxLayout *alarmsLayout = new QVBoxLayout;alarmsList = new QListWidget;refreshAlarmsButton = new QPushButton("刷新");alarmsLayout->addWidget(alarmsList);alarmsLayout->addWidget(refreshAlarmsButton);alarmsTab->setLayout(alarmsLayout);tabWidget->addTab(alarmsTab, "報警信息");// 連接信號和槽connect(addButton, &QPushButton::clicked, this, &MainWindow::onAddMedicine);connect(deleteButton, &QPushButton::clicked, this, &MainWindow::onDeleteMedicine);connect(refreshEnvButton, &QPushButton::clicked, this, &MainWindow::onRefreshEnvironment);connect(refreshAlarmsButton, &QPushButton::clicked, this, &MainWindow::onRefreshAlarms);
}void MainWindow::onAddMedicine()
{QString medicine = medicineInput->text().trimmed();if (!medicine.isEmpty()) {medicineList->addItem(medicine);medicineInput->clear();// 這里應添加代碼將藥品上傳到云平臺,假設通過API POST// 簡化處理,僅本地添加}
}void MainWindow::onDeleteMedicine()
{QList<QListWidgetItem*> selected = medicineList->selectedItems();for (QListWidgetItem *item : selected) {delete item;// 這里應添加代碼從云平臺刪除藥品,假設通過API DELETE}
}void MainWindow::onRefreshEnvironment()
{fetchEnvironmentData();
}void MainWindow::onRefreshAlarms()
{fetchAlarmsData();
}void MainWindow::fetchEnvironmentData()
{QUrl url(baseUrl + "environment");QNetworkRequest request(url);networkManager->get(request);
}void MainWindow::fetchAlarmsData()
{QUrl url(baseUrl + "alarms");QNetworkRequest request(url);networkManager->get(request);
}void MainWindow::onEnvironmentReplyFinished(QNetworkReply *reply)
{if (reply->error() == QNetworkReply::NoError) {QByteArray response = reply->readAll();QJsonDocument jsonDoc = QJsonDocument::fromJson(response);QJsonArray jsonArray = jsonDoc.array();environmentList->clear();for (const QJsonValue &value : jsonArray) {QJsonObject obj = value.toObject();QString temp = obj["temperature"].toString();QString humidity = obj["humidity"].toString();QString time = obj["timestamp"].toString();environmentList->addItem(QString("溫度: %1°C, 濕度: %2%%, 時間: %3").arg(temp).arg(humidity).arg(time));}} else {QMessageBox::warning(this, "錯誤", "獲取環境數據失敗: " + reply->errorString());}reply->deleteLater();
}void MainWindow::onAlarmsReplyFinished(QNetworkReply *reply)
{if (reply->error() == QNetworkReply::NoError) {QByteArray response = reply->readAll();QJsonDocument jsonDoc = QJsonDocument::fromJson(response);QJsonArray jsonArray = jsonDoc.array();alarmsList->clear();for (const QJsonValue &value : jsonArray) {QJsonObject obj = value.toObject();QString message = obj["message"].toString();QString time = obj["timestamp"].toString();alarmsList->addItem(QString("報警: %1, 時間: %2").arg(message).arg(time));}} else {QMessageBox::warning(this, "錯誤", "獲取報警數據失敗: " + reply->errorString());}reply->deleteLater();
}

說明:

  • 此代碼是一個基本框架,實際應用中需要根據華為云API的具體細節調整URL和JSON解析邏輯。
  • 藥品管理功能目前僅本地操作,應添加云同步代碼(例如,在onAddMedicine和onDeleteMedicine中實現網絡請求)。
  • 環境數據和報警數據通過HTTP GET請求獲取,假設API返回JSON數組。
  • 使用Qt的網絡和JSON模塊,確保在.pro文件中添加QT += network

編譯和運行此代碼需要Qt開發環境。根據實際API調整基URL和JSON處理。

上位機代碼設計

#include <QApplication>
#include <QMainWindow>
#include <QTabWidget>
#include <QTableWidget>
#include <QPushButton>
#include <QLineEdit>
#include <QLabel>
#include <QTextEdit>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QChartView>
#include <QLineSeries>
#include <QValueAxis>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QHeaderView>
#include <QMessageBox>
#include <QJsonDocument>
#include <QJsonArray>
#include <QJsonObject>
#include <QDialog>
#include <QFormLayout>
#include <QDialogButtonBox>QT_CHARTS_USE_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void onAddMedicine();void onDeleteMedicine();void onRefreshData();void onNetworkReply(QNetworkReply *reply);private:void setupUI();void fetchDataFromCloud();QTabWidget *tabWidget;QTableWidget *medicineTable;QTableWidget *envDataTable;QTextEdit *alarmTextEdit;QNetworkAccessManager *networkManager;
};MainWindow::MainWindow(QWidget *parent): QMainWindow(parent)
{setupUI();networkManager = new QNetworkAccessManager(this);connect(networkManager, &QNetworkAccessManager::finished, this, &MainWindow::onNetworkReply);fetchDataFromCloud();
}MainWindow::~MainWindow()
{
}void MainWindow::setupUI()
{setWindowTitle("智能醫療藥品存儲柜管理系統");setGeometry(100, 100, 800, 600);tabWidget = new QTabWidget(this);// 藥品管理標簽QWidget *medicineTab = new QWidget;QVBoxLayout *medicineLayout = new QVBoxLayout;QHBoxLayout *buttonLayout = new QHBoxLayout;QPushButton *addButton = new QPushButton("添加藥品");QPushButton *deleteButton = new QPushButton("刪除藥品");QPushButton *refreshButton = new QPushButton("刷新數據");connect(addButton, &QPushButton::clicked, this, &MainWindow::onAddMedicine);connect(deleteButton, &QPushButton::clicked, this, &MainWindow::onDeleteMedicine);connect(refreshButton, &QPushButton::clicked, this, &MainWindow::onRefreshData);buttonLayout->addWidget(addButton);buttonLayout->addWidget(deleteButton);buttonLayout->addWidget(refreshButton);medicineTable = new QTableWidget;medicineTable->setColumnCount(4);medicineTable->setHorizontalHeaderLabels(QStringList() << "藥品ID" << "藥品名稱" << "數量" << "生產日期");medicineLayout->addLayout(buttonLayout);medicineLayout->addWidget(medicineTable);medicineTab->setLayout(medicineLayout);tabWidget->addTab(medicineTab, "藥品管理");// 環境數據標簽QWidget *envDataTab = new QWidget;QVBoxLayout *envLayout = new QVBoxLayout;envDataTable = new QTableWidget;envDataTable->setColumnCount(3);envDataTable->setHorizontalHeaderLabels(QStringList() << "時間" << "溫度" << "濕度");envLayout->addWidget(envDataTable);QChart *chart = new QChart;QLineSeries *tempSeries = new QLineSeries;QLineSeries *humiditySeries = new QLineSeries;chart->addSeries(tempSeries);chart->addSeries(humiditySeries);chart->setTitle("溫濕度歷史數據");chart->createDefaultAxes();QChartView *chartView = new QChartView(chart);chartView->setRenderHint(QPainter::Antialiasing);envLayout->addWidget(chartView);envDataTab->setLayout(envLayout);tabWidget->addTab(envDataTab, "環境數據");// 報警信息標簽QWidget *alarmTab = new QWidget;QVBoxLayout *alarmLayout = new QVBoxLayout;alarmTextEdit = new QTextEdit;alarmTextEdit->setReadOnly(true);alarmLayout->addWidget(alarmTextEdit);alarmTab->setLayout(alarmLayout);tabWidget->addTab(alarmTab, "報警信息");setCentralWidget(tabWidget);
}void MainWindow::onAddMedicine()
{QDialog dialog(this);dialog.setWindowTitle("添加藥品");QFormLayout form(&dialog);QLineEdit *nameEdit = new QLineEdit;QLineEdit *quantityEdit = new QLineEdit;QLineEdit *dateEdit = new QLineEdit;form.addRow("藥品名稱:", nameEdit);form.addRow("數量:", quantityEdit);form.addRow("生產日期:", dateEdit);QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);form.addRow(&buttonBox);connect(&buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);connect(&buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);if (dialog.exec() == QDialog::Accepted) {int row = medicineTable->rowCount();medicineTable->insertRow(row);medicineTable->setItem(row, 0, new QTableWidgetItem(QString::number(row + 1)));medicineTable->setItem(row, 1, new QTableWidgetItem(nameEdit->text()));medicineTable->setItem(row, 2, new QTableWidgetItem(quantityEdit->text()));medicineTable->setItem(row, 3, new QTableWidgetItem(dateEdit->text()));}
}void MainWindow::onDeleteMedicine()
{int currentRow = medicineTable->currentRow();if (currentRow >= 0) {medicineTable->removeRow(currentRow);} else {QMessageBox::warning(this, "警告", "請選擇要刪除的藥品行");}
}void MainWindow::onRefreshData()
{fetchDataFromCloud();
}void MainWindow::fetchDataFromCloud()
{QUrl url("https://your-huawei-cloud-api.com/data");QNetworkRequest request(url);networkManager->get(request);
}void MainWindow::onNetworkReply(QNetworkReply *reply)
{if (reply->error() == QNetworkReply::NoError) {QByteArray data = reply->readAll();QJsonDocument doc = QJsonDocument::fromJson(data);if (doc.isArray()) {QJsonArray array = doc.array();envDataTable->setRowCount(0);for (int i = 0; i < array.size(); ++i) {QJsonObject obj = array[i].toObject();QString time = obj["time"].toString();double temperature = obj["temperature"].toDouble();double humidity = obj["humidity"].toDouble();int row = envDataTable->rowCount();envDataTable->insertRow(row);envDataTable->setItem(row, 0, new QTableWidgetItem(time));envDataTable->setItem(row, 1, new QTableWidgetItem(QString::number(temperature)));envDataTable->setItem(row, 2, new QTableWidgetItem(QString::number(humidity)));}}// 假設報警數據也在回復中if (doc.isObject()) {QJsonObject obj = doc.object();if (obj.contains("alarms")) {QJsonArray alarms = obj["alarms"].toArray();alarmTextEdit->clear();for (const QJsonValue &value : alarms) {QJsonObject alarm = value.toObject();QString alarmMsg = alarm["message"].toString();alarmTextEdit->append(alarmMsg);}}}} else {QMessageBox::critical(this, "錯誤", "獲取數據失敗: " + reply->errorString());}reply->deleteLater();
}int main(int argc, char *argv[])
{QApplication a(argc, argv);MainWindow w;w.show();return a.exec();
}#include "main.moc"

模塊代碼設計

#include "stm32f10x.h"// 引腳定義
#define DHT22_PIN GPIO_Pin_0
#define DHT22_PORT GPIOA#define DOOR_SENSOR_PIN GPIO_Pin_1
#define DOOR_SENSOR_PORT GPIOA#define DS1302_CE_PIN GPIO_Pin_2
#define DS1302_CE_PORT GPIOA
#define DS1302_IO_PIN GPIO_Pin_3
#define DS1302_IO_PORT GPIOA
#define DS1302_SCLK_PIN GPIO_Pin_4
#define DS1302_SCLK_PORT GPIOA#define TEMP_CONTROL_PIN GPIO_Pin_5
#define TEMP_CONTROL_PORT GPIOA
#define ALARM_PIN GPIO_Pin_6
#define ALARM_PORT GPIOA// UART1 for ESP8266
#define ESP8266_UART USART1// 溫濕度閾值
#define TEMP_HIGH_THRESHOLD 30.0
#define TEMP_LOW_THRESHOLD 2.0
#define HUMIDITY_HIGH_THRESHOLD 80.0// 函數聲明
void SystemInit(void);
void GPIO_Init(void);
void UART1_Init(void);
void DHT22_Init(void);
float DHT22_ReadTemperature(void);
float DHT22_ReadHumidity(void);
uint8_t DHT22_ReadByte(void);
void DS1302_Init(void);
void DS1302_WriteByte(uint8_t data);
uint8_t DS1302_ReadByte(void);
void DS1302_GetTime(uint8_t *time);
void DoorSensor_Init(void);
uint8_t DoorSensor_Read(void);
void ESP8266_Init(void);
void ESP8266_SendCmd(char *cmd);
void ESP8266_SendData(char *data);
void Delay_ms(uint32_t nTime);
void Delay_us(uint32_t nTime);int main(void) {SystemInit();GPIO_Init();UART1_Init();DHT22_Init();DS1302_Init();DoorSensor_Init();ESP8266_Init();while (1) {// 讀取溫濕度float temp = DHT22_ReadTemperature();float humidity = DHT22_ReadHumidity();// 讀取門狀態uint8_t door_state = DoorSensor_Read();// 讀取時間uint8_t time[7];DS1302_GetTime(time);// 檢查溫濕度閾值if (temp > TEMP_HIGH_THRESHOLD || temp < TEMP_LOW_THRESHOLD || humidity > HUMIDITY_HIGH_THRESHOLD) {GPIO_SetBits(TEMP_CONTROL_PORT, TEMP_CONTROL_PIN); // 啟動溫控設備GPIO_SetBits(ALARM_PORT, ALARM_PIN); // 報警} else {GPIO_ResetBits(TEMP_CONTROL_PORT, TEMP_CONTROL_PIN);GPIO_ResetBits(ALARM_PORT, ALARM_PIN);}// 準備數據上傳到華為云char data_str[100];sprintf(data_str, "temp=%.2f&humidity=%.2f&door=%d&time=%02d:%02d:%02d", temp, humidity, door_state, time[2], time[1], time[0]);ESP8266_SendData(data_str);Delay_ms(5000); // 每5秒上傳一次}
}void SystemInit(void) {// 設置系統時鐘為72MHzRCC->CFGR |= RCC_CFGR_PLLMULL9;RCC->CFGR |= RCC_CFGR_PLLSRC;RCC->CR |= RCC_CR_PLLON;while (!(RCC->CR & RCC_CR_PLLRDY));RCC->CFGR |= RCC_CFGR_SW_PLL;while (!(RCC->CFGR & RCC_CFGR_SWS_PLL));
}void GPIO_Init(void) {// 啟用GPIOA和UART1時鐘RCC->APB2ENR |= RCC_APB2ENR_IOPAEN | RCC_APB2ENR_USART1EN;// 配置DHT22引腳為輸入GPIOA->CRL &= ~(0xF << (0 * 4)); // PA0: inputGPIOA->CRL |= (0x4 << (0 * 4)); // Floating input// 配置門傳感器引腳為輸入帶上拉GPIOA->CRL &= ~(0xF << (1 * 4)); // PA1: inputGPIOA->CRL |= (0x8 << (1 * 4)); // Pull-up inputGPIOA->ODR |= DOOR_SENSOR_PIN; // Enable pull-up// 配置DS1302引腳:CE、IO、SCLK為輸出GPIOA->CRL &= ~(0xFF << (2 * 4)); // Clear PA2, PA3, PA4GPIOA->CRL |= (0x3 << (2 * 4)) | (0x3 << (3 * 4)) | (0x3 << (4 * 4)); // PA2, PA3, PA4: output, 50MHzGPIOA->ODR &= ~(DS1302_CE_PIN | DS1302_IO_PIN | DS1302_SCLK_PIN); // Set low initially// 配置溫控和報警引腳為輸出GPIOA->CRL &= ~(0xF << (5 * 4)); // PA5: outputGPIOA->CRL |= (0x3 << (5 * 4)); // Output, 50MHzGPIOA->CRL &= ~(0xF << (6 * 4)); // PA6: outputGPIOA->CRL |= (0x3 << (6 * 4)); // Output, 50MHz// 配置UART1引腳: PA9 as TX, PA10 as RXGPIOA->CRH &= ~(0xFF << 4); // Clear PA9 and PA10GPIOA->CRH |= (0xB << 4) | (0x4 << 8); // PA9: AF output, 50MHz; PA10: input floating
}void UART1_Init(void) {// 配置UART1: 9600 baud, 8 data bits, no parity, 1 stop bitUSART1->BRR = 72000000 / 9600; // Set baud rateUSART1->CR1 |= USART_CR1_TE | USART_CR1_RE; // Enable TX and RXUSART1->CR1 |= USART_CR1_UE; // Enable UART
}void DHT22_Init(void) {// 初始化代碼,設置引腳GPIO_ResetBits(DHT22_PORT, DHT22_PIN); // Set low initiallyDelay_ms(1000);
}float DHT22_ReadTemperature(void) {uint8_t data[5];// 啟動信號GPIO_SetBits(DHT22_PORT, DHT22_PIN);Delay_us(30);GPIO_ResetBits(DHT22_PORT, DHT22_PIN);Delay_ms(1);GPIO_SetBits(DHT22_PORT, DHT22_PIN);Delay_us(40);// 等待響應while (GPIO_ReadInputDataBit(DHT22_PORT, DHT22_PIN));while (!GPIO_ReadInputDataBit(DHT22_PORT, DHT22_PIN));// 讀取數據for (int i = 0; i < 5; i++) {data[i] = DHT22_ReadByte();}// 校驗和檢查if (data[4] == (data[0] + data[1] + data[2] + data[3])) {float temp = (data[2] & 0x7F) * 256 + data[3];temp /= 10.0;if (data[2] & 0x80) temp = -temp;return temp;}return -1.0;
}float DHT22_ReadHumidity(void) {uint8_t data[5];// 類似ReadTemperature,但返回濕度// 啟動信號GPIO_SetBits(DHT22_PORT, DHT22_PIN);Delay_us(30);GPIO_ResetBits(DHT22_PORT, DHT22_PIN);Delay_ms(1);GPIO_SetBits(DHT22_PORT, DHT22_PIN);Delay_us(40);while (GPIO_ReadInputDataBit(DHT22_PORT, DHT22_PIN));while (!GPIO_ReadInputDataBit(DHT22_PORT, DHT22_PIN));for (int i = 0; i < 5; i++) {data[i] = DHT22_ReadByte();}if (data[4] == (data[0] + data[1] + data[2] + data[3])) {float humidity = data[0] * 256 + data[1];humidity /= 10.0;return humidity;}return -1.0;
}uint8_t DHT22_ReadByte(void) {uint8_t byte = 0;for (int i = 0; i < 8; i++) {while (!GPIO_ReadInputDataBit(DHT22_PORT, DHT22_PIN)); // Wait for highDelay_us(30);if (GPIO_ReadInputDataBit(DHT22_PORT, DHT22_PIN)) {byte |= (1 << (7 - i));}while (GPIO_ReadInputDataBit(DHT22_PORT, DHT22_PIN)); // Wait for low}return byte;
}void DS1302_Init(void) {GPIO_ResetBits(DS1302_CE_PORT, DS1302_CE_PIN);GPIO_ResetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);
}void DS1302_WriteByte(uint8_t data) {for (int i = 0; i < 8; i++) {GPIO_WriteBit(DS1302_IO_PORT, DS1302_IO_PIN, (data & (1 << i)) ? Bit_SET : Bit_RESET);GPIO_SetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);Delay_us(1);GPIO_ResetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);Delay_us(1);}
}uint8_t DS1302_ReadByte(void) {uint8_t byte = 0;for (int i = 0; i < 8; i++) {if (GPIO_ReadInputDataBit(DS1302_IO_PORT, DS1302_IO_PIN)) {byte |= (1 << i);}GPIO_SetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);Delay_us(1);GPIO_ResetBits(DS1302_SCLK_PORT, DS1302_SCLK_PIN);Delay_us(1);}return byte;
}void DS1302_GetTime(uint8_t *time) {GPIO_SetBits(DS1302_CE_PORT, DS1302_CE_PIN);DS1302_WriteByte(0x81); // Read secondstime[0] = DS1302_ReadByte();DS1302_WriteByte(0x83); // Read minutestime[1] = DS1302_ReadByte();DS1302_WriteByte(0x85); // Read hourstime[2] = DS1302_ReadByte();GPIO_ResetBits(DS1302_CE_PORT, DS1302_CE_PIN);
}void DoorSensor_Init(void) {// 已在GPIO_Init中初始化
}uint8_t DoorSensor_Read(void) {return GPIO_ReadInputDataBit(DOOR_SENSOR_PORT, DOOR_SENSOR_PIN);
}void ESP8266_Init(void) {ESP8266_SendCmd("AT+RST\r\n");Delay_ms(1000);ESP8266_SendCmd("AT+CWMODE=1\r\n");Delay_ms(1000);ESP8266_SendCmd("AT+CWJAP=\"YourSSID\",\"YourPassword\"\r\n");Delay_ms(5000);ESP8266_SendCmd("AT+CIPSTART=\"TCP\",\"華為云地址\",端口號\r\n");Delay_ms(1000);
}void ESP8266_SendCmd(char *cmd) {while (*cmd) {USART_SendData(ESP8266_UART, *cmd++);while (USART_GetFlagStatus(ESP8266_UART, USART_FLAG_TC) == RESET);}
}void ESP8266_SendData(char *data) {char cmd[50];sprintf(cmd, "AT+CIPSEND=%d\r\n", strlen(data));ESP8266_SendCmd(cmd);Delay_ms(100);ESP8266_SendCmd(data);ESP8266_SendCmd("\r\n");
}void Delay_ms(uint32_t nTime) {for (uint32_t i = 0; i < nTime * 1000; i++) {__NOP();}
}void Delay_us(uint32_t nTime) {for (uint32_t i = 0; i < nTime; i++) {__NOP();}
}

模塊代碼設計

#include <stdint.h>// Register definitions for STM32F103C8T6
#define GPIOA_BASE 0x40010800
#define GPIOA_CRL (*((volatile uint32_t *)(GPIOA_BASE + 0x00)))
#define GPIOA_CRH (*((volatile uint32_t *)(GPIOA_BASE + 0x04)))
#define GPIOA_IDR (*((volatile uint32_t *)(GPIOA_BASE + 0x08)))
#define GPIOA_ODR (*((volatile uint32_t *)(GPIOA_BASE + 0x0C)))#define GPIOB_BASE 0x40010C00
#define GPIOB_CRL (*((volatile uint32_t *)(GPIOB_BASE + 0x00)))
#define GPIOB_CRH (*((volatile uint32_t *)(GPIOB_BASE + 0x04)))
#define GPIOB_IDR (*((volatile uint32_t *)(GPIOB_BASE + 0x08)))
#define GPIOB_ODR (*((volatile uint32_t *)(GPIOB_BASE + 0x0C)))#define RCC_BASE 0x40021000
#define RCC_APB2ENR (*((volatile uint32_t *)(RCC_BASE + 0x18)))#define USART1_BASE 0x40013800
#define USART1_SR (*((volatile uint32_t *)(USART1_BASE + 0x00)))
#define USART1_DR (*((volatile uint32_t *)(USART1_BASE + 0x04)))
#define USART1_BRR (*((volatile uint32_t *)(USART1_BASE + 0x08)))
#define USART1_CR1 (*((volatile uint32_t *)(USART1_BASE + 0x0C)))#define SYSTICK_BASE 0xE000E010
#define SYST_CSR (*((volatile uint32_t *)(SYSTICK_BASE + 0x00)))
#define SYST_RVR (*((volatile uint32_t *)(SYSTICK_BASE + 0x04)))
#define SYST_CVR (*((volatile uint32_t *)(SYSTICK_BASE + 0x08)))// Pin definitions
#define DHT22_PIN 0  // PA0
#define DOOR_SENSOR_PIN 1  // PA1
#define DS1302_CE_PIN 2  // PA2
#define DS1302_IO_PIN 3  // PA3
#define DS1302_SCLK_PIN 4  // PA4
#define TEMP_CTRL_PIN 5  // PA5 (e.g., relay for fan)
#define ALARM_PIN 6  // PA6 (e.g., LED)
#define ESP8266_TX_PIN 9  // PA9
#define ESP8266_RX_PIN 10 // PA10// Constants
#define SYSTEM_CORE_CLOCK 8000000  // 8MHz
#define DHT22_TIMEOUT 10000
#define TEMP_THRESHOLD_HIGH 30.0  // Example temperature threshold
#define HUMIDITY_THRESHOLD_HIGH 80.0  // Example humidity threshold// Global variables
volatile uint32_t msTicks = 0;// SysTick interrupt handler
void SysTick_Handler(void) {msTicks++;
}// Delay in milliseconds
void Delay_ms(uint32_t ms) {uint32_t startTicks = msTicks;while ((msTicks - startTicks) < ms);
}// Delay in microseconds (approximate for 8MHz)
void Delay_us(uint32_t us) {us = us * 2;  // Adjust for 8MHz, each loop ~0.5uswhile (us--) {__asm__("nop");}
}// GPIO initialization
void GPIO_Init(void) {// Enable clock for GPIOA and GPIOBRCC_APB2ENR |= (1 << 2) | (1 << 3);  // GPIOA and GPIOB clock enable// Configure PA0 (DHT22) as output open-drain initiallyGPIOA_CRL &= ~(0xF << (DHT22_PIN * 4));GPIOA_CRL |= (0x3 << (DHT22_PIN * 4));  // Output mode, max speed 50MHzGPIOA_ODR |= (1 << DHT22_PIN);  // Set high// Configure PA1 (Door sensor) as input with pull-upGPIOA_CRL &= ~(0xF << (DOOR_SENSOR_PIN * 4));GPIOA_CRL |= (0x8 << (DOOR_SENSOR_PIN * 4));  // Input with pull-up/pull-downGPIOA_ODR |= (1 << DOOR_SENSOR_PIN);  // Pull-up// Configure PA2, PA3, PA4 for DS1302: PA2(CE) and PA4(SCLK) as output, PA3(IO) as input/outputGPIOA_CRL &= ~(0xFFF << (DS1302_CE_PIN * 4));  // Clear bits for PA2, PA3, PA4GPIOA_CRL |= (0x3 << (DS1302_CE_PIN * 4)) | (0x3 << (DS1302_SCLK_PIN * 4));  // Output for CE and SCLKGPIOA_ODR &= ~(1 << DS1302_CE_PIN);  // CE lowGPIOA_ODR &= ~(1 << DS1302_SCLK_PIN);  // SCLK low// For PA3(IO), set as input initiallyGPIOA_CRL |= (0x8 << (DS1302_IO_PIN * 4));  // Input with pull-up/pull-downGPIOA_ODR |= (1 << DS1302_IO_PIN);  // Pull-up// Configure PA5 (Temperature control) and PA6 (Alarm) as outputGPIOA_CRL &= ~(0xFF << (TEMP_CTRL_PIN * 4));GPIOA_CRL |= (0x3 << (TEMP_CTRL_PIN * 4)) | (0x3 << (ALARM_PIN * 4));  // OutputGPIOA_ODR &= ~(1 << TEMP_CTRL_PIN);  // Off initiallyGPIOA_ODR &= ~(1 << ALARM_PIN);  // Off initially// Configure PA9 (USART1 TX) as alternate function output, PA10 (USART1 RX) as inputGPIOA_CRH &= ~(0xFF << ((ESP8266_TX_PIN - 8) * 4));GPIOA_CRH |= (0xB << ((ESP8266_TX_PIN - 8) * 4));  // AF output for TXGPIOA_CRH |= (0x4 << ((ESP8266_RX_PIN - 8) * 4));  // Input floating for RX
}// USART1 initialization for ESP8266
void USART1_Init(void) {// Enable clock for USART1RCC_APB2ENR |= (1 << 14);  // USART1 clock enable// Configure USART1: 9600 baud, 8 data bits, no parity, 1 stop bitUSART1_BRR = 0x341;  // 8MHz / 9600 = 833.33 -> 0x341 (mantissa 52, fraction 1)USART1_CR1 |= (1 << 13) | (1 << 3) | (1 << 2);  // UE, TE, RE
}// USART1 send character
void USART1_SendChar(char c) {while (!(USART1_SR & (1 << 7)));  // Wait for TXEUSART1_DR = c;
}// USART1 send string
void USART1_SendString(const char *str) {while (*str) {USART1_SendChar(*str++);}
}// DHT22 functions
void DHT22_Start(void) {GPIOA_CRL &= ~(0xF << (DHT22_PIN * 4));GPIOA_CRL |= (0x3 << (DHT22_PIN * 4));  // Output modeGPIOA_ODR &= ~(1 << DHT22_PIN);  // Pull lowDelay_ms(1);  // Wait 1msGPIOA_ODR |= (1 << DHT22_PIN);  // Pull highDelay_us(30);  // Wait 30usGPIOA_CRL &= ~(0xF << (DHT22_PIN * 4));GPIOA_CRL |= (0x8 << (DHT22_PIN * 4));  // Input mode
}uint8_t DHT22_Check_Response(void) {uint32_t timeout = 0;while (GPIOA_IDR & (1 << DHT22_PIN)) {  Wait for lowif (timeout++ > DHT22_TIMEOUT) return 0;Delay_us(1);}timeout = 0;while (!(GPIOA_IDR & (1 << DHT22_PIN))) {  Wait for highif (timeout++ > DHT22_TIMEOUT) return 0;Delay_us(1);}timeout = 0;while (GPIOA_IDR & (1 << DHT22_PIN)) {  Wait for low againif (timeout++ > DHT22_TIMEOUT) return 0;Delay_us(1);}return 1;
}uint8_t DHT22_Read_Bit(void) {uint32_t timeout = 0;while (!(GPIOA_IDR & (1 << DHT22_PIN))) {  Wait for highif (timeout++ > DHT22_TIMEOUT) return 0;Delay_us(1);}Delay_us(40);  // Wait 40usif (GPIOA_IDR & (1 << DHT22_PIN)) return 1;else return 0;
}uint8_t DHT22_Read_Byte(void) {uint8_t byte = 0;for (int i = 0; i < 8; i++) {byte <<= 1;byte |= DHT22_Read_Bit();}return byte;
}int DHT22_Read(float *temperature, float *humidity) {uint8 data[5] = {0};DHT22_Start();if (!DHT22_Check_Response()) return 0;for (int i = 0; i < 5; i++) {data[i] = DHT22_Read_Byte();}// Checksumif (data[4] != (data[0] + data[1] + data[2] + data[3])) return 0;*humidity = (data[0] * 256 + data[1]) / 10.0;*temperature = (data[2] * 256 + data[3]) / 10.0;return 1;
}// DS1302 functions
void DS1302_Write_Byte(uint8_t byte) {GPIOA_CRL &= ~(0xF << (DS1302_IO_PIN * 4));GPIOA_CRL |= (0x3 << (DS1302_IO_PIN * 4));  // Output modefor (int i = 0; i < 8; i++) {if (byte & 0x01) GPIOA_ODR |= (1 << DS1302_IO_PIN);else GPIOA_ODR &= ~(1 << DS1302_IO_PIN);GPIOA_ODR |= (1 << DS1302_SCLK_PIN);  // SCLK highDelay_us(1);GPIOA_ODR &= ~(1 << DS1302_SCLK_PIN);  // SCLK lowDelay_us(1);byte >>= 1;}
}uint8_t DS1302_Read_Byte(void) {uint8_t byte = 0;GPIOA_CRL &= ~(0xF << (DS1302_IO_PIN * 4));GPIOA_CRL |= (0x8 << (DS1302_IO_PIN * 4));  // Input modefor (int i = 0; i < 8; i++) {byte >>= 1;if (GPIOA_IDR & (1 << DS1302_IO_PIN)) byte |= 0x80;GPIOA_ODR |= (1 << DS1302_SCLK_PIN);  // SCLK highDelay_us(1);GPIOA_ODR &= ~(1 << DS1302_SCLK_PIN);  // SCLK lowDelay_us(1);}return byte;
}void DS1302_Write_Register(uint8_t reg, uint8_t data) {GPIOA_ODR |= (1 << DS1302_CE_PIN);  // CE highDS1302_Write_Byte(reg);DS1302_Write_Byte(data);GPIOA_ODR &= ~(1 << DS1302_CE_PIN);  // CE low
}uint8_t DS1302_Read_Register(uint8_t reg) {GPIOA_ODR |= (1 << DS1302_CE_PIN);  // CE highDS1302_Write_Byte(reg | 0x01);  // Read commanduint8_t data = DS1302_Read_Byte();GPIOA_ODR &= ~(1 << DS1302_CE_PIN);  // CE lowreturn data;
}void DS1302_Init(void) {// Disable write protectionDS1302_Write_Register(0x8E, 0x00);// Enable clockDS1302_Write_Register(0x80, 0x00);  // Ensure clock is running
}void DS1302_Get_Time(uint8_t *year, uint8_t *month, uint8_t *day, uint8_t *hour, uint8_t *minute, uint8_t *second) {*second = DS1302_Read_Register(0x81);*minute = DS1302_Read_Register(0x83);*hour = DS1302_Read_Register(0x85);*day = DS1302_Read_Register(0x87);*month = DS1302_Read_Register(0x89);*year = DS1302_Read_Register(0x8D);
}// Door sensor read
uint8_t Door_Read(void) {return (GPIOA_IDR & (1 << DOOR_SENSOR_PIN)) ? 1 : 0;  // 1 means door closed? depends on wiring
}// Control functions
void Temp_Ctrl_On(void) {GPIOA_ODR |= (1 << TEMP_CTRL_PIN);  // Turn on temp control device
}void Temp_Ctrl_Off(void) {GPIOA_ODR &= ~(1 << TEMP_CTRL_PIN);  // Turn off
}void Alarm_On(void) {GPIOA_ODR |= (1 << ALARM_PIN);  // Turn on alarm
}void Alarm_Off(void) {GPIOA_ODR &= ~(1 << ALARM_PIN);  // Turn off
}// ESP8266 functions for Huawei Cloud
void ESP8266_Init(void) {USART1_SendString("AT+RST\r\n");Delay_ms(1000);USART1_SendString("AT+CWMODE=1\r\n");Delay_ms(1000);USART1_SendString("AT+CWJAP=\"SSID\",\"PASSWORD\"\r\n");  // Replace with your WiFi credentialsDelay_ms(5000);USART1_SendString("AT+CIPSTART=\"TCP\",\"192.168.1.100\",8080\r\n");  // Replace with Huawei Cloud IP and portDelay_ms(2000);
}void ESP8266_Send_Data(float temp, float hum, uint8_t door狀態, uint8_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t minute, uint8_t second) {char buffer[100];sprintf(buffer, "AT+CIPSEND=%d\r\n", strlen("Temp: XX.X, Hum: XX.X, Door: X, Time: YYYY-MM-DD HH:MM:SS"));USART1_SendString(buffer);Delay_ms(100);sprintf(buffer, "Temp: %.1f, Hum: %.1f, Door: %d, Time: 20%02d-%02d-%02d %02d:%02d:%02d\r\n", temp, hum, door狀態, year, month, day, hour, minute, second);USART1_SendString(buffer);Delay_ms(500);
}// Main function
int main(void) {// Initialize SysTick for 1ms interruptsSYST_RVR = 8000 - 1;  // Reload value for 1ms at 8MHzSYST_CVR = 0;SYST_CSR = (1 << 2) | (1 << 0);  // Processor clock, enableGPIO_Init();USART1_Init();DS1302_Init();ESP8266_Init();float temperature, humidity;uint8_t door狀態;uint8_t year, month, day, hour, minute, second;while (1) {if (DHT22_Read(&temperature, &humidity)) {door狀態 = Door_Read();DS1302_Get_Time(&year, &month, &day, &hour, &minute, &second);// Check thresholds and controlif (temperature > TEMP_THRESHOLD_HIGH || humidity > HUMIDITY_THRESHOLD_HIGH) {Temp_Ctrl_On();Alarm_On();} else {Temp_Ctrl_Off();Alarm_Off();}// Send data to cloudESP8266_Send_Data(temperature, humidity, door狀態, year, month, day, hour, minute, second);// Log access if door state changed (simple example)static uint8_t last_door狀態 = 0;if (door狀態 != last_door狀態) {// Record access event, e.g., send to cloud or store locallylast_door狀態 = door狀態;}}Delay_ms(5000);  // Read every 5 seconds}
}

項目核心代碼

#include <stdint.h>// Register definitions for STM32F103
#define RCC_APB2ENR (*(volatile uint32_t*)0x40021018)
#define GPIOA_CRL (*(volatile uint32_t*)0x40010800)
#define GPIOA_CRH (*(volatile uint32_t*)0x40010804)
#define GPIOA_ODR (*(volatile uint32_t*)0x4001080C)
#define USART1_SR (*(volatile uint32_t*)0x40013800)
#define USART1_DR (*(volatile uint32_t*)0x40013804)
#define USART1_BRR (*(volatile uint32_t*)0x40013808)
#define USART1_CR1 (*(volatile uint32_t*)0x4001380C)// External function declarations
extern void DHT22_Init(void);
extern void DHT22_Read(float *temp, float *humidity);
extern void DoorSensor_Init(void);
extern uint8_t DoorSensor_Read(void);
extern void DS1302_Init(void);
extern void DS1302_GetTime(char *timeBuffer);
extern void ESP8266_Init(void);
extern void ESP8266_SendData(const char *data);// Pin definitions
#define FAN_PIN 2  // PA2
#define ALARM_PIN 3 // PA3// GPIO initialization
void GPIO_Init(void) {// Enable GPIOA clockRCC_APB2ENR |= (1 << 2);// Configure PA2 and PA3 as output push-pull, 50MHzGPIOA_CRL &= ~(0xF << 8);   // Clear bits for PA2GPIOA_CRL |= (0x3 << 8);    // Set PA2 to output push-pullGPIOA_CRL &= ~(0xF << 12);  // Clear bits for PA3GPIOA_CRL |= (0x3 << 12);   // Set PA3 to output push-pull
}// USART1 initialization for ESP8266
void USART1_Init(void) {// Enable USART1 clockRCC_APB2ENR |= (1 << 14);// Configure PA9 as alternative push-pull output (TX)GPIOA_CRH &= ~(0xF << 4);GPIOA_CRH |= (0xB << 4);// Configure PA10 as input floating (RX)GPIOA_CRH &= ~(0xF << 8);GPIOA_CRH |= (0x4 << 8);// Set baud rate to 9600 (72MHz clock)USART1_BRR = 0x1D4C;// Enable USART1, transmitter, and receiverUSART1_CR1 |= (1 << 13) | (1 << 3) | (1 << 2);
}// Control functions
void Fan_On(void) {GPIOA_ODR |= (1 << FAN_PIN);
}void Fan_Off(void) {GPIOA_ODR &= ~(1 << FAN_PIN);
}void Alarm_On(void) {GPIOA_ODR |= (1 << ALARM_PIN);
}void Alarm_Off(void) {GPIOA_ODR &= ~(1 << ALARM_PIN);
}// Simple delay function
void Delay(void) {for (volatile int i = 0; i < 500000; i++);
}int main(void) {// Initialize hardwareGPIO_Init();USART1_Init();DHT22_Init();DoorSensor_Init();DS1302_Init();ESP8266_Init();float temp, humidity;uint8_t door_status;char time_str[20];while (1) {// Read sensorsDHT22_Read(&temp, &humidity);door_status = DoorSensor_Read();DS1302_GetTime(time_str);// Control logicif (temp > 30.0 || humidity > 80.0) {Fan_On();Alarm_On();} else {Fan_Off();Alarm_Off();}// Prepare data stringchar data[100];int len = 0;len += sprintf(data + len, "Time: %s, Temp: %.2f C, Humidity: %.2f%%, Door: %s", time_str, temp, humidity, door_status ? "Open" : "Closed");// Send data to cloudESP8266_SendData(data);// DelayDelay();}
}

總結

本系統基于STM32F103C8T6微控制器,成功設計并實現了一個智能醫療藥品存儲柜,核心功能包括實時監測柜內溫濕度及門開關狀態,確保藥品存儲環境符合標準,并在溫濕度超標時自動啟動溫控設備和報警機制,從而保障藥品的安全與有效性。

硬件組成上,系統采用了DHT22溫濕度傳感器進行環境數據采集,干簧管門磁傳感器檢測門狀態,DS1302時鐘模塊記錄精確時間信息,ESP8266-01S Wi-Fi模塊實現與華為云平臺的穩定通信,所有組件通過洞洞板焊接的信號處理電路和杜邦線連接,確保了系統的可靠性和易維護性。

軟件方面,通過華為云平臺集成,系統實現了環境數據和藥品存取記錄的上傳與存儲,QT上位機應用提供了友好的用戶界面,支持藥品管理、歷史數據查詢和報警信息處理,大大提升了系統的智能化水平和操作便利性。

總體而言,該系統將嵌入式硬件、云平臺和上位機軟件有機結合,為醫療藥品存儲提供了一套高效、可靠的解決方案,具有廣泛的應用前景和推廣價值。

項目核心代碼

#include <stdint.h>// 寄存器定義
#define RCC_BASE        0x40021000
#define GPIOA_BASE      0x40010800
#define USART1_BASE     0x40013800#define RCC_CR          (*((volatile uint32_t *)(RCC_BASE + 0x00)))
#define RCC_CFGR        (*((volatile uint32_t *)(RCC_BASE + 0x04)))
#define RCC_APB2ENR     (*((volatile uint32_t *)(RCC_BASE + 0x18)))#define GPIOA_CRL       (*((volatile uint32_t *)(GPIOA_BASE + 0x00)))
#define GPIOA_CRH       (*((volatile uint32_t *)(GPIOA_BASE + 0x04)))
#define GPIOA_IDR       (*((volatile uint32_t *)(GPIOA_BASE + 0x08)))
#define GPIOA_ODR       (*((volatile uint32_t *)(GPIOA_BASE + 0x0C)))#define USART1_SR       (*((volatile uint32_t *)(USART1_BASE + 0x00)))
#define USART1_DR       (*((volatile uint32_t *)(USART1_BASE + 0x04)))
#define USART1_BRR      (*((volatile uint32_t *)(USART1_BASE + 0x08)))
#define USART1_CR1      (*((volatile uint32_t *)(USART1_BASE + 0x0C)))// 假設其他模塊函數原型
extern void DHT22_Init(void);
extern float DHT22_ReadTemperature(void);
extern float DHT22_ReadHumidity(void);
extern void DoorSensor_Init(void);
extern int DoorSensor_Read(void);
extern void DS1302_Init(void);
extern void DS1302_GetTime(char *timeStr);
extern void ESP8266_Init(void);
extern void ESP8266_SendData(const char *data);// 引腳定義
#define HEATER_PIN  2  // PA2
#define ALARM_PIN   3  // PA3void SystemInit(void) {// 啟用HSE并配置PLL為72MHzRCC_CR |= (1 << 16);  // 啟用HSEwhile (!(RCC_CR & (1 << 17)));  // 等待HSE就緒RCC_CFGR |= (1 << 16);  // PLL源為HSERCC_CFGR |= (9 << 18);  // PLL倍頻9倍,HSE 8MHz * 9 = 72MHzRCC_CR |= (1 << 24);  // 啟用PLLwhile (!(RCC_CR & (1 << 25)));  // 等待PLL就緒RCC_CFGR |= (2 << 0);  // 切換系統時鐘到PLLwhile ((RCC_CFGR & 0x0C) != 0x08);  // 等待切換完成
}void GPIO_Init(void) {// 啟用GPIOA時鐘RCC_APB2ENR |= (1 << 2);  // IOPAEN// 配置PA1為輸入(門傳感器),假設帶上拉GPIOA_CRL &= ~(0xF << 4);  // 清除PA1配置GPIOA_CRL |= (0x8 << 4);   // 輸入模式,帶上拉/下拉// 配置PA2和PA3為推挽輸出(溫控設備和報警)GPIOA_CRL &= ~(0xF << 8);   // 清除PA2配置GPIOA_CRL |= (0x3 << 8);    // 推挽輸出,50MHzGPIOA_CRL &= ~(0xF << 12);  // 清除PA3配置GPIOA_CRL |= (0x3 << 12);   // 推挽輸出,50MHz// 配置PA9為USART1 TX(復用推挽輸出),PA10為USART1 RX(輸入浮空)GPIOA_CRH &= ~(0xF << 4);   // 清除PA9配置GPIOA_CRH |= (0xB << 4);    // 復用推挽輸出,50MHzGPIOA_CRH &= ~(0xF << 8);   // 清除PA10配置GPIOA_CRH |= (0x4 << 8);    // 輸入浮空
}void USART1_Init(void) {// 啟用USART1時鐘RCC_APB2ENR |= (1 << 14);  // USART1EN// 配置USART1波特率為9600,72MHz時鐘USART1_BRR = 0x1D4C;  // 72MHz / 9600 = 7500 -> 0x1D4CUSART1_CR1 |= (1 << 13);  // 啟用USARTUSART1_CR1 |= (1 << 3) | (1 << 2);  // 啟用TX和RX
}void Delay_ms(uint32_t ms) {for (uint32_t i = 0; i < ms * 1000; i++) {__asm__("nop");  // 無操作指令實現延遲}
}int main(void) {SystemInit();GPIO_Init();USART1_Init();DHT22_Init();DoorSensor_Init();DS1302_Init();ESP8266_Init();float temperature, humidity;int doorStatus;char timeStr[20];while (1) {temperature = DHT22_ReadTemperature();humidity = DHT22_ReadHumidity();doorStatus = DoorSensor_Read();DS1302_GetTime(timeStr);// 溫濕度閾值檢查(示例閾值:溫度>25°C或濕度>60%)if (temperature > 25.0 || humidity > 60.0) {GPIOA_ODR |= (1 << HEATER_PIN);  // 開啟溫控設備GPIOA_ODR |= (1 << ALARM_PIN);   // 開啟報警} else {GPIOA_ODR &= ~(1 << HEATER_PIN);  // 關閉溫控設備GPIOA_ODR &= ~(1 << ALARM_PIN);   // 關閉報警}// 準備數據并上傳到華為云char data[100];sprintf(data, "Time: %s, Temp: %.2f, Humidity: %.2f, Door: %d", timeStr, temperature, humidity, doorStatus);ESP8266_SendData(data);Delay_ms(5000);  // 每5秒執行一次}
}

總結

本系統基于STM32F103C8T6微控制器核心板,成功設計并實現了一個智能醫療藥品存儲柜系統,能夠實時監測柜內溫濕度及門開關狀態,并在溫濕度超標時自動啟動溫控設備并觸發報警,確保了藥品存儲環境的安全與穩定。該系統通過集成多種傳感器和執行器,實現了高效的本地控制與數據處理。

硬件組成包括DHT22溫濕度傳感器用于環境監測、干簧管門磁傳感器檢測門狀態、DS1302時鐘模塊記錄精確時間、以及ESP8266-01S Wi-Fi模塊負責云平臺通信。所有組件通過洞洞板焊接的信號處理電路和杜邦線連接,確保了系統的可靠性和擴展性,為后續功能升級提供了基礎。

數據上傳至華為云平臺,實現了藥品存取記錄和環境數據的遠程存儲與訪問,用戶可以通過云服務實時監控柜內狀態并接收報警信息,提升了醫療藥品管理的智能化和遠程化水平。此外,系統支持與QT上位機軟件的交互,便于藥品管理、歷史數據查詢和報警處理,增強了用戶體驗和操作便利性。

總體而言,該系統結合了嵌入式技術、物聯網云平臺和上位機軟件,為醫療行業提供了一種高效、可靠的藥品存儲解決方案,具有較高的實用價值和推廣前景。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/95413.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/95413.shtml
英文地址,請注明出處:http://en.pswp.cn/web/95413.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python批量調用大模型API:多線程和異步協程

文章目錄 多線程批量調用 基本原理 實現代碼 代碼解析 使用注意事項 異步協程實現批量調用 異步協程實現方式 異步實現的核心原理 多線程 vs 異步協程 選擇建議 多線程批量調用 基本原理 多線程批量調用大模型API的核心思想是通過并發處理提高效率,主要原理包括: 并發請求:…

硬件開發1-51單片機1

一、嵌入式1、概念&#xff1a;以應用為中心&#xff0c;以計算機技術為基礎&#xff0c;軟硬件可裁剪的專用計算機系統以應用為中心&#xff1a;系統設計的起點是 “具體應用場景”&#xff0c;按照應用需求出發以計算機技術為基礎&#xff1a; 硬件技術&#xff1a;嵌…

Redis核心數據類型解析——string篇

Redis的常見數據類型Redis 提供了 5 種數據結構&#xff0c;理解每種數據結構的特點對于 Redis 開發運維?常重要&#xff0c;同時掌握每 種數據結構的常?命令&#xff0c;會在使? Redis 的時候做到游刃有余。預備在正式介紹 5 種數據結構之前&#xff0c;了解?下 Redis 的?…

爬蟲逆向--Day20Day21--扣JS逆向練習【案例4:深證信服務平臺】

一、案例【深證信數據服務平臺】案例地址鏈接&#xff1a;https://webapi.cninfo.com.cn/#/marketDataDate案例爬取鏈接&#xff1a;https://webapi.cninfo.com.cn/api/sysapi/p_sysapi10071.1、入口定位當進行入口定位時&#xff0c;我們首先需要進行查看響應、載荷、請求頭是…

ExcelJS實現導入轉換HTML展示(附源碼可直接使用)

目錄 簡介 開始實踐 難點 文件示例 效果預覽 具體實現 安裝 完整代碼 總結 簡介 在日常工作中&#xff0c;我們可能會遇到需要上傳并展示 Excel 文件的需求&#xff0c;實現文件內容的在線預覽。 這里給大家接收一個組件庫exceljs&#xff0c;這個組件庫進過實踐發現…

ECDH和數字簽名

文章目錄一、核心區別&#xff1a;目的完全不同二、協同工作關系&#xff1a;缺一不可的安全組合三、技術結合點&#xff1a;都基于ECC(橢圓曲線密碼學)ECDH&#xff08;橢圓曲線迪菲-赫爾曼密鑰交換&#xff09;和數字簽名&#xff08;如ECDSA&#xff0c;橢圓曲線數字簽名算法…

withCredentials(簡單說:帶不帶憑證)

一、withCredentials是什么&#xff1f;withCredentials 是瀏覽器 XMLHttpRequest 或 Fetch API&#xff08;以及 axios 等基于它們的庫&#xff09;中的一個配置項&#xff0c;作用是控制跨域請求時是否攜帶 Cookie、HTTP 認證信息等憑證。用更通俗的方式解釋&#xff1a;二、…

window系統使用命令行來安裝OpenSSH服務器或客戶端

可以通過 PowerShell 命令行來安裝&#xff0c;這種方式更直接可靠&#xff1a;以管理員身份打開 PowerShell&#xff1a; 按下 Win S 搜索 “PowerShell”右鍵點擊 “Windows PowerShell”&#xff0c;選擇"以管理員身份運行"安裝 OpenSSH 客戶端&#xff1a; Add-…

vim中常見操作及命令

在 Vim 中為所有行的行首添加相同字符&#xff0c;可以使用以下方法&#xff1a; 方法1&#xff1a;使用 :%s 替換命令&#xff08;推薦&#xff09; vim :%s/^/要添加的字符/ 例如要在所有行首添加 #&#xff1a;vim :%s/^/#/ 方法2&#xff1a;使用塊選擇模式&#xff08;可視…

開發使用mybatis是用混合模式還是全注解模式

在使用 MyBatis 開發項目時&#xff0c;Mapper 接口是為數據庫操作提供最直觀的方法&#xff0c;但在實現方式上&#xff0c;我們有兩種選擇&#xff1a;全注解模式和混合模式。那么&#xff0c;他們有什么區別&#xff0c;應該如何選擇&#xff1f;我們一起來討論一下。一、全…

WS2812燈帶效果設計器上位機

軟件使用方法介紹&#xff1a;bilibili地址 【免寫單片機代碼WS2812燈帶效果設計軟件-嗶哩嗶哩】 https://b23.tv/xFhxMGm

Docker 容器(二)

Docker四、Docker容器數據卷1.數據卷的主要特點2.卷的共享與繼承&#xff08;1&#xff09;卷的共享&#xff08;Sharing&#xff09;(2) 卷的繼承&#xff08;Inheritance&#xff09;3.數據卷運行實例五、Dockerfile1.Dockerfile2. 創建一個名為 myubuntu的自定義鏡像第 1 步…

PCB基礎細節--工藝篇

pcb基礎細節&#xff08;工藝篇&#xff09; 1. 孔與焊盤2. PCB各層之間的作用3. 阻抗匹配 3.1. 什么是傳輸線&#xff1f;我們只看特性阻抗&#xff0c;時延以后再說。 在畫原理圖時&#xff0c;我們把電阻&#xff0c;電容&#xff0c;電感是抽象成一個點了。兩邊加一個電壓&…

信創服務器總死機原因及解決辦法

哈嘍&#xff0c;你好啊&#xff0c;我是雷工&#xff01;最近有個項目使用信創的服務器&#xff0c;總是出現死機的情況&#xff0c;聯系廠家檢查了一下&#xff0c;說是沐創網卡固件較低造成的&#xff0c;讓移除網卡或升級固件嘗試一下。記得5月份按廠家的說法處理過一臺&am…

03_網關ip和端口映射(路由器轉發)操作和原理

網關ip和端口映射&#xff08;路由器轉發&#xff09;操作和原理IP 與端口映射配置全指南&#xff1a;2 種方案搞定外網訪問內網一、先搞懂&#xff1a;為什么需要 IP 與端口映射&#xff1f;二、方案一&#xff1a;路由器端口映射&#xff08;適合有公網 IP&#xff0c;長期穩…

「數據獲取」《安徽建設統計年鑒》(2002-2007)(2004、2006缺失)(獲取方式看綁定的資源)

01、數據簡介《安徽建設統計年鑒》是一部全方位反映安徽省建設事業發展變遷的重要統計資料著作。該書系統收集并精心整理了 2006 年度安徽省城鄉建設領域的核心統計數據&#xff0c;涵蓋城鄉建設固定資產投資、建筑業發展態勢、城鎮建設推進情況等多個關鍵方面&#xff0c;為政…

Python/JS/Go/Java同步學習(第一篇)格式化/隱藏參數一鍋端 四語言輸出流參數宇宙(附源碼/截圖/參數表/避坑指南/老板沉默術)

&#x1f91d; 免罵聲明&#xff1a; 本文四語言輸出流參數經本蜀黎實戰整理&#xff0c;旨在提供快速參考指南&#x1f4dd;因各語言版本迭代及不同系統環境差異&#xff0c;偶爾可能出現整理不全面之處&#xff0c;實屬正常?歡迎理性交流補充&#xff0c;噴子勿噴——畢竟你…

人工智能助力流感疫苗選擇:MIT 團隊推出 VaxSeer 系統

每周跟蹤AI熱點新聞動向和震撼發展 想要探索生成式人工智能的前沿進展嗎&#xff1f;訂閱我們的簡報&#xff0c;深入解析最新的技術突破、實際應用案例和未來的趨勢。與全球數同行一同&#xff0c;從行業內部的深度分析和實用指南中受益。不要錯過這個機會&#xff0c;成為AI領…

使用 qmake 生成 Makefile,Makefile 轉換為 Qt 的 .pro 文件

使用 qmake 生成 Makefile 的完整指南 qmake 是 Qt 提供的構建工具&#xff0c;用于從 .pro 項目文件生成 Makefile。以下是詳細的使用方法&#xff1a; 基本使用方法 1. 從 .pro 文件生成 Makefile bash qmake -o Makefile your_project.pro2. 直接運行 qmake&#xff08;自動…

利用DeepSeek編寫驗證xlsx格式文件中是否啟用sharedStrings.xml對讀寫效率影響python程序

讓他分別用100*10000個單元格有100、1000、10000個不同的1-200字符長的大寫英文字母字符串測試. 一開始DeepSeek沒有找到啟用sharedStrings.xml的寫xlsx模塊&#xff0c;我自己找了pyxlsbwriter的例子告訴他才改好的。 import os import time import random import string impo…