9/8我是ai大師

一、變量定義部分(理解程序的 "記憶")

c

運行

/* USER CODE BEGIN PV */
static uint8_t last_button_state = 1; // 初始為高電平(未按下)
static uint8_t device_mode = 0; // 設備模式:0=LD1, 1=LD3, 2=蜂鳴器, 3=全部關閉
static uint8_t device_state[3] = {0, 0, 0}; // 設備狀態:0=關, 1=開
/* USER CODE END PV */

這部分定義了程序運行中需要 "記住" 的變量,就像人的短期記憶:

  • last_button_state:記錄上一次按鍵的狀態(1 = 未按下,0 = 按下),用于檢測按鍵的 "變化"(從按下到松開或反之)。初始值為 1,因為按鍵未按下時默認是高電平(硬件上拉)。
  • device_mode:記錄當前操作的設備模式(0-3 分別對應不同設備),類似遙控器的 "模式切換"。
  • device_state[3]:數組,分別記錄 3 個設備的開關狀態(索引 0=LD1,1=LD3,2 = 蜂鳴器),0 表示關,1 表示開。

二、函數聲明(提前 "告知" 程序要用到的功能)

c

運行

/* USER CODE BEGIN PFP */
void beep_short(void);
/* USER CODE END PFP */

這行代碼是函數聲明,告訴編譯器:后面會定義一個叫beep_short的函數,無參數、無返回值。作用是提前 "報備",避免編譯器在遇到函數調用時不認識該函數。

三、初始化代碼(程序啟動時的 "準備工作")

c

運行

/* USER CODE BEGIN 2 */
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET);  // LD1關閉
HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); // LD3關閉
HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); // 蜂鳴器關閉// 開機提示音
beep_short();
HAL_Delay(200);
beep_short();
/* USER CODE END 2 */

這部分是程序啟動后首先執行的初始化操作:

  1. 關閉所有外設:通過HAL_GPIO_WritePin函數將 3 個設備的引腳設為低電平(GPIO_PIN_RESET),確保程序啟動時所有設備都是關閉狀態。
    • LD1 接在 GPIOC 的 Pin4
    • LD3 接在 GPIOC 的 Pin13
    • 蜂鳴器接在 GPIOA 的 Pin15
  2. 開機提示音:調用beep_short函數讓蜂鳴器短響兩次(間隔 200ms),提示程序已正常啟動。

四、主循環邏輯(程序的 "核心動作",反復執行)

這部分在while(1)循環中,是程序運行時一直在重復做的事情,就像人反復 "觀察→判斷→行動" 的過程。

1. 讀取當前按鍵狀態

c

運行

uint8_t current_button_state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9);

  • 通過HAL_GPIO_ReadPin函數讀取按鍵引腳(GPIOC 的 Pin9)的當前狀態(1 = 未按下,0 = 按下),并存在current_button_state變量中。
2. 檢測按鍵 "按下" 動作(下降沿檢測)

c

運行

if (last_button_state == 1 && current_button_state == 0) {// 按鍵從"未按下"變為"按下"(下降沿)HAL_Delay(20); // 防抖延時current_button_state = HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9);if (current_button_state == 0) { // 確認按鍵確實按下// 按鍵處理邏輯...}
}

這是按鍵檢測的核心邏輯,作用是準確識別一次有效的按鍵按下

  • 條件last_button_state == 1 && current_button_state == 0:判斷按鍵是否從 "未按下"(1)變為 "按下"(0),這種變化叫 "下降沿"。
  • HAL_Delay(20):延時 20ms,是為了 "消抖"—— 按鍵機械結構會導致按下瞬間有微小抖動(狀態快速變化),延時后再讀一次狀態,避免誤判。
  • 再次判斷current_button_state == 0:確認按鍵確實處于按下狀態,排除抖動干擾。
3. 按鍵按下后的處理

當確認按鍵按下后,執行以下操作:

(1)按鍵提示音

c

運行

beep_short(); // 調用蜂鳴器短響函數,反饋按鍵已被按下
(2)切換設備模式

c

運行

device_mode = (device_mode + 1) % 4;

  • device_mode從 0 開始,每次按鍵加 1,通過%4(取余 4)實現循環:0→1→2→3→0→...,對應 4 種模式的切換。
(3)根據模式控制外設(核心邏輯)

通過switch-case語句,根據當前device_mode執行不同操作:

c

運行

switch(device_mode) {case 0: // 控制LD1device_state[0] = !device_state[0]; // 取反:0→1(開),1→0(關)// 控制LD1引腳狀態(開=高電平,關=低電平)HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, device_state[0] ? GPIO_PIN_SET : GPIO_PIN_RESET);// 關閉其他設備,確保每次只控制一個設備HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);device_state[1] = 0; // 同步更新其他設備的狀態記錄device_state[2] = 0;break;// case 1(控制LD3)、case 2(控制蜂鳴器)邏輯與case 0類似,只是操作的引腳不同case 3: // 全部關閉模式// 關閉所有設備引腳HAL_GPIO_WritePin(GPIOC, GPIO_PIN_4, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET);HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET);// 同步更新所有設備狀態為0(關)device_state[0] = 0;device_state[1] = 0;device_state[2] = 0;break;
}

邏輯要點:

  • 每個模式只控制一個設備,同時關閉其他設備(避免多個設備同時工作)。
  • device_state數組記錄設備狀態,方便下次切換時判斷當前狀態(開 / 關)。
  • 通過三元運算符device_state[0] ? GPIO_PIN_SET : GPIO_PIN_RESET快速設置引腳狀態(開 = 高電平,關 = 低電平)。
4. 等待按鍵釋放并更新狀態

c

運行

// 等待按鍵釋放
while (HAL_GPIO_ReadPin(GPIOC, GPIO_PIN_9) == 0) {// 空循環,直到按鍵松開(狀態變為1)
}
HAL_Delay(20); // 釋放時的防抖延時

  • 這部分確保一次按鍵只觸發一次模式切換,避免按鍵長按導致多次切換。
  • 按鍵松開后再延時 20ms,進一步消除釋放時的機械抖動。
5. 更新按鍵狀態記錄

c

運行

last_button_state = current_button_state;

  • 將當前按鍵狀態保存到last_button_state,為下一次循環的 "狀態變化檢測" 做準備。

五、蜂鳴器短響函數(封裝重復功能)

c

運行

/* USER CODE BEGIN 4 */
void beep_short(void)
{HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_SET); // 蜂鳴器開啟(高電平)HAL_Delay(100); // 持續100msHAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, GPIO_PIN_RESET); // 蜂鳴器關閉(低電平)
}
/* USER CODE END 4 */

  • 這是一個封裝好的函數,實現蜂鳴器短響 100ms 的功能。
  • 好處:避免重復寫相同代碼,需要蜂鳴器提示時直接調用beep_short()即可,讓程序更簡潔。

總結:程序的整體流程

  1. 初始化:關閉所有設備,蜂鳴器響兩次提示啟動。
  2. 循環檢測:反復讀取按鍵狀態,判斷是否有有效按下。
  3. 按鍵處理:確認按鍵按下后,切換模式→控制對應設備(開 / 關)→關閉其他設備→等待按鍵釋放。
  4. 狀態記錄:通過變量記錄按鍵狀態和設備狀態,實現 "記憶" 功能。

關鍵思路提煉(自己寫時可復用)

  1. 按鍵檢測:通過 "上一次狀態 + 當前狀態" 判斷按鍵變化(下降沿),加延時消抖。
  2. 狀態管理:用變量 / 數組記錄設備狀態,方便切換時判斷當前狀態。
  3. 模式切換:用switch-case或數組索引實現多模式循環。
  4. 功能封裝:重復使用的功能(如蜂鳴器提示)寫成函數,簡化代碼。

理解這些邏輯后,你可以嘗試修改設備引腳、增加更多模式(如控制 4 個設備),或者改用中斷方式檢測按鍵,逐步掌握 STM32 的 GPIO 控制編程。

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

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

相關文章

前沿重器[74] | 淘寶RecGPT:大模型推薦框架,打破信息繭房

前沿重器欄目主要給大家分享各種大廠、頂會的論文和分享,從中抽取關鍵精華的部分和大家分享,和大家一起把握前沿技術。具體介紹:倉頡專項:飛機大炮我都會,利器心法我還有。(算起來,專項啟動已經…

jenkins加docker 部署項目

jenkins加docker 部署springboot項目 1項目結構Dockerfile 內容 FROM openjdk:8-jdk-alpine ARG JAR_FILEtarget/*.jar COPY ${JAR_FILE} app.jar ENTRYPOINT ["java","-jar","/app.jar","--server.port9090"]在A服務器上啟動jenkins …

提示詞工程(Prompt Engineering)的崛起——為什么“會寫Prompt”成了新技能?

🎀【開場 貓貓狐狐的對話】🐾貓貓扒著屏幕:“喵?咱寫的這句 Prompt 怎么又跑偏啦?明明只是想讓它幫忙寫一段 Python 代碼,它偏要給咱寫論文摘要……” 🦊狐狐瞇著眼,聲音帶點冷意&a…

供應鏈管理系統入門知識:是什么,功能模塊,怎么定制開發?

如果你是剛接觸企業運營的新手,聽到 “供應鏈管理系統” 可能會覺得有點復雜。其實,它就像一個 “智能管家”,幫企業把從買材料到賣產品的一系列流程管得明明白白。今天就用大白話給你講清楚這個系統到底是什么,以及它能幫上什么忙…

kotlin - 平板分屏,左右拖動,2個Activity計算寬度,使用ActivityOptions、Rect(三)

kotlin - 平板分屏,左右拖動,2個Activity計算寬度,使用ActivityOptions、Rect使用平板,api33才支持,可以左右拖動,分屏第一個頁面 , 思考:分屏后,對整個app的影響&#x…

v0.29.3 敏感詞性能優化之繁簡體轉換 opencc4j 優化

敏感詞性能調優系列 v0.29.0 敏感詞性能優化提升 14 倍全過程 v0.29.1 敏感詞性能優化之內部類迭代器內部類 v0.29.2 敏感詞性能優化之基本類型拆箱、裝箱的進一步優化的嘗試 v0.29.3 敏感詞性能優化之繁簡體轉換 opencc4j 優化 背景 opencc4j opencc4j 中,因…

Spark SQL解析查詢parquet格式Hive表獲取分區字段和查詢條件

首先說一下,這里解決的問題應用場景: sparksql處理Hive表數據時,判斷加載的是否是分區表,以及分區表的字段有哪些?再進一步限制查詢分區表必須指定分區? 這里涉及到兩種情況:select SQL查詢和…

谷歌發布文本嵌入模型EmbeddingGemma(附部署方式)

EmbeddingGemma是谷歌于2025年9月開源的開放式文本嵌入模型,專為端側設備設計,具備以下核心優勢: 性能優勢 在MTEB基準測試中,EmbeddingGemma在500M以下參數規模的多語言文本嵌入模型中表現最佳,性能接近參數翻倍的頂…

CPU調度——調度的目標

2.2.2 調度的目標 當系統中“想運行”的實體多于 CPU 的數量時,調度就不可避免地要在“效率”與“公平”之間做取舍。直觀地說,一類目標希望把硬件壓榨到更高的利用率,讓單位時間內做更多的工作;另一類目標則關心個體體驗&#x…

C++ 8

封裝一個學生的類&#xff0c;定義一個學生這樣類的vector容器, 里面存放學生對象&#xff08;至少3個&#xff09;再把該容器中的對象&#xff0c;保存到文件中。再把這些學生從文件中讀取出來&#xff0c;放入另一個容器中并且遍歷輸出該容器里的學生。#include <iostream…

短視頻矩陣系統源碼開發搭建技術指南--支持OEM

短視頻矩陣系統架構設計短視頻矩陣系統通常采用分布式架構&#xff0c;包含內容管理、用戶管理、推薦算法、存儲分發等模塊。主流技術棧包括微服務框架&#xff08;Spring Cloud/Dubbo&#xff09;、消息隊列&#xff08;Kafka/RabbitMQ&#xff09;、數據庫&#xff08;MySQL/…

不連續頁分配器補充

vmalloc流程 1. 背景&#xff1a;vmalloc() 要解決的問題 kmalloc() 要求 虛擬地址連續&#xff0c;物理頁也連續。大塊內存分配可能失敗。vmalloc() 只保證 虛擬地址連續&#xff0c;物理內存可以由很多不連續的頁拼接。 實現的關鍵就是&#xff1a; 在 vmalloc 區域 找一塊空…

bug | 事務粒度不能太大,含demo

刷到一個說法&#xff0c;建議不要使用transaction注解。這個說法不太準確&#xff0c;注解可以用&#xff0c;但標注的事務粒度不能太大&#xff0c;這樣可能會引起數據庫阻塞問題。以下介紹注解事務和編程式事務的兩種用法。 關鍵字&#xff1a;聲明式事務&#xff0c;編程式…

別再看人形機器人了!真正干活的機器人還有這些!

每次提起“機器人”&#xff0c;你腦海中是不是立刻浮現出雙足行走、擬人微笑、還能陪你聊天的那種“人形機器人”&#xff1f;但真相是&#xff1a;人形機器人并非更實用&#xff0c;只是滿足了我們對“人類替代品”的幻想。事實上&#xff0c;機器人的世界遠比我們想象的更豐…

垃圾回收,幾種GC算法及GC機制

1.什么是垃圾回收&#xff1f;如何觸發垃圾回收&#xff1f; 垃圾回收(GC)是自動管理內存的一種機制&#xff0c;它負責自動釋放不再被程序引用的對象所占用的內存&#xff0c;這種機制減少內存泄漏和內存管理錯誤的可能性。可以通過多種方式觸發&#xff1a;內存不足時&#x…

更智能的零售終端設備管理:合規、安全與高效

目錄 引言&#xff1a;為什么零售連鎖和自助終端需要更智能的設備管理&#xff1f; 典型應用場景 1. 便利店連鎖 2. 大型超市 3. 加油站 4. 自助終端 核心功能&#xff0c;驅動高效與安全 1. 批量配置 2. 定時策略同步 3. 設備狀態監控 4. Kiosk 模式&#xff0c;保…

Elasticsearch:向量搜索過濾 - 保持相關性

作者&#xff1a;來自 Elastic Carlos Delgado 僅執行向量搜索以找到與查詢最相似的結果是不夠的。通常需要過濾來縮小搜索結果。本文解釋了在 Elasticsearch 和 Apache Lucene 中向量搜索的過濾是如何工作的。 Elasticsearch 擁有豐富的新功能&#xff0c;幫助你為自己的用例構…

Linux 性能調優之 OOM Killer 的認知與觀測

寫在前面 博文內容涉及到OOM Killer機制,以及利用 Cgroup/dmesg/BPF 觀測 OOM Killer 事件,包括云原生環境下的 OOM Killer 機制的簡單介紹 這是內存調優的最后一篇,之后會分享一些網絡調優相關內容 理解不足小伙伴幫忙指正 ??,生活加油 我不再將這個世界與我所期待的,塑…

webrtc之高通濾波——HighPassFilter源碼及原理分析

文章目錄前言一、導讀二、高通濾波過程1.HighPassFilter的創建1&#xff09;HighPassFilter的作用2&#xff09;開啟條件3&#xff09;開啟配置2.高通濾波整體過程1&#xff09;觸發時機2&#xff09;濾波器創建3&#xff09;高通濾波過程三、算法實現1.原理1&#xff09;濾波器…

《sklearn機器學習——聚類性能指數》同質性,完整性和 V-measure

函數&#xff1a;homogeneity_score 參數&#xff1a; labels_true: array-like, shape [n_samples] 樣本的真實標簽。 labels_pred: array-like, shape [n_samples] 樣本的預測標簽。返回值&#xff1a; h: float 同質性得分&#xff0c;在0到1之間&#xff0c;值越大表示聚…