基于外部中中斷機制,實現以下功能: 1.按鍵1,按下和釋放后,點亮LED 2.按鍵2,按下和釋放后,熄滅LED 3.按鍵3,按下和釋放后,使得LED閃爍

題目:

參照外部中斷的原理和代碼示例,再結合之前已經實現的按鍵切換LED狀態的實驗,用外部中斷改進其實現。

請自行參考文檔《中斷》當中,有關按鍵切換LED狀態的內容, 自行連接電路圖,基于外部中斷機制,實現以下功能:

1.按鍵1,按下和釋放后,點亮LED

2.按鍵2,按下和釋放后,熄滅LED

3.按鍵3,按下和釋放后,使得LED閃爍

具體按鍵的電路接法,可以直接參考文檔的內容去實現。


關鍵點


分析:

按鍵外部中斷實驗
在這里插入圖片描述


代碼

// 完成實驗代碼
#include "stm32f10x.h"
#include "Delay.h"#define LED_NORMAL 0   // LED 正常狀態
#define LED_BLINK 1   // LED 閃爍狀態uint8_t LED_State = LED_NORMAL;  // LED 默認正常狀態
void KEY_GPIO_Init(void);//初始化GPIO引腳
void KEY_AFIO_Map(void);//AFIO映射PA11到EXTI_Line11
void KEY_EXTI_Init(void);//初始化 EXTI 配置(EXTI_Line11)
void KEY_NVIC_Init(void);//初始化NVIC,開啟EXTI9_5_IRQn外部中斷
void EXTI9_5_IRQHandler(void);//中斷服務程序
void EXTI0_IRQHandler(void);
int main(void) {KEY_GPIO_Init();KEY_AFIO_Map();KEY_EXTI_Init();KEY_NVIC_Init();GPIO_SetBits(GPIOA, GPIO_Pin_5);while (1) {if (LED_State == LED_BLINK) {GPIO_SetBits(GPIOA, GPIO_Pin_5);Delay_Ms(100);//當LED閃爍時如果不加入這行代碼,//可能會引發按鍵操作點亮時,LED表現為熄滅狀態//這是因為當GPIO_Pin_6引發中斷時正好處在延遲時候,while循環沒結束//當GPIO_Pin_6中斷執行后,可能會執行GPIO_ResetBits(GPIOA,GPIO_Pin_5);if (LED_State == LED_NORMAL) {continue;}GPIO_ResetBits(GPIOA, GPIO_Pin_5);Delay_Ms(100);}}
}void KEY_GPIO_Init(void) {//開啟GPIO外設時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);//初始化P0引腳GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//上拉輸入模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);//初始化P6和P8引腳GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_8;//下拉輸入模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//推免輸出模式GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);
}void KEY_AFIO_Map(void) {//開啟AFIO外設時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);// 映射 PA0 到 EXTI_Line0GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);// 映射 PB6 到 EXTI_Line6GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource6);// 映射 PB8 到 EXTI_Line8GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource8);}void KEY_EXTI_Init(void) {EXTI_InitTypeDef EXTI_InitStructure;EXTI_InitStructure.EXTI_Line = EXTI_Line0 ;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中斷模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; //采用下降沿觸發EXTI_Init(&EXTI_InitStructure);EXTI_InitStructure.EXTI_Line = EXTI_Line6 | EXTI_Line8 ;EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt; //中斷模式EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising; //采用上升沿觸發EXTI_Init(&EXTI_InitStructure);}void EXTI9_5_IRQHandler(void) {if (EXTI_GetITStatus(EXTI_Line6) == SET) {// 清除中斷標志EXTI_ClearITPendingBit(EXTI_Line6);//檢查引腳輸入,如果是高電平說明按下還沒有松開。while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6) == Bit_SET);
LED_State = LED_NORMAL;//低電平點亮LEDGPIO_ResetBits(GPIOA, GPIO_Pin_5);}if (EXTI_GetITStatus(EXTI_Line8) == SET) {// 清除中斷標志EXTI_ClearITPendingBit(EXTI_Line8);//檢查引腳輸入,如果是高電平說明按下還沒有松開。while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_8) == Bit_SET);
LED_State = LED_NORMAL;//高電平熄滅LEDGPIO_SetBits(GPIOA, GPIO_Pin_5);}}void EXTI0_IRQHandler(void) {if (EXTI_GetITStatus(EXTI_Line0) == SET) {// 清除中斷標志EXTI_ClearITPendingBit(EXTI_Line0);Delay_Ms(20);  // 簡單消抖while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET);LED_State = LED_BLINK;}}//  初始化NVIC外設
void KEY_NVIC_Init(void) {//將優先級進行分組NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//初始化NVIC外設NVIC_InitTypeDef NVIC_InitStruct;//設置中斷號NVIC_InitStruct.NVIC_IRQChannel = EXTI9_5_IRQn;//開啟中斷NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//初始化搶占優先級NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;//初始化子優先級NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;NVIC_Init(&NVIC_InitStruct);NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;//開啟中斷NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;//初始化搶占優先級NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0;//初始化子優先級NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0;NVIC_Init(&NVIC_InitStruct);}
#include "stm32f10x.h"
#include "Delay.h"#define LED_NORMAL 0   // LED 正常狀態(熄滅或者點亮)
#define LED_BLINK 1   // LED 閃爍狀態uint8_t LED_State = LED_NORMAL;  // LED 默認正常狀態/**
* @brief  按鍵初始化,配置 PB6, PB8 和 PA0 為外部中斷
* @param  無
* @retval 無
* 按鍵1控制LED點亮,它的兩腳接入電源正極和PB6引腳,
* 按鍵2控制LED熄滅,它的兩腳接入電源正極和PB8引腳,
* 按鍵3控制LED閃爍,它的兩腳接入電源正極和PA0引腳.
*///按鍵引腳的的初始化一級配件相關的外部中斷
void KEY_Init(void) {// 開啟 GPIOB 和 AFIO 時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);GPIO_InitTypeDef GPIO_InitStructure;// 配置 PB6 和 PB8 為下拉輸入模式(因為 按鍵 接正極,按下時會變為高電平)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_8;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; // 下拉輸入模式GPIO_Init(GPIOB, &GPIO_InitStructure);// 配置 PA0 為上拉輸入模式(因為 按鍵 接負極,按下時會變為低電平)GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // 上拉輸入模式GPIO_Init(GPIOA, &GPIO_InitStructure);// 使用AFIO外設將三個按鍵引腳映射到對應達到EXTI線GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource6); // PB6GPIO_EXTILineConfig(GPIO_PortSourceGPIOB, GPIO_PinSource8); // PB8GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0); // PA0EXTI_InitTypeDef EXTI_InitStructure;// 配置 EXTI6 和 EXTI8(PB6 和 PB8)為上升沿觸發EXTI_InitStructure.EXTI_Line = EXTI_Line6 | EXTI_Line8;EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;  // 上升沿觸發EXTI_InitStructure.EXTI_LineCmd = ENABLE;EXTI_Init(&EXTI_InitStructure);// 配置 EXTI0(PA0)為下降沿觸發EXTI_InitStructure.EXTI_Line = EXTI_Line0; // 選擇 PA0 對應的 EXTI0EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿觸發EXTI_Init(&EXTI_InitStructure);// NVIC 配置初始化NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);NVIC_InitTypeDef NVIC_InitStructure;// 配置 NVIC,處理 EXTI6, EXTI8 和 EXTI0 的中斷// 優先級都設置為相同的優先級NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn; // 處理 EXTI6 和 EXTI8 的中斷NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn; // 處理 EXTI0 的中斷NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);
}/**
* @brief  LED(PA3)初始化
* @param  無
* @retval 無
*/
void LED_Init(void) {// 開啟 GPIOA 時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);// 配置 PA3 為開漏輸出模式GPIO_InitTypeDef GPIO_InitStructure;GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_OD;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);// 設定初始狀態為 LED 關閉(PA3 高阻態)GPIO_SetBits(GPIOA, GPIO_Pin_3);
}/**
* @brief  外部中斷服務函數(ISR),處理 PB6 和 PB8 按鍵中斷
* @param  無
* @retval 無
*/
void EXTI9_5_IRQHandler(void) {// 檢查是否是 PB6 觸發的中斷if (EXTI_GetITStatus(EXTI_Line6) == SET) {// 清除 EXTI6 中斷標志EXTI_ClearITPendingBit(EXTI_Line6);// 按鍵持續按下,等待彈起while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_6) == Bit_SET);// 點亮 LED,設置LED為正常模式LED_State = LED_NORMAL;GPIO_ResetBits(GPIOA, GPIO_Pin_3);  // 低電平,點亮 LED}// 檢查是否是 PB8 觸發的中斷if (EXTI_GetITStatus(EXTI_Line8) == SET) {// 清除 EXTI8 中斷標志EXTI_ClearITPendingBit(EXTI_Line8);// 按鍵持續按下,等待彈起while (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_8) == Bit_SET);// 點亮 LED,設置LED為正常模式LED_State = LED_NORMAL;GPIO_SetBits(GPIOA, GPIO_Pin_3);  // 高電平,熄滅 LED}
}/**
* @brief  外部中斷服務函數(ISR),處理 PA0 按鍵中斷,LED閃爍
* @param  無
* @retval 無
*/
void EXTI0_IRQHandler(void) {if (EXTI_GetITStatus(EXTI_Line0) == SET) {// 清除 EXTI0 中斷標志EXTI_ClearITPendingBit(EXTI_Line0);while (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) == Bit_RESET);LED_State = LED_BLINK;}
}int main(void) {LED_Init();       // 初始化 LEDKEY_Init();       // 初始化 PB6, PB8 和 PA0 按鍵while (1) {if (LED_State == LED_BLINK) {// LED 進入閃爍狀態GPIO_ResetBits(GPIOA, GPIO_Pin_3);  // 點亮 LEDDelay_Ms(100);  // 延時 100ms/*Delay_Ms函數是使用中斷來實現的若LED在閃爍狀態下,按壓點亮LED按鍵恰好進入了上一個Delay_Ms函數等它中斷延時結束就會執行LED熄滅操作這樣點亮LED按鍵的功能就會失效,所以這里要加一個判斷然后跳過后面的熄燈邏輯*/if (LED_State == LED_NORMAL) {continue;}GPIO_SetBits(GPIOA, GPIO_Pin_3);    // 熄滅 LEDDelay_Ms(100);  // 延時 100ms}}
}

在這里插入圖片描述
閃爍這里線沒接對,豎著才行,豎著才是聯通的.
在這里插入圖片描述
在這里插入圖片描述
修正圖片
在這里插入圖片描述


解決方案總結:

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

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

相關文章

在SQL中,FROM子句中的子查詢必須指定別名,即使后續未引用該別名

FROM子句中的子查詢必須指定別名 示例錯誤示例及原因:總結: 在SQL中, FROM子句中的子查詢必須指定別名, 即使后續未引用該別名 示例 查詢館藏圖書最多的作者姓名及館藏數量 SELECT 作者, COUNT(圖書編號) AS 館藏數量 FROM 圖…

問道數碼獸 懷舊劇情回合手游源碼搭建教程(反查重優化版)

本文將對"問道數碼獸"這一經典卡通風格回合制手游的服務端部署與客戶端調整流程進行詳細拆解,適用于具備基礎 Windows 運維和手游源碼調試經驗的開發者參考使用。教程以實戰為導向,基于原始說明內容重構優化,具備較高的內容查重避重…

Shell腳本-for循環應用案例

在Shell腳本編程中,for循環是一種強大的工具,用于處理重復性任務。無論是批量處理文件、遍歷目錄內容還是簡單的計數任務,for循環都能提供簡潔而有效的解決方案。本文將通過幾個實際的應用案例來展示如何使用for循環解決具體的編程問題。 案…

Chrmo手動同步數據

地址欄輸入 chrome://sync-internals分別點擊這2個按鈕即可觸發手動同步

為什么圓形在GeoJSON中被表示為多邊形(Polygon)而不是圓形類型

GeoJSON規范中沒有"圓形"類型 GeoJSON是一種用于表示地理空間數據的標準格式,它的規范中只定義了以下幾種基本幾何類型: Point (點) LineString (線) Polygon (多邊形) MultiPoint (多點) MultiLineString (多線) MultiPolygon (多多邊形) GeometryCollection (幾…

大數據組件學習之--Kafka 安裝搭建

一、前置環境 在搭建kafka之前,請確認自己的hadoop、zookeeper是否搭建完成且可正常運行 二、下載并上傳安裝包(鏈接為百度網盤) kafka安裝包 tar -zxvf /opt/software/kafka_2.12-2.4.1.tgz -C /opt/module/ 進入解壓后的目錄更改文件名…

PyQt6基礎_pyqtgraph_折線圖with縮放調節

目錄 字符型橫坐標代碼 折線圖代碼 運行 創建新類,繼承pg.PlotWidget,在新類中實現業務內容,重寫pg.PlotWidget中的wheelEvent方法并使用業務數據實現比較理想的縮放狀態。 字符型橫坐標代碼 class StrAxisItem(pg.AxisItem):def __init…

聯邦元學習實現個性化物聯網的框架

隨著數據安全和隱私保護相關法律法規的出臺,需要直接在中央服務器上收集和處理數據的集中式解決方案,對于個性化物聯網而言,訓練各種特定領域場景的人工智能模型已變得不切實際。基于此,中山大學,南洋理工大學&#xf…

audio 核心服務AudioPolicyService 和AudioFlinger啟動流程

目錄 1、audioserver啟動 2、AudioPolicyService啟動 3、AudioFlinger啟動 audio的核心服務有兩個,AudioPolicyService 和AudioFlinger他們到在audioserver一個進程中 1、audioserver啟動 設備開機,系統啟動時將執行 /system/etc/init/audioserver.rc…

反爬蟲機制中的驗證碼識別:類型、技術難點與應對策略

在互聯網數據抓取領域,驗證碼識別是爬蟲過程中的關鍵環節之一。下面對常見驗證碼類型、技術難點及應對策略進行詳細解析,并提供多種場景下的代碼實現示例。 一、驗證碼類型與技術難點 (一)圖形驗證碼 1. 字符驗證碼 特征&#…

vue element使用el-table時,切換tab,table表格列項發生錯位問題

展示問題 問題描述:使用el-table的fixed"right"屬性后,如果切換tab時,回出現最后一列錯誤的問題 官網提供解決方法:doLayout 需要注意的事項:我這里是通過組件使用的table組件,涉及多層組件封裝…

示例:Spring JDBC 聲明式事務(xml配置形式)

聲明式事務是指在不修改源代碼的情況下通過配置applicationContext.xml自動實現事務控制,其本質是AOP環繞通知。它的觸發時機為:1、當目標方法執行成功時自動提交事務,2、當目標方法拋出運行時異常時,自動事務回滾 核心步驟示例&a…

在vmware中ubuntu系統因為安裝了docker查不到ip地址

問題截圖: 根據提供的截圖信息,可以明確看到ens33網卡處于**物理連接斷開(NO-CARRIER)且接口關閉(DOWN)**的狀態,這是導致無法獲取IP地址的直接原因。以下是針對VMware虛擬機的具體解決方案&am…

51c大模型~合集121

我自己的原文哦~ https://blog.51cto.com/whaosoft/13869815 #大模型何以擅長小樣本學習? 這項研究給出詳細分析 近年來,大語言模型(LLM)在人工智能領域取得了突破性進展,成為推動自然語言處理技術發展與通用人…

Babylon.js 材質統一轉換指南:將 AssetContainer 中的所有材質轉換為 PBRMetallicRoughnessMaterial

在現代 3D 開發中,基于物理的渲染(PBR)已成為行業標準。本文將詳細介紹如何在 Babylon.js 中將 AssetContainer 加載的各種材質統一轉換為 PBRMetallicRoughnessMaterial,實現項目材質的標準化。 為什么需要材質轉換? PBRMetallicRoughness…

Go slice切片使用教程,一次通關!

簡介 Go 中的 切片(slice) 是 Go 最強大、最常用的數據結構之一。它是對數組的輕量封裝,比數組更靈活,幾乎所有的集合處理都用切片來完成。 什么是切片(slice) 切片是一個擁有 長度(len&…

nodejs的包管理工具介紹,npm的介紹和安裝,npm的初始化包 ,搜索包,下載安裝包

nodejs的包管理工具介紹,npm的介紹和安裝,npm的初始化包 ,搜索包,下載安裝包 🧰 一、Node.js 的包管理工具有哪些? 工具簡介是否默認特點npmNode.js 官方的包管理工具(Node Package Manager&am…

FPGA設計 時空變換

1、時空變換基本概念 1.1、時空概念簡介 時鐘速度決定完成任務需要的時間,規模的大小決定完成任務所需要的空間(資源),因此速度和規模就是FPGA中時間和空間的體現。 如果要提高FPGA的時鐘,每個clk內組合邏輯所能做的事…

增加首屏圖片

增加首屏圖片&#xff08;bg.jpg&#xff09; web-mobile類型打包 //index.html腳本 <div id"myDiv_1111"style"background: url(./bg.jpg) 50% 50%/ 100% auto no-repeat ; width:100%;height:100%;position:absolute;"></div> //游戲內腳本…

貪心算法~~

目錄 一、理論基礎 二、題目練習 &#xff08;1&#xff09;455. 分發餅干 &#xff08;2&#xff09;53. 最大子數組和 - 力扣 &#xff08;3&#xff09;122. 買賣股票的最佳時機 II - 力扣&#xff08;LeetCode&#xff09; &#xff08;4&#xff09;860. 檸檬水找零…