[STM32]從零開始的STM32 BSRR、BRR、ODR寄存器講解

一、前言

? ? ? ? 學習STM32一陣子以后,相信大家對STM32 GPIO的控制也有一定的了解了。之前在STM32 LED的教程中也教了大家如何使用寄存器以及庫函數控制STM32的引腳從而點亮一個LED,之前的寄存器只是作為一個引入,并沒有深層次的講解,在教程中,也沒讓大家有太多的了解。既然學習STM32有一段時間了,那我們能不能從現象推導到本質,去了解一下STM32 引腳控制的本質原理。那么本次教程,就來為大家講解一下STM32引腳驅動的三個關鍵寄存器BSRR、BRR、ODR,相信看了本次教程以后,你對STM32會有更深層次的理解。如果你準備好了,那就讓我們開始吧!

二、誰適合本次教程

? ? ? ? 因為已經涉及到寄存器的操作與講解了,所以請學習本次教程的小伙伴需要具備一定的STM32基礎以及對十六進制轉二進制比較熟悉。

三、資料的準備

? ? ? ? 本次使用STM32F103C8T6進行演示,所以請大家自己準備一塊STM32F103的開發板。本次教程中,我們需要去翻閱STM32F103的手冊,所以大家準備一份STM32F103的數據手冊,相信學習過一陣子STM32的小伙伴應該都有這個手冊吧,這里我就不放了。

四、BSRR、BRR、ODR寄存器講解

? ? ? ? 在我們日常的代碼或者一些模塊的代碼中,可能經常會看到下面這樣的寫法:

GPIOC->BSRR=0x00002000;

又或者是這種寫法:

GPIOC->ODR=0x00002000;

我們可以很明顯的看到,這些寫法都是在控制GPIO的電平,那么這些寫法之間都有什么區別呢?哪種寫法更好呢?

1.BSRR

? ? ? ? 這里我們首先來看BSRR,這里我們打開STM32F10的中文手冊,找到BSRR寄存器處:

下面我們就來解釋一下這個寄存器的作用,很明顯的看到,這里寄存器的位下面只有一個W,表示這個寄存器只是可寫的:

這里大家只需要記住這個寄存器只能寫就可以了,后面會為大家講解為什么。

我們再往下看,下面的寄存器詳細描述中,將寄存器分為了兩個部分來講,分別是0-15位,以及16-31位,總的來說就是將這個寄存器分為了高十六位和低十六位:

這里我們先來看位16-31,這些位都被叫做BR位,這里的R即Reset,手冊中的描述是這些位是用于清除端口0-15:

簡單來說,16-31位就是用于將GPIO口拉低的。假如這里我想控制GPIOC,那么我就可以使用BSRR中的16-31位將GPIPC的0-16引腳全部拉低。

在下面也提到了,這些位只能寫入并且只能一十六位的形式寫入:

我們繼續往下看,如果BSRR的16-31位寫0不會對ODR產生影響,如果寫1,則ODR的對應位就會為0,從而引腳電平被拉低。至于這里為什么我們寫ODR的位就可以直接控制引腳我們后面講解ODR寄存器的時候會講。

然后我們來看BSRR的0-15位,這些位從手冊中可以看到,是用于置位GPIO口的某一位的,0-15位被叫做BS位,這里的S即Set:

同樣的,假如我還是控制GPIOC,那我就可以通過BSRR下的0-15位將GPIOC的0-15引腳都置高。同樣的,下面也提到了,如果給0-15位的某一位置0,則ODR對應的位不產生影響。如果給0-15位置1那么對應的ODR位就會置1從而對應的引腳置1:

這里大家就可能有疑惑了,如果我將一個引腳對應BS位和BR位都置位,會怎么樣?其實在手冊中已經提到了,如果這樣做的話,只有BR位會起作用:

看了上面的內容,相信大家對BSRR寄存器有一定的了解了,簡單來說,它就是一個控制ODR寄存器對應位高低電平從而控制引腳的一個寄存器,在官方的庫函數中,也使用到了BSRR寄存器來控制引腳電平:

這里大家可能又有疑問了,為什么我這里要通過BSRR來控制ODR從而來控制引腳的電平,我不能直接控制ODR嗎?這個問題,同樣也留到我們講解ODR的時候再做講解。

2.BRR

? ? ? ? BRR的功能和BSRR非常接近,以至于現在一些高端的芯片已經閹割了BRR寄存器,不過我們現在還是可以來看看,我們在手冊中找到BRR對應的描述:

我們可以看到BRR寄存器的高十六位是沒有作用的:

并且低十六位和BSRR一樣,只能寫:

這里我們直接看寄存器描述,這里提到了,0-15位主要用于清除端口的位,也就是為指定端口拉低。這里的用法其實和BSRR的高十六位一樣,都是通過給對應的位置1從而給ORD對應的位置0從而控制引腳電平。如果你理解BSRR的話,理解BRR也不是什么難題,這里就不多說了:

3.ODR

? ? ? ? 現在我們來講解ODR,前面已經為大家留了許多問題在ODR這里了,現在我們一一來解決。

我們同樣先在手冊中找到ODR所在的位置:

這里我們可以看到,ODR的高十六位同樣作為保留位。然后就是低十六位,這里的低十六位我們簡單來說就是,對應了GPIO的十六個引腳。我們給ODR對應的位置高或者置低,那么對應的GPIO引腳就會被置對應的電平。假如我么就將ODR的第12位置1,那么對應的GPIO12就會被置1。在手冊中也提到了,我們的BSRR寄存器可以對每個ODR位進行獨立的設置和清除:

這就是為什么我們要通過BSRR來操作ODR從而來操作GPIO。因為BSRR可以對ODR的每一位進行操作并且不影響別的位。如果我們直接操作ODR的話,要實現不影響別的位的效果就需要將ODR的值先讀出來然后再寫入對應的值最后整體寫入ODR,這也是我們常用的讀-改-寫的操作流程。那么大家可能又有疑問了,為什么我們的BSRR可以直接操作ODR。

這里我們在手冊中,找到“8.1.8輸出配置”,這里我們主要是需要下面的圖:

我們將下面的圖單獨拿出來:

這里我們可以看到,我們的寫入可以寫到“位設置/清除寄存器”,這個“位設置/清除寄存器”是什么?這不就是BSRR嗎?:

然后,我們寫入BSRR以后,BSRR直接就寫入了一個名為“輸出數據寄存器”的地方,這個輸出數據寄存器,不就是我們的ODR嗎?:

相當于,BSRR一旦收到數據,就會發送給ODR,從而對ODR的位進行操作。BSRR發送完數據以后,就直接將內部存儲的值扔掉了,本身就不保存值,所以讀取BSRR本很就沒有意義。這樣也印證了為什么之前我們說BSRR不能讀取。

最后,我們可以看到,我們的ODR上有一條單獨的線,是用于讀寫ODR的,這些表示ODR可以被直接讀寫:

其實,總的來說,為什么我們不直接操作ODR呢?因為我們操作BSRR可以直接操作ODR的值從而不影響別的引腳。為什么我們操作BSRR可以直接操作ODR呢?因為它們在物理總線層面被鏈接在了一起,并且操作BSRR可以直接操作ODR的位。為什么BSRR不能讀取呢?因為BSRR有了值以后直接就拿給ODR了,本身不存儲值,沒有讀取的必要。

假如我們執行下面兩段代碼,在實際效果上應該是一樣的:

#include "stm32f10x.h"                  
int main(void)
{RCC->APB2ENR=0x00000010;GPIOC->CRH=0x00300000;GPIOC->BSRR=0x00002000;while(1){}
}
#include "stm32f10x.h"                  
int main(void)
{RCC->APB2ENR=0x00000010;GPIOC->CRH=0x00300000;GPIOC->ODR=0x00002000;while(1){}
}

但是,最后的最后,仍然建議大家在操作引腳時不直接操作ODR,雖然我們可以通過讀-改-寫的方法保留原本的值并且寫入新值,但是,這樣會增加我們的代碼量并且增加出錯的概率。

五、結語

? ? ? ? 以上就是我對GPIO相關的寄存器的一些見解,如果有講得不對的地方,還請大家指正,最后感謝大家的觀看!

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

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

相關文章

SQL分組問題

下列為電商公司用戶訪問時間數據 統計某個用戶連續的訪問記錄,如果時間間隔小于60s,就分為一組 id ts 1001 17523641234 1001 17523641256 1002 17523641278 1001 17523641334 1002 17523641434 1001 17523641534 1001 17523641544 1002 17523…

3月2日 C++日常習題測試一答案

C測試題答案與講解 一、填空題答案及講解 答案:const 講解:在 C 中,const關鍵字用于定義常量,一旦定義,其值不能被修改。例如const int num 10;,這里的num就是一個常量。 答案:3 講解&…

2W8000字 LLM架構文章閱讀指北

? 大模型架構專欄已經更新了30多篇文章。完整的專欄內容歡迎訂閱: LLM 架構專欄 1、LLM大模型架構專欄|| 從NLP基礎談起 2、 LLM大模型架構專欄|| 自然語言處理(NLP)之建模 3、 LLM大模型架構之詞嵌入(Part1) 3、 LLM…

SP導入智能材質球

智能材質球路徑 ...\Adobe Substance 3D Painter\resources\starter_assets\smart-materials 放入之后就會自動刷新

網絡原理----TCP/IP(3)

核心機制七----延時應答 默認情況下,接收方都是在收到數據報的第一時間,就返回ack,但是可以通過延時返回ack的方式來提高效率,理論上不是100%提高效率,但還是有一定幫助的。 因為如果接收數據的主機?刻返回ACK應答,…

MacBook Pro使用FFmpeg捕獲攝像頭與麥克風推流音視頻

FFmpeg查看macos系統音視頻設備列表 ffmpeg -f avfoundation -list_devices true -i "" 使用攝像頭及麥克風同時推送音頻及視頻流: ffmpeg -f avfoundation -pixel_format yuyv422 -framerate 30 -i "0:1" -c:v libx264 -preset ultrafast -b:v 1000k -…

部署Joplin私有云服務器postgres版-docker compose

我曾經使用過一段時間 Joplin,官方版本是收費的,而我更傾向于將數據掌握在自己手中。因此,在多次權衡后,我決定自己搭建 Joplin 服務器并進行嘗試。 個人搭建的版本與數據庫直連,下面是使用 Docker Compose 配置數據庫…

SQL的select語句完整的執行順序

SQL的SELECT語句的執行順序可以用"做菜流程"來類比理解。雖然我們寫SQL時按SELECT…FROM…WHERE…順序寫,但數據庫執行順序完全不同。以下是通俗易懂的講解(附流程圖和示例): 🔧 執行順序流程圖&#xff1a…

Spring Cloud LoadBalancer詳解

一、介紹 Spring Cloud LoadBalancer是Spring Cloud官方自己提供的客戶端負載均衡器,抽象和實現,用來替代Ribbon(已經停更), 二、Ribbon和Loadbalance 對比 組件組件提供的負載策略支持負載的客戶端Ribbon隨機 RandomRule輪詢 RoundRobinRule 重試 RetryRule最低并發 Bes…

ubuntu中ollama設置記錄

自己同一臺電腦主機安裝3080和3090顯卡,測試發現ollama只默認跑在3090上;故查看一下設置,成功也把3080也運行起來了。 原因如下: 開始設置記錄: Environment Variables: OLLAMA_DEBUG 作用:顯示額外的調試…

RabbitMQ系列(四)基本概念之Exchange

在 RabbitMQ 中,Exchange(交換機) 是消息路由的核心組件,負責根據規則將生產者發送的消息分發到對應的隊列(Queue)中。以下是其核心功能與分類的詳細說明: 一、Exchange 的核心作用 消息路由樞…

有沒有什么免費的AI工具可以幫忙做簡單的ppt?

互聯網各領域資料分享專區(不定期更新): Sheet 正文 1. 博思AIPPT 特點:專為中文用戶設計,支持文本/文件導入生成PPT,內置海量模板和智能排版功能,涵蓋商務、教育等多種場景。可一鍵優化布局、配色,并集成AI繪圖功能(文生圖/圖生圖)。適用場景:職場匯報、教育培訓、商…

【Python · PyTorch】循環神經網絡 RNN(基礎應用)

【Python PyTorch】循環神經網絡 RNN(簡單應用) 1. 簡介2. 模擬客流預測(數據集轉化Tensor)3.1 數據集介紹3.2 訓練過程 3. 模擬股票預測(DataLoader加載數據集)3.1 IBM 數據集3.1.2 數據集介紹3.1.3 訓練…

【JSON2WEB】15 銀河麒麟操作系統下部署JSON2WEB

【JSON2WEB】系列目錄 【JSON2WEB】01 WEB管理信息系統架構設計 【JSON2WEB】02 JSON2WEB初步UI設計 【JSON2WEB】03 go的模板包html/template的使用 【JSON2WEB】04 amis低代碼前端框架介紹 【JSON2WEB】05 前端開發三件套 HTML CSS JavaScript 速成 【JSON2WEB】06 JSO…

地基簡識Spring MVC 組件

Spring MVC 是一個基于 MVC 設計模式的框架,其核心組件協同工作以處理 HTTP 請求并生成響應。以下是各組件的詳細說明及其協作流程: 一、?核心組件 ?DispatcherServlet(前端控制器)? ?作用:接收所有請求并協調其他…

Spring Boot(七):Swagger 接口文檔

1. Swagger 簡介 1.1 Swagger 是什么? Swagger 是一款 RESTful 風格的接口文檔在線自動生成 功能測試功能軟件。Swagger 是一個規范和完整的框架,用于生成、描述、調用和可視化 RESTful 風格的 Web 服務。目標是使客戶端和文件系統作為服務器以同樣的…

cursor 彈出在簽出前,請清理倉庫工作樹 窗口

問題出現的背景:是因為我有兩臺電腦開發,提交后,另一個電腦的代碼是舊的,這個時候我想拉取最新的代碼,就會出現如下彈窗,因為這個代碼暫存區有記錄或者工作區有代碼的修改,所以有沖突&#xff0…

Cocos Creator3.8.6拖拽物體的幾種方式

文章目錄 前言一、第一種通過UILocation二、第二種通過UIDelta實現總結 前言 在游戲開發中,拖拽物體是一個非常常見的交互功能,無論是用于UI元素的拖動,還是場景中物體的移動,拖拽操作都能極大地提升用戶體驗。Cocos Creator 3.8…

在 Mac mini M2 上本地部署 DeepSeek-R1:14B:使用 Ollama 和 Chatbox 的完整指南

隨著人工智能技術的飛速發展,本地部署大型語言模型(LLM)已成為許多技術愛好者的熱門選擇。本地部署不僅能夠保護隱私,還能提供更靈活的使用體驗。本文將詳細介紹如何在 Mac mini M2(24GB 內存)上部署 DeepS…

《UE5_C++多人TPS完整教程》學習筆記33 ——《P34 關卡與大廳之間的過渡(Transition Level And Lobby)》

本文為B站系列教學視頻 《UE5_C多人TPS完整教程》 —— 《P34 關卡與大廳之間的過渡(Transition Level And Lobby)》 的學習筆記,該系列教學視頻為計算機工程師、程序員、游戲開發者、作家(Engineer, Programmer, Game Developer,…