STM32F103C8T6開發板入門學習——寄存器和庫函數介紹

學習目標:STM32F103C8T6開發板入門學習——寄存器和庫函數介紹


學習內容:

1. 寄存器介紹

1.1 存儲器映射

存儲器本身無固有地址,是具有特定功能的內存單元。它的地址是由芯片廠商或用戶分配,給存儲器分配地址的過程就叫做存儲區映射。給內存單元分配地址之后,就可以通過指針去操作內存地址。

1.2 存儲器映射表

STM32作為32位單片機,地址范圍為232(即4GB)。為降低相同應用場景下的軟件復雜度,其存儲映射按Cortex-M4處理器規則預先定義:

  • 部分地址空間由Arm Cortex-M4的系統外設占用,且不可更改;
  • 其余地址空間可由芯片供應商定義使用。
1.3 什么是寄存器

寄存器是具有特定功能的內存單元,通過操作這些單元可驅動外設工作。按功能可分為:

  • 指令寄存器、地址寄存器、數據寄存器;
  • 處理器可通過相互獨立的總線讀取指令、加載/存儲數據。
1.4 寄存器映射

程序存儲器、數據存儲器、寄存器和I/O端口位于同一4GB線性地址空間內:

  • 每個寄存器對應不同功能,操作相應寄存器可配置對應功能;
  • 控制外設時,可通過起始地址以C語言指針方式訪問內存單元;
  • 給已分配地址、有特定功能的內存單元取別名的過程,稱為寄存器映射,該別名即寄存器。
1.5 寄存器重映射

給寄存器再次分配地址的過程稱為寄存器重映射。

1.6 總線基地址

片上外設區域分為三條總線,按外設速度不同掛載相應外設:

  • AHB總線:最高時鐘可達72MHz;
  • APB1總線:最高時鐘可達36MHz;
  • APB2總線:最高時鐘可達72MHz。

根據外設速度的不同,不同的總線掛載著不同的外設。總線的最低地址我們稱為該總線的基地址,總線基地址也是掛載在該總線上的首個外設的地址。
請添加圖片描述

1.7 外設基地址

每條總線上掛載多個外設,每個外設均有自己的地址范圍。

請添加圖片描述

1.8 外設寄存器地址

在外設的地址范圍內,分布著該外設的多個寄存器。以GPIO外設為例:

  • GPIO外設地址范圍內有多個寄存器,每個均有特定功能,通過操作對應寄存器可配置GPIO功能;
  • 每個寄存器為32位,占4個字節。

請添加圖片描述

1.9 如何操作寄存器

以“讓GPIOA端口的16個引腳都置1”為例,操作步驟如下:

  1. 確定目標寄存器:需配置端口輸出寄存器GPIOx_ODR;
  2. 計算寄存器地址
    • 由中文參考手冊第115頁可知,GPIOx_ODR寄存器的地址偏移量為0x0C;
    • GPIOA端口的基地址為0x40010800;
    • 因此,GPIOx_ODR寄存器的地址為:0x40010800 + 0x0C = 0x4001080C。
      請添加圖片描述

通過上圖可以了解到要想使能所有引腳配置為1,只需要將ODRy(y=0…15)對應的位置1即可。也就是配置GPIOA_ODR寄存器的高16位為0,低16位為1,換成十六進制就是0x0000FFFF。

1.通過絕對地址訪問內存單元
// GPIOA 端口的16個引腳全部輸出高電平
*(unsigned int*)(0x4001080C) = 0xFFFF;

說明

  • (unsigned int*):將立即數0x4001080C強制轉換為無符號整型指針,告訴編譯器這是一個內存地址;
  • *:對該地址進行解引用,訪問地址對應的內存空間;
  • 整體含義:向0x4001080C(GPIOA_ODR寄存器)對應的內存空間寫入0xFFFF,實現GPIOA所有16個引腳輸出高電平(低16位置1,高16位為0)。
2. 通過別名訪問內存單元

為簡化操作并增強可讀性,可給寄存器地址定義別名:

方式一:定義地址指針

// 定義 GPIOA_ODR 地址指針
#define GPIOA_ODR (unsigned int*)(0x4001080C)// GPIOA 端口的16個引腳全部輸出高電平
*GPIOA_ODR = 0xFFFF;

方式二:直接定義解引用的地址(更常用)

// 定義 GPIOA_ODR 并直接解引用
#define GPIOA_ODR (*(unsigned int*)(0x4001080C))// GPIOA 端口的16個引腳全部輸出高電平
GPIOA_ODR = 0xFFFF;
  • 優勢:通過GPIOA_ODR這樣的別名,可直觀理解操作的是GPIOA的輸出數據寄存器,無需記憶復雜的十六進制地址,提升代碼可讀性和可維護性。

2. 庫函數介紹

2.1 為什么要使用庫函數

從上一節可知,通過寄存器驅動外設雖可行,但STM32寄存器數量極多:

  • 僅定義寄存器就需耗費大量時間,還需逐一查找其功能、地址并配置對應值,在開發難度和時間成本上均不劃算。

庫函數的出現正是為解決這一問題,其優勢在于:

  • 由STM32官方開發,可直接移植到工程中使用,大幅提升開發效率;
  • 無需深入了解硬件底層機制,只需根據需求查找對應函數并調用,降低了開發門檻。
2.2 庫函數簡單介紹

在創建的工程模板中,包含STM32F1x的標準外設庫,可通過打開stm32f10x_gpio.hstm32f10x_gpio.c等文件查看具體實現。

本質上,庫函數是在寄存器操作的基礎上進行了封裝:

  • 底層仍通過操作寄存器實現功能,但上層提供了更簡潔的函數接口,使開發操作更簡單。

3. 寄存器和庫函數的區別

寄存器和庫函數最終均通過對地址操作實現功能,但二者存在明顯差異,適用場景也不同:

  • 原理與直觀性:寄存器操作更易理解底層原理,過程直觀;庫函數則屏蔽了底層細節,直接面向應用功能。
  • 代碼量與冗余:庫函數代碼量相對更大,因函數需考慮多種使用場景,可能存在代碼冗余;寄存器操作代碼更精簡。
  • 開發難度與效率:庫函數使用簡單、易上手,可快速開發應用,能顯著提高開發效率;寄存器操作需熟悉硬件細節,開發門檻更高。
  • 資源占用與速度:寄存器操作占用內存少、執行速度快,在資源有限(如內存緊張)或對執行速度有高要求的場景下更具優勢。

學習時間:8月25日

1. 寄存器介紹

1.1 存儲器映射

原文核心:存儲器本身無固有地址,分配地址的過程稱為存儲區映射,映射后可通過指針操作內存單元。

個人理解:存儲器就像一堆無編號的儲物箱,“存儲器映射”就是給每個箱子貼上限號(地址)。有了編號后,CPU才能通過“地址指針”準確找到并操作對應的存儲單元。這是硬件與軟件交互的基礎——沒有地址映射,軟件就無法“定位”硬件資源。

1.2 存儲器映射表

原文核心:STM32作為32位單片機,地址范圍為4GB,部分地址由Cortex-M4內核占用(不可改),其余由芯片廠商定義。

個人理解:4GB地址空間是32位處理器的“理論上限”,就像一個巨大的“地址版圖”。其中,Cortex-M4內核預留了部分區域(如系統外設),相當于“國家劃定的保護區”,不可占用;剩下的區域由STM32廠商分配給片上外設(如GPIO、UART等),形成了固定的“地址規劃”。這種標準化的映射表讓不同開發者能基于同一套地址規則操作硬件,降低了兼容性成本。

1.3 什么是寄存器

原文核心:寄存器是具有特定功能的內存單元,按功能分為指令、地址、數據寄存器,處理器通過獨立總線訪問。

個人理解:寄存器是硬件的“控制面板”。比如,指令寄存器存放當前要執行的指令,地址寄存器存放要訪問的內存地址,數據寄存器臨時存儲運算數據。獨立總線設計(如指令總線、數據總線)就像“專用通道”,避免了指令讀取和數據傳輸的沖突,提高了CPU效率。簡單說,寄存器是CPU與外設“對話”的直接窗口——操作寄存器就是在“告訴”硬件該做什么。

1.4 寄存器映射

原文核心:給已分配地址、有特定功能的內存單元取別名的過程,稱為寄存器映射,別名即寄存器。

個人理解:假設某塊內存單元的地址是0x4001080C,其功能是控制GPIOA的輸出,我們給它起個名字“GPIOA_ODR”,這個過程就是寄存器映射。它的本質是“地址→功能別名”的映射,讓開發者不用死記硬背冗長的十六進制地址,而是通過“GPIOA_ODR”這樣直觀的名字操作硬件,大幅降低了代碼的理解難度。

1.6 總線基地址

原文核心:片上外設分為AHB(72MHz)、APB1(36MHz)、APB2(72MHz)三條總線,總線基地址是總線上首個外設的地址。

個人理解:總線就像“高速公路”,外設是“車輛”。AHB和APB2是“快車道”(72MHz),適合高速外設(如GPIO、SPI);APB1是“慢車道”(36MHz),適合低速外設(如I2C、UART)。總線基地址是“高速路的起點”,比如AHB總線基地址是0x40010000,總線上的所有外設地址都從這個起點開始“編號”,方便按總線歸類管理外設。

1.7 外設基地址

原文核心:每條總線上的外設都有自己的地址范圍。

個人理解:如果總線是“高速公路”,外設就是路上的“服務區”,每個服務區有自己的“管轄范圍”(地址范圍)。比如,GPIOA掛在APB2總線上,其基地址是0x40010800,地址范圍從0x40010800到下一個外設的基地址前,這樣CPU就能通過地址范圍準確區分不同外設(如GPIOA和GPIOB)。

1.8 外設寄存器地址

原文核心:外設地址范圍內有多個寄存器,每個32位(4字節),對應特定功能(以GPIO為例)。

個人理解:一個外設(如GPIOA)就像一個“工具箱”,里面的每個“工具”(寄存器)對應不同功能:比如“GPIOA_CRL”控制低8位引腳模式,“GPIOA_ODR”控制輸出電平。每個寄存器占4字節(32位),是因為STM32是32位處理器,一次可處理32位數據,這種設計能高效讀寫寄存器。

1.9 如何操作寄存器(以GPIOA引腳置1為例)

原文核心:步驟為“確定目標寄存器→計算地址→寫入值”,并給出了具體示例。

個人理解:操作寄存器的本質是“地址+值”的精準控制。比如要讓GPIOA所有引腳輸出高電平,需找到“輸出數據寄存器(ODR)”,計算其地址(GPIOA基地址+偏移量0x0C=0x4001080C),再寫入0xFFFF(低16位置1)。這個過程像“按地址找到開關,再撥動開關”,需要對硬件地址和寄存器功能有清晰了解。

1. 通過絕對地址訪問內存單元

原文示例:*(unsigned int*)(0x4001080C) = 0xFFFF;

個人理解:這種方式直接通過地址操作,優點是“直達底層”,缺點是可讀性差——如果不查手冊,沒人知道0x4001080C是什么。適合對硬件極度熟悉的場景,或調試時快速驗證功能。

2. 通過別名訪問內存單元

原文給出兩種方式:定義地址指針(#define GPIOA_ODR (unsigned int*)(0x4001080C))或直接定義解引用地址(#define GPIOA_ODR (*(unsigned int*)(0x4001080C)))。

個人理解:這是實際開發中更推薦的方式。通過“GPIOA_ODR”這樣的別名,代碼可讀性大幅提升,且修改時只需改宏定義,無需逐個修改地址。就像用“家門鑰匙”代替“鑰匙的物理編號”,更符合人類的記憶習慣。

2. 庫函數介紹

2.1 為什么要使用庫函數

原文核心:寄存器數量多,手動定義和配置耗時,庫函數由官方開發,可直接移植,降低門檻、提高效率。

個人理解:STM32的外設和寄存器極其龐大(僅GPIO就有近10個寄存器,全芯片有上百個外設),如果每個寄存器都手動定義地址、查手冊配置值,開發效率會極低。庫函數就像“封裝好的快捷指令”,比如要配置GPIO輸出,直接調用GPIO_Init()即可,無需關心底層寄存器的地址和具體值,適合快速開發。

2.2 庫函數簡單介紹

原文核心:庫函數基于寄存器操作封裝,在stm32f10x_gpio.h等文件中實現,提供簡潔接口。

個人理解:庫函數不是“魔法”,其底層依然是操作寄存器。比如GPIO_SetBits(GPIOA, GPIO_Pin_All)函數,內部其實是對GPIOA_ODR寄存器寫入0xFFFF。它的價值在于“抽象”——把復雜的寄存器配置邏輯(如時鐘使能、模式設置、輸出控制)打包成函數,讓開發者只需關注“要做什么”,而非“怎么做”。

3. 寄存器和庫函數的區別

原文從原理、代碼量、開發效率、資源占用等方面對比了兩者。

個人感悟:

  • 寄存器是“手動擋”:直接操作硬件,代碼精簡、執行快,但需要深入了解硬件細節,開發門檻高,適合底層驅動開發或資源受限場景(如內存極小的設備)。
  • 庫函數是“自動擋”:屏蔽底層細節,開發效率高、易上手,但代碼量較大(可能有冗余),執行速度略慢,適合應用層開發或快速原型驗證。

實際開發中,兩者并非對立:簡單功能可用庫函數快速實現,對性能要求高的部分(如中斷處理)可結合寄存器操作優化。初學者建議先通過庫函數入門,熟悉后再深入寄存器,理解底層原理。


學習產出:

  • 了解并學習STMSTM32F103C8T6開發板的寄存器和庫函數介紹
  • 技術文章的1篇

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

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

相關文章

【CouponHub項目開發】使用RocketMQ5.x實現延時修改優惠券狀態,并通過使用模板方法模式重構消息隊列發送功能

在上個章節中我實現了創建優惠券模板的功能,但是,優惠券總會有過期時間,我們怎么去解決到期自動修改優惠券狀態這樣一個功能呢?我們可以使用RocketMQ5.x新出的任意定時發送消息功能來解決。 初始方案:首先在創建優惠券…

Claude Code SDK 配置Gitlab MCP服務

一、MCP配置前期準備 (一)創建個人令牌/群組令牌 我這里是創建個人令牌,去到首頁左上角,點擊頭像——>偏好設置——>訪問令牌——>添加新令牌 (二)配置mcp信息 去到魔塔社區,點擊mc…

Eclipse 常用搜索功能匯總

Eclipse 常用搜索功能匯總 Eclipse 提供了多種搜索功能,幫助開發者快速定位代碼、文件、類、方法、API 等資源。以下是詳細的使用方法和技巧。 一、常用搜索快捷鍵快捷鍵功能描述Ctrl H打開全局搜索對話框,支持文件、Java 代碼、任務等多種搜索。Ctrl …

關于Spring的一些理解

Spring整體結構:Spring實際運行場景:基礎 Spring啟動過程 傳統Spring: (1)初始化準備階段 (2)容器創建與注入 (3)Bean工廠后置處理 (4)Bean工廠后…

Windows右下角系統托盤圖標快速顯示或隱藏

系統托盤指的是Windows電腦桌面右下角的區域,包括時間、wifi(網絡)、音量、電源、輸入法、一些程序/應用等。啟動了應用后,Windows會把部分應用的圖標顯示或隱藏在系統托盤區。我們可以根據需要快速顯示或隱藏相關應用&#xff0c…

Kotlin編程學習記錄2

Kotlin編程學習記錄2——條件與循環 條件語句:if 與 when ? Kotlin 的控制流把“表達式優先”作為設計原則——if、when 不只是控制語句,都可以作為表達式使用并返回值,這影響了日常代碼風格(更函數式、可組合)。筆…

印度物聯網崛起:政策紅利下的千億藍海與本土化博弈

印度物聯網市場正處于快速發展階段,2025年市場規模預計達到200億美元,主要得益于政府"數字印度"計劃和智能城市項目的推動。蜂窩物聯網連接數在2024年同比增長34%,2025年Q1增速進一步提升至32%,其中智能電表部署和資產追蹤應用成為核心驅動力。然而,市場也面臨著…

html學習:

ok,今天準備學一下html&#xff0c;花費點時間整理一下&#xff1a; HTML標簽的語法格式 HTML 中的標簽就像關鍵字一樣&#xff0c;每個標簽都有自己的語義&#xff08;含義&#xff09;。 HTML 標簽的語法格式 屬性↓ <div class"begin">cyx</div>↑…

CRYPT32!PkiAsn1Decode函數分析的一個例子

第一部分&#xff1a; 0: kd> g Breakpoint 35 hit CRYPT32!PkiAsn1Decode: 001b:75c9af0c 55 push ebp 1: kd> kc# 00 CRYPT32!PkiAsn1Decode 01 CRYPT32!PkiAsn1DecodeAndAllocInfo 02 CRYPT32!PkiAsn1DecodeAndAllocInfoEx 03 CRYPT32!Asn1InfoDecode…

大模型蒸餾、大模型微調、RAG

前言&#xff1a; 有很多同學想學習大模型開發&#xff0c;又無從下手&#xff0c;網上一搜&#xff0c;鋪天蓋地的付費課程。又不想當韭菜&#xff0c;打破認知障礙&#xff0c;通過自學&#xff0c;改變自己&#xff0c;改變世界&#xff01; 一、大模型蒸餾、微調、RAG的適…

25高教社杯數模國賽【E題保姆級思路+問題分析】

注&#xff1a;本內容由”數模加油站“ 原創出品&#xff0c;雖無償分享&#xff0c;但創作不易。 歡迎參考teach&#xff0c;但請勿抄襲、盜賣或商用。 E 題 AI輔助智能體測 《國家學生體質健康標準》的頒布&#xff0c;有效地促進了大中小學生關注自身體質健康的發展&#xf…

基于單片機車內換氣溫度檢測空氣質量檢測系統Proteus仿真(含全部資料)

全套資料包含&#xff1a;Proteus仿真源文件keil C語言源程序AD原理圖流程圖元器件清單說明書等 資料下載&#xff1a; 通過網盤分享的文件&#xff1a;資料分享 鏈接: 百度網盤 請輸入提取碼 提取碼: tgnu 目錄 資料下載&#xff1a; Proteus仿真功能 項目文件資料&#…

MySQL子查詢的分類講解與實戰

精選專欄鏈接 &#x1f517; MySQL技術筆記專欄Redis技術筆記專欄大模型搭建專欄Python學習筆記專欄深度學習算法專欄 歡迎訂閱&#xff0c;點贊&#xff0b;關注&#xff0c;每日精進1%&#xff0c;與百萬開發者共攀技術珠峰 更多內容持續更新中&#xff01;希望能給大家帶來…

Leetcode 206. 反轉鏈表 迭代/遞歸

原題鏈接&#xff1a;Leetcode 206. 反轉鏈表 解法一&#xff1a;迭代 /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode() : val(0), next(nullptr) {}* ListNode(int x) : val(x), next(nullptr) {}* …

C++11新特性 | 歡迎來到現代C++的世界!

左值與右值 左值與右值的概念 可以被取地址的值為左值&#xff08;left value&#xff0c;簡稱lvalue&#xff09;&#xff0c;否則為右值&#xff08;right value&#xff0c;簡稱rvalue&#xff09;。 常見的左值、右值例子&#xff1a; // >>>>>>> 左值…

因為對象裝箱拆箱導致的空指針異常

今天業務突然提了個事件單&#xff0c;客戶添加承租人一直報錯&#xff0c;但是很奇怪&#xff0c;報錯信息是空的二話不說&#xff0c;先跟API組要了接口和參數&#xff0c;然后看日志然鵝&#xff0c;這個接口并沒有打印日志&#xff0c;只有一個e.printStackTrace()然后靜下…

Rust 在 Windows 環境下交叉編譯其他操作系統可執行文件的詳細指南

前言&#xff1a;為什么需要交叉編譯&#xff1f; 想象一下這樣的場景&#xff1a;你在 Windows 電腦上開發了一個 Rust 程序&#xff0c;希望它能在 Linux 服務器上運行&#xff0c;或者在朋友的 macOS 電腦上測試 —— 總不能為了編譯不同系統的版本&#xff0c;專門買一臺 …

Ubuntu系統配置鏡像源

要修改的文件 /etc/apt/sources.list操作步驟 1. 備份原文件 sudo cp /etc/apt/sources.list /etc/apt/sources.list.bak2. 編輯文件 sudo nano /etc/apt/sources.list3. 清空文件內容&#xff0c;填入以下內容 先獲取Ubuntu版本代號&#xff1a; lsb_release -cs然后根據版本填…

【Spring Cloud Alibaba】Sentinel(一)

【Spring Cloud Alibaba】Sentinel&#xff08;一&#xff09;1. 簡介2. 服務雪崩1. 簡介 Sentinel 是阿里巴巴開源的分布式系統的流量防護組件&#xff0c;主要用來做流量控制、熔斷降級、系統保護。它的定位類似于 Hystrix&#xff0c;但更側重在 流量治理 上。目前在微服務…