STM32中寄存器編程


一、存儲器映射:給存儲器分配地址。

存儲器重映射:給存儲器再分配一個地址

存儲器的地址空間有4G,被平均分為8塊。

 

 

block0設計成FLASH

block1設計成內部SRAM

block2設計成片上外設(根據外設的總線速度不同,block被分成了APB和AHB,APB被分為APB1和APB2)

二、寄存器映射

在block2中,設計成片上外設,四個字節為一個單元,共32bit(4*8),每個單元對應不同功能,通過控制這些單元來控制外設工作。找到每個單元的起始地址然后利用c語言的指針操作來進行訪問。如果利用地址來進行操作的話,很麻煩。

因此我們根據每個單元功能的不同以此對內存單元取別名方便操作。這個別名就叫寄存器。

利用絕對地址對內存單元進行訪問:
// GPIOB 端口全部輸出 高電平
*(unsigned int*)(0x4001 0C0C) = 0xFFFF; 

 此處0x4001 0C0C就是GPIOB端口ODR的地址,類似變量名。

先轉換成指針,c語言就知道是這是個地址,就可以通過*操作來對這個地址存儲的值進行間接訪問。

 上述方法過於麻煩,可以把強制類型轉換和*操作放在宏定義里,然后直接打英文字符就行了。

// GPIOB 端口全部輸出 高電平
#define GPIOB_ODR
*(unsigned int*)(GPIOB_BASE+0x0C)
GPIOB_ODR = 0xFF;

 三、STM32外設地址映射

APB1掛載低速外設,APB2,AHB掛載高速外設

相應總線的最低地址我們稱為該總線的基地址,總線基地址也是掛載在該總線上的首個外設的地址。APB1總線的地址最低,片上外設從此開始。

總線基地址+相對外設基地址的偏移(該總線地址與片上外設基地址的差值)。

總線上掛載這各種外設也有自己的地址范圍,特定外設的首個地址稱為XX外設基地址=XX外設的邊界地址。

XX外設的地址范圍內分布着的就是該外設的寄存器。

例如GPIO 有很多寄存器,每一個都有相應的特定功能。每個寄存器32bit,占4個字節。

寄存器位置=外設基地址+相對該外設基地址的偏移。

四、一個一個定義太麻煩

因此采取對寄存器封裝的方式,全部用宏定義起來,總線和外設以他們的名字作為宏名

*(unsigned int *)GPIOB_BSRR = (0x01<<(16+0));

我們對於總線基地址,外設基地址,寄存器基地址進行宏定義。通過查閱手冊來進行宏定義。

此時這些地址是一些無符號整型的值。

c語言中,對於一些普通的變量來講,程序被編譯和鏈接之后,變量名被替換成相應的地址,然后獲取數據。

C語言中,允許用一個變量來存放指針,這種變量稱為指針變量。指針變量的值就是某份數據的地址,這樣的一份數據可以是數組、字符串、函數,也可以是另外的一個普通變量或指針變量。

而指針不同:

假設變量 a、p 的地址分別為 0X1000、0XF0A0,它們的指向關系如下圖所示:

 

程序被編譯和鏈接后,a、p 被替換成相應的地址。使用 *p 的話,要先通過地址 0XF0A0 取得變量 p 本身的值,這個值是變量 a 的地址,然后再通過這個值取得變量 a 的數據,前后共有兩次運算;而使用 a 的話,可以通過地址 0X1000 直接取得它的數據,只需要一步運算。

我們要用 C 語言控制讀寫外設寄存器

這里采用了指針的方式

(unsigned int *)GPIOB_BSRR的意思是強制類型轉換,將原先定義的一個無符號整型變量變成一個指針變量,這個指針變量指向的數據類型是無符號整型,然后這個指針變量存放的是一個地址,這個地址是(0x01<<(16+0)).

前面又加了一個*號,這個意思賦予GPIOB_BSRR的值,也就是把這個地址賦予給這個指針。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM