91欧美超碰AV自拍|国产成年人性爱视频免费看|亚洲 日韩 欧美一厂二区入|人人看人人爽人人操aV|丝袜美腿视频一区二区在线看|人人操人人爽人人爱|婷婷五月天超碰|97色色欧美亚州A√|另类A√无码精品一级av|欧美特级日韩特级

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

第四章 什么是寄存器

W55MH32 ? 來源:W55MH32 ? 作者:W55MH32 ? 2025-05-21 14:23 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

單芯片解決方案,開啟全新體驗(yàn)——W55MH32 高性能以太網(wǎng)單片機(jī)

W55MH32是WIZnet重磅推出的高性能以太網(wǎng)單片機(jī),它為用戶帶來前所未有的集成化體驗(yàn)。這顆芯片將強(qiáng)大的組件集于一身,具體來說,一顆W55MH32內(nèi)置高性能Arm? Cortex-M3核心,其主頻最高可達(dá)216MHz;配備1024KB FLASH與96KB SRAM,滿足存儲與數(shù)據(jù)處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協(xié)議棧、內(nèi)置MAC以及PHY,擁有獨(dú)立的32KB以太網(wǎng)收發(fā)緩存,可供8個獨(dú)立硬件socket使用。如此配置,真正實(shí)現(xiàn)了All-in-One解決方案,為開發(fā)者提供極大便利。

在封裝規(guī)格上,W55MH32 提供了兩種選擇:QFN100和QFN68。

W55MH32L采用QFN100封裝版本,尺寸為12x12mm,其資源豐富,專為各種復(fù)雜工控場景設(shè)計。它擁有66個GPIO、3個ADC、12通道DMA、17個定時器、2個I2C、5個串口、2個SPI接口(其中1個帶I2S接口復(fù)用)、1個CAN、1個USB2.0以及1個SDIO接口。如此豐富的外設(shè)資源,能夠輕松應(yīng)對工業(yè)控制中多樣化的連接需求,無論是與各類傳感器、執(zhí)行器的通信,還是對復(fù)雜工業(yè)協(xié)議的支持,都能游刃有余,成為復(fù)雜工控領(lǐng)域的理想選擇。 同系列還有QFN68封裝的W55MH32Q版本,該版本體積更小,僅為8x8mm,成本低,適合集成度高的網(wǎng)關(guān)模組等場景,軟件使用方法一致。更多信息和資料請進(jìn)入http://www.w5500.com/網(wǎng)站或者私信獲取。

此外,本W(wǎng)55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應(yīng)用,涵蓋TCP SSL、HTTP SSL以及 MQTT SSL等,為網(wǎng)絡(luò)通信安全再添保障。

為助力開發(fā)者快速上手與深入開發(fā),基于W55MH32L這顆芯片,WIZnet精心打造了配套開發(fā)板。開發(fā)板集成WIZ-Link芯片,借助一根USB C口數(shù)據(jù)線,就能輕松實(shí)現(xiàn)調(diào)試、下載以及串口打印日志等功能。開發(fā)板將所有外設(shè)全部引出,拓展功能也大幅提升,便于開發(fā)者全面評估芯片性能。

若您想獲取芯片和開發(fā)板的更多詳細(xì)信息,包括產(chǎn)品特性、技術(shù)參數(shù)以及價格等,歡迎訪問官方網(wǎng)頁:http://www.w5500.com/,我們期待與您共同探索W55MH32的無限可能。

wKgZPGgbOfaANhwzACodXd3sVzg463.png

第四章 什么是寄存器

本章參考資料:《W55MH32_數(shù)據(jù)手冊_V1.0.0》、《W55MH 32參考手冊_V1.0.0》

學(xué)習(xí)本章時,配合《W55MH 32參考手冊_V1.0.0》“存儲器和總線架構(gòu)”及“通用I/O(GPIO)”章節(jié)一起閱讀,效果會更佳,特別是涉及到寄存器說明的部分。

1 什么是寄存器

我們經(jīng)常說寄存器,那么什么是寄存器?這是我們本章需要講解的內(nèi)容,在學(xué)習(xí)的過程中,大家?guī)е@個疑問好好思考下,到最后看看大家能否用一句話給寄存器下一個定義。

2 W55MH32

我們開發(fā)板中使用的芯片是100pin的W55MH32L,具體見下圖。這個就是我們接下來要學(xué)習(xí)的高性能以太網(wǎng)單片機(jī),它將帶領(lǐng)我們進(jìn)入嵌入式的殿堂。

芯片四周是引腳,開發(fā)板中把芯片的引腳引出來,連接到各種傳感器上,然后在W55MH32L上編程(實(shí)際就是通過程序控制這些引腳輸出高電平或者低電平)來控制各種傳感器工作, 通過做實(shí)驗(yàn)的方式來學(xué)習(xí)W55MH32芯片的各個資源。開發(fā)板是一種評估板,板載資源非常豐富,引腳復(fù)用比較多, 力求在一個板子上驗(yàn)證芯片的全部功能。

wKgZPGgtTrqATxpWAAjzNQE-9Xg370.pngwKgZPGgRskSACVm2AAGG5sO9Q70099.png

3 芯片里面有什么

我們看到的芯片是已經(jīng)封裝好的成品,主要由內(nèi)核和片上外設(shè)組成。若與電腦類比,內(nèi)核與外設(shè)就如同電腦上的CPU與主板、內(nèi)存、顯卡、硬盤的關(guān)系。

W55MH32采用的是Cortex-M3內(nèi)核,內(nèi)核即CPU,負(fù)責(zé)在內(nèi)核之外設(shè)計部件并生產(chǎn)整個芯片,這些內(nèi)核之外的部件被稱為核外外設(shè)或片上外設(shè)。 如GPIO、USART(串口)、I2C、SPI等都叫做片上外設(shè)。

wKgZO2gtTruAHumwAAElNiRtqW4779.png

芯片(這里指內(nèi)核,或者叫CPU)和外設(shè)之間通過各種總線連接,其中驅(qū)動單元有4個,被動單元也有4個, 具體見圖 W55MH32系統(tǒng)框圖 。為了方便理解,我們都可以把驅(qū)動單元理解成是CPU部分,被動單元都理解成外設(shè)。 下面我們簡單介紹下驅(qū)動單元和被動單元的各個部件。

3.1 ICode總線

ICode中的I表示Instruction,即指令。我們寫好的程序編譯之后都是一條條指令,存放在FLASH中, 內(nèi)核要讀取這些指令來執(zhí)行程序就必須通過ICode總線,它幾乎每時每刻都需要被使用,它是專門用來取指的。

3.2 驅(qū)動單元

3.2.1 DCode總線

DCode中的D表示Data,即數(shù)據(jù),那說明這條總線是用來取數(shù)的。我們在寫程序的時候,數(shù)據(jù)有常量和變量兩種, 常量就是固定不變的,用C語言中的const關(guān)鍵字修飾,是放到內(nèi)部的FLASH當(dāng)中的,變量是可變的,不管是全局變量還是局部變量都放在內(nèi)部的SRAM。 因?yàn)閿?shù)據(jù)可以被Dcode總線和DMA總線訪問,所以為了避免訪問沖突,在取數(shù)的時候需要經(jīng)過一個總線矩陣來仲裁,決定哪個總線在取數(shù)。

3.2.2 系統(tǒng)總線

系統(tǒng)總線主要是訪問外設(shè)的寄存器,我們通常說的寄存器編程,即讀寫寄存器都是通過這根系統(tǒng)總線來完成的。

3.2.3 DMA總線

DMA總線也主要是用來傳輸數(shù)據(jù),這個數(shù)據(jù)可以是在某個外設(shè)的數(shù)據(jù)寄存器,可以在SRAM,可以在內(nèi)部的FLASH。 因?yàn)閿?shù)據(jù)可以被Dcode總線和DMA總線訪問,所以為了避免訪問沖突,在取數(shù)的時候需要經(jīng)過一個總線矩陣來仲裁,決定哪個總線在取數(shù)。

3.3 被動單元

3.3.1 內(nèi)部的閃存存儲器

內(nèi)部的閃存存儲器即FLASH,我們編寫好的程序就放在這個地方。內(nèi)核通過ICode總線來取里面的指令。

3.3.2 內(nèi)部的SRAM

內(nèi)部的SRAM,即我們通常說的RAM,程序的變量,堆棧等的開銷都是基于內(nèi)部的SRAM。內(nèi)核通過DCode總線來訪問它。

3.3.3 FSMC

FSMC的英文全稱是Flexible static memory controller,叫靈活的靜態(tài)的存儲器控制器, 是W55MH32中一個很有特色的外設(shè), 通過FSMC,我們可以擴(kuò)展內(nèi)存,如外部的SRAM,NANDFLASH和NORFLASH。但有一點(diǎn)我們要注意的是,F(xiàn)SMC只能擴(kuò)展靜態(tài)的內(nèi)存, 即名稱里面的S:static,不能是動態(tài)的內(nèi)存,比如SDRAM就不能擴(kuò)展。

3.3.4 AHB到APB的橋

從AHB總線延伸出來的兩條APB2和APB1總線,上面掛載著W55MH32各種各樣的特色外設(shè)。我們經(jīng)常說的GPIO、串口、I2C、SPI這些外設(shè)就掛載在這兩條總線上, 這個是我們學(xué)習(xí)W55MH32的重點(diǎn),就是要學(xué)會編程這些外設(shè)去驅(qū)動外部的各種設(shè)備。

wKgZO2gtbMyAQMsAAAKz8dGRy80597.png

4 存儲器映射

在W55MH32系統(tǒng)框圖中,程序存儲器、數(shù)據(jù)存儲器、寄存器和輸入輸出端口被組織在同一個 4GB 的線性地址空間內(nèi)。數(shù)據(jù)字節(jié)以小端格式存放在存儲器中。一個字里的最低地址字節(jié)被認(rèn)為是該字的最低有效字節(jié),而最高地址字節(jié)是最高有效字節(jié)??稍L問的存儲器空間被分成 8 個主要塊,每個塊為 512MB。我們在編程的時候,可以通過他們的地址找到他們,然后來操作他們(通過C語言對它們進(jìn)行數(shù)據(jù)的讀和寫)。

4.1 存儲器映射

存儲器本身不具有地址信息,它的地址是由芯片廠商或用戶分配,給存儲器分配地址的過程就稱為存儲器映射, 具體見圖 存儲器映射 。如果給存儲器再分配一個地址就叫存儲器重映射。

wKgZPGgtTrqAX4OdAAjXV68IGZA800.png

4.1.1 存儲器區(qū)域功能劃分

在這4GB的地址空間中,ARM已經(jīng)粗線條的平均分成了8個塊,每塊512MB,每個塊也都規(guī)定了用途,具體分類見表格 存儲器功能分類 。 每個塊的大小都有512MB,顯然這是非常大的,芯片廠商在每個塊的范圍內(nèi)設(shè)計各具特色的外設(shè)時并不一定都用得完,都是只用了其中的一部分而已。

序號 用途 地址范圍
Block 0 Code 0x0000 0000 ~ 0x1FFF FFFF(512MB)
Block 1 SRAM 0x2000 0000 ~ 0x3FFF FFFF(512MB)
Block 2 片上外設(shè) 0x4000 0000 ~ 0x5FFF FFFF(512MB)
Block 3 FSMC 的 bank1 ~ bank2 0x6000 0000 ~ 0x7FFF FFFF(512MB)
Block 4 FSMC 的 bank3 ~ bank4 0x8000 0000 ~ 0x9FFF FFFF(512MB)
Block 5 FSMC 寄存器 0xA000 0000 ~ 0xCFFF FFFF(512MB)
Block 6 沒有使用 0xD000 0000 ~ 0xDFFF FFFF(512MB)
Block 7 Cortex-M3 內(nèi)部外設(shè) 0xE000 0000 ~ 0xFFFF FFFF(512MB)

在這8個Block里面,有3個塊非常重要,也是我們最關(guān)心的三個塊。Block0用來設(shè)計成內(nèi)部FLASH,Block1用來設(shè)計成內(nèi)部RAM, Block2用來設(shè)計成片上的外設(shè),下面我們簡單的介紹下這三個Block里面的具體區(qū)域的功能劃分。

4.1.1.1 存儲器Block0內(nèi)部區(qū)域功能劃分

Block0主要用于設(shè)計片內(nèi)的FLASH,要在芯片內(nèi)部集成更大的FLASH或者SRAM都意味著芯片成本的增加,往往片內(nèi)集成的FLASH都不會太大, W55MH32能在追求性價比的同時做到512KB,實(shí)乃良心之舉。Block內(nèi)部區(qū)域的功能劃分具體見表格 存儲器Block0內(nèi)部區(qū)域功能劃分 。

用途說明 地址范圍
Block0 預(yù)留 0x1FFE C008 ~ 0x1FFF FFFF
選項(xiàng)字節(jié):用于配置讀寫保護(hù)、BOR 級別、軟件 / 硬件看門狗以及器件處于待機(jī)或停止模式下的復(fù)位。當(dāng)芯片被鎖住后,可從 RAM 啟動修改對應(yīng)寄存器位。 0x1FFF F800 - 0x1FFF F80F
系統(tǒng)存儲器:存放 ST 出廠燒寫的 ISP 自舉程序(Bootloader),用戶無法改動,串口下載需用此程序。 0x1FFF F000 - 0x1FFF F7FF
預(yù)留 0x0808 0000 ~ 0x1FFF EFFF
FLASH:程序存放位置 0x0800 0000 ~ 0x0807 FFFF (512KB)
預(yù)留 0x0008 0000 ~ 0x07FF FFFF
取決于 BOOT 引腳,為 FLASH、系統(tǒng)存儲器、SRAM 的別名。 0x0000 0000 ~ 0x0007 FFFF

4.1.1.2 儲存器Block1內(nèi)部區(qū)域功能劃分

Block1用于設(shè)計片內(nèi)的SRAM,Block內(nèi)部區(qū)域的功能劃分具體見表格 存儲器Block1內(nèi)部區(qū)域功能劃分 。

用途說明 地址范圍
Block1 預(yù)留 0x2001 0000 ~ 0x3FFF FFFF
SRAM 64KB 0x2000 0000 ~ 0x2000 FFFF

4.1.1.3 儲存器Block2內(nèi)部區(qū)域功能劃分

Block2用于設(shè)計片內(nèi)的外設(shè),根據(jù)外設(shè)的總線速度不同,Block被分成了APB和AHB兩部分,其中APB又被分為APB1和APB2, 具體見表格 存儲器Block2內(nèi)部區(qū)域功能劃分 。

用途說明 地址范圍
Block2 APB1 總線外設(shè) 0x4000 0000 ~ 0x4000 77FF
APB2 總線外設(shè) 0x4001 0000 ~ 0x4001 3FFF
AHB 總線外設(shè) 0x4001 8000 ~ 0x5003 FFFF

5 寄存器映射

我們知道,存儲器本身沒有地址,給存儲器分配地址的過程叫存儲器映射,那什么叫寄存器映射?寄存器到底是什么?

在存儲器Block2這塊區(qū)域,設(shè)計的是片上外設(shè),它們以四個字節(jié)為一個單元,共32bit,每一個單元對應(yīng)不同的功能, 當(dāng)我們控制這些單元時就可以驅(qū)動外設(shè)工作。我們可以找到每個單元的起始地址,然后通過C語言指針的操作方式來訪問這些單元, 如果每次都是通過這種地址的方式來訪問,不僅不好記憶還容易出錯,這時我們可以根據(jù)每個單元功能的不同,以功能為名給這個內(nèi)存單元取一個別名, 這個別名就是我們經(jīng)常說的寄存器,這個給已經(jīng)分配好地址的有特定功能的內(nèi)存單元取別名的過程就叫寄存器映射。

比如,我們找到GPIOB端口的輸出數(shù)據(jù)寄存器ODR的地址是0x40010C0C(至于這個地址如何找到可以先跳過,后面我們會有詳細(xì)的講解), ODR寄存器是32bit,低16bit有效,對應(yīng)著16個外部IO,寫0/1對應(yīng)的的IO則輸出低/高電平?,F(xiàn)在我們通過C語言指針的操作方式, 讓GPIOB的16個IO都輸出高電平,具體見代碼清單:寄存器-1。

代碼清單:寄存器-1 通過絕對地址訪問內(nèi)存單元

// GPIOB 端口全部輸出 高電平
*(unsigned int*)(0x4001 0C0C) = 0xFFFF;

0x4001 0C0C在我們看來是GPIOB端口ODR的地址,但是在編譯器看來,這只是一個普通的變量,是一個立即數(shù), 要想讓編譯器也認(rèn)為是指針,我們得進(jìn)行強(qiáng)制類型轉(zhuǎn)換,把它轉(zhuǎn)換成指針, 即(unsigned int *)0x4001 0C0C,然后再對這個指針進(jìn)行 * 操作。

剛剛我們說了,通過絕對地址訪問內(nèi)存單元不好記憶且容易出錯,我們可以通過寄存器的方式來操作,具體見代碼清單:寄存器-2。

代碼清單:寄存器-2 通過寄存器別名方式訪問內(nèi)存單元

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

為了方便操作,我們干脆把指針操作“*”也定義到寄存器別名里面,具體見代碼清單:寄存器-3。

代碼清單:寄存器-3 通過寄存器別名訪問內(nèi)存單元

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

5.1 W55MH32的外設(shè)地址映射

片上外設(shè)區(qū)分為三條總線,根據(jù)外設(shè)速度的不同,不同總線掛載著不同的外設(shè),APB1掛載低速外設(shè),APB2和AHB掛載高速外設(shè)。 相應(yīng)總線的最低地址我們稱為該總線的基地址,總線基地址也是掛載在該總線上的首個外設(shè)的地址。其中APB1總線的地址最低,片上外設(shè)從這里開始,也叫外設(shè)基地址。

5.1.1 總線基地址

總線名稱 總線基地址 相對外設(shè)基地址的偏移
APB1 0x4000 0000 0x0
APB2 0x4001 0000 0x0001 0000
AHB 0x4001 8000 0x0001 8000

表格 總線基地址 的“相對外設(shè)基地址偏移”即該總線地址與“片上外設(shè)”基地址0x4000 0000的差值。關(guān)于地址的偏移我們后面還會講到。

5.1.2 外設(shè)基地址

在XX外設(shè)的地址范圍內(nèi),分布著的就是該外設(shè)的寄存器。以GPIO外設(shè)為例,GPIO是通用輸入輸出端口的簡稱, 簡單來說就是W55MH32可控制的引腳,基本功能是控制引腳輸出高電平或者低電平。最簡單的應(yīng)用就是把GPIO的引腳連接到LED燈的陰極, LED燈的陽極接電源,然后通過W55MH32控制該引腳的電平,從而實(shí)現(xiàn)控制LED燈的亮滅。

GPIO有很多個寄存器,每一個都有特定的功能。每個寄存器為32bit,占四個字節(jié),在該外設(shè)的基地址上按照順序排列, 寄存器的位置都以相對該外設(shè)基地址的偏移地址來描述。這里我們以GPIOB端口為例,來說明GPIO都有哪些寄存器, 具體見表格 GPIOB端口的寄存器地址列表:

寄存器名稱 寄存器地址 相對 GPIOB 基址的偏移
GPIOB_CRL 0x4001 0C00 0x00
GPIOB_CRH 0x4001 0C04 0x04
GPIOB_IDR 0x4001 0C08 0x08
GPIOB_ODR 0x4001 0C0C 0x0C
GPIOH_BSRR 0x4001 0C10 0x10
GPIOH_BRR 0x4001 0C14 0x14
GPIOH_LOCKR 0x4001 0C18 0x18

有關(guān)外設(shè)的寄存器說明可參考《W55MH32參考手冊》中具體章節(jié)的寄存器描述部分,在編程的時候我們需要反復(fù)的查閱外設(shè)的寄存器說明。

這里我們以“GPIO端口置位/復(fù)位寄存器”為例,教大家如何理解寄存器的說明, 具體見圖 GPIO端口置位_復(fù)位寄存器說明 。

wKgZO2gtTrqASRfPAAFNDE5jp44811.png

1 名稱

寄存器說明中首先列出了該寄存器中的名稱,“(GPIOx_BSRR)(x=A…E)”這段的意思是該寄存器名為“GPIOx_BSRR”其中的“x”可以為A-E, 也就是說這個寄存器說明適用于GPIOA、GPIOB至GPIOE,這些GPIO端口都有這樣的一個寄存器。

2 偏移地址

偏移地址是指本寄存器相對于這個外設(shè)的基地址的偏移。本寄存器的偏移地址是0x10, 從參考手冊中我們可以查到GPIOA外設(shè)的基地址為0x4001 0800 , 我們就可以算出GPIOA的這個GPIOA_BSRR寄存器的地址為:0x4001 0800+0x10;同理, 由于GPIOB的外設(shè)基地址為0x4001 0C00, 可算出GPIOB_BSRR寄存器的地址為:0x4001 0C00+0x10 。其他GPIO端口以此類推即可。

3 寄存器位表

緊接著的是本寄存器的位表,表中列出它的0-31位的名稱及權(quán)限。表上方的數(shù)字為位編號,中間為位名稱,最下方為讀寫權(quán)限,其中w表示只寫, r表示只讀,rw表示可讀寫。本寄存器中的位權(quán)限都是w,所以只能寫,如果讀本寄存器,是無法保證讀取到它真正內(nèi)容的。而有的寄存器位只讀, 一般是用于表示W(wǎng)55MH32外設(shè)的某種工作狀態(tài)的,由W55MH32硬件自動更改,程序通過讀取那些寄存器位來判斷外設(shè)的工作狀態(tài)。

4 位功能說明

位功能是寄存器說明中最重要的部分,它詳細(xì)介紹了寄存器每一個位的功能。例如本寄存器中有兩種寄存器位,分別為BRy及BSy, 其中的y數(shù)值可以是0-15,這里的0-15表示端口的引腳號,如BR0、BS0用于控制GPIOx的第0個引腳,若x表示GPIOA,那就是控制GPIOA的第0引腳, 而BR1、BS1就是控制GPIOA第1個引腳。

其中BRy引腳的說明是“0:不會對相應(yīng)的ODRx位執(zhí)行任何操作;1:對相應(yīng)ODRx位進(jìn)行復(fù)位”。這里的“復(fù)位”是將該位設(shè)置為0的意思, 而“置位”表示將該位設(shè)置為1;說明中的ODRx是另一個寄存器的寄存器位,我們只需要知道ODRx位為1的時候,對應(yīng)的引腳x輸出高電平, 為0的時候?qū)?yīng)的引腳輸出低電平即可(感興趣的讀者可以查詢該寄存器GPIOx_ODR的說明了解)。所以,如果對BR0寫入“1”的話, 那么GPIOx的第0個引腳就會輸出“低電平”,但是對BR0寫入“0”的話,卻不會影響ODR0位,所以引腳電平不會改變。要想該引腳輸出“高電平”, 就需要對“BS0”位寫入“1”,寄存器位BSy與BRy是相反的操作。

5.2 C語言對寄存器的封裝

以上所有的關(guān)于存儲器映射的內(nèi)容,最終都是為大家更好地理解如何用C語言控制讀寫外設(shè)寄存器做準(zhǔn)備,此處是本章的重點(diǎn)內(nèi)容。

5.2.1 封裝總線和外設(shè)基地址

在編程上為了方便理解和記憶,我們把總線基地址和外設(shè)基地址都以相應(yīng)的宏定義起來,總線或者外設(shè)都以他們的名字作為宏名, 具體見代碼清單:寄存器-4 。

代碼清單:寄存器-4 總線和外設(shè)基址宏定義

/* 外設(shè)基地址 */
#define PERIPH_BASE ((unsigned int)0x40000000)

/* 總線基地址 */
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE + 0x00010000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x00020000)


/* GPIO外設(shè)基地址 */
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400)
#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)
#define GPIOF_BASE (APB2PERIPH_BASE + 0x1C00)
#define GPIOG_BASE (APB2PERIPH_BASE + 0x2000)


/* 寄存器基地址,以GPIOB為例 */
#define GPIOB_CRL (GPIOB_BASE+0x00)
#define GPIOB_CRH (GPIOB_BASE+0x04)
#define GPIOB_IDR (GPIOB_BASE+0x08)
#define GPIOB_ODR (GPIOB_BASE+0x0C)
#define GPIOB_BSRR (GPIOB_BASE+0x10)
#define GPIOB_BRR (GPIOB_BASE+0x14)
#define GPIOB_LCKR (GPIOB_BASE+0x18)

代碼清單:寄存器-4 首先定義了 “片上外設(shè)”基地址PERIPH_BASE,接著在PERIPH_BASE上加入各個總線的地址偏移, 得到APB1、APB2總線的地址APB1PERIPH_BASE、APB2PERIPH_BASE,在其之上加入外設(shè)地址的偏移,得到GPIOA-G的外設(shè)地址, 最后在外設(shè)地址上加入各寄存器的地址偏移,得到特定寄存器的地址。一旦有了具體地址,就可以用指針讀寫, 具體見代碼清單:寄存器-5 。

代碼清單:寄存器-5 使用指針控制BSRR寄存器

/* 控制GPIOB 引腳0輸出低電平(BSRR寄存器的BR0置1) */
*(unsigned int *)GPIOB_BSRR = (0x01

該代碼使用 (unsigned int *) 把GPIOB_BSRR宏的數(shù)值強(qiáng)制轉(zhuǎn)換成了地址,然后再用“*”號做取指針操作,對該地址的賦值, 從而實(shí)現(xiàn)了寫寄存器的功能。同樣,讀寄存器也是用取指針操作,把寄存器中的數(shù)據(jù)取到變量里,從而獲取W55MH32外設(shè)的狀態(tài)。

5.2.2 封裝寄存器列表

用上面的方法去定義地址,還是稍顯繁瑣,例如GPIOA-GPIOE都各有一組功能相同的寄存器,如GPIOA_ODR/GPIOB_ODR/GPIOC_ODR等等, 它們只是地址不一樣,但卻要為每個寄存器都定義它的地址。為了更方便地訪問寄存器,我們引入C語言中的結(jié)構(gòu)體語法對寄存器進(jìn)行封裝, 具體見 代碼清單:寄存器-6 。

代碼清單:寄存器-6 使用結(jié)構(gòu)體對GPIO寄存器組的封裝

typedef unsigned int uint32_t; /*無符號32位變量*/
typedef unsigned short int uint16_t; /*無符號16位變量*/

/* GPIO寄存器列表 */
typedef struct {
uint32_t CRL; /*GPIO端口配置低寄存器 地址偏移: 0x00 */
uint32_t CRH; /*GPIO端口配置高寄存器 地址偏移: 0x04 */
uint32_t IDR; /*GPIO數(shù)據(jù)輸入寄存器 地址偏移: 0x08 */
uint32_t ODR; /*GPIO數(shù)據(jù)輸出寄存器 地址偏移: 0x0C */
uint32_t BSRR; /*GPIO位設(shè)置/清除寄存器 地址偏移: 0x10 */
uint32_t BRR; /*GPIO端口位清除寄存器 地址偏移: 0x14 */
uint16_t LCKR; /*GPIO端口配置鎖定寄存器 地址偏移: 0x18 */
} GPIO_TypeDef;

這段代碼用typedef 關(guān)鍵字聲明了名為GPIO_TypeDef的結(jié)構(gòu)體類型,結(jié)構(gòu)體內(nèi)有7個 成員變量,變量名正好對應(yīng)寄存器的名字。 C語言的語法規(guī)定,結(jié)構(gòu)體內(nèi)變量的存儲空間是連續(xù)的,其中32位的變量占用4個字節(jié),16位的變量占用2個字節(jié), 具體見圖 GPIO_TypeDef結(jié)構(gòu)體成員的地址偏移 。

wKgZO2gtTrqAZ7ZjAACSJsGyZ-Q697.png

也就是說,我們定義的這個GPIO_TypeDef ,假如這個結(jié)構(gòu)體的首地址為0x4001 0C00(這也是第一個成員變量CRL的地址), 那么結(jié)構(gòu)體中第二個成員變量CRH的地址即為0x4001 0C00 +0x04 ,加上的這個0x04,正是代表CRL所占用的4個字節(jié)地址的偏移量, 其它成員變量相對于結(jié)構(gòu)體首地址的偏移,在上述代碼右側(cè)注釋已給。

這樣的地址偏移與W55MH32 GPIO外設(shè)定義的寄存器地址偏移一一對應(yīng),只要給結(jié)構(gòu)體設(shè)置好首地址,就能把結(jié)構(gòu)體內(nèi)成員的地址確定下來, 然后就能以結(jié)構(gòu)體的形式訪問寄存器,具體見 代碼清單:寄存器-7 。

代碼清單:寄存器-7 通過結(jié)構(gòu)體指針訪問寄存器

GPIO_TypeDef * GPIOx; //定義一個GPIO_TypeDef型結(jié)構(gòu)體指針GPIOx
GPIOx = GPIOB_BASE; //把指針地址設(shè)置為宏GPIOB_BASE地址
GPIOx->IDR = 0xFFFF;
GPIOx->ODR = 0xFFFF;

uint32_t temp;
temp = GPIOx->IDR; //讀取GPIOB_IDR寄存器的值到變量temp中

這段代碼先用GPIO_TypeDef類型定義一個結(jié)構(gòu)體指針GPIOx,并讓指針指向地址GPIOB_BASE(0x4001 0C00),使用地址確定下來, 然后根據(jù)C語言訪問結(jié)構(gòu)體的語法,用GPIOx->ODR及GPIOx->IDR等方式讀寫寄存器。

最后,我們更進(jìn)一步,直接使用宏定義好GPIO_TypeDef類型的指針,而且指針指向各個GPIO端口的首地址, 使用時我們直接用該宏訪問寄存器即可,具體 代碼清單:寄存器-8 。

代碼清單:寄存器-8 定義好GPIO端口首地址址針

/*使用GPIO_TypeDef把地址強(qiáng)制轉(zhuǎn)換成指針*/
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)
#define GPIOH ((GPIO_TypeDef *) GPIOH_BASE)


/*使用定義好的宏直接訪問*/
/*訪問GPIOB端口的寄存器*/
GPIOB->BSRR = 0xFFFF; //通過指針訪問并修改GPIOB_BSRR寄存器
GPIOB->CRL = 0xFFFF; //修改GPIOB_CRL寄存器
GPIOB->ODR =0xFFFF; //修改GPIOB_ODR寄存器

uint32_t temp;
temp = GPIOB->IDR; //讀取GPIOB_IDR寄存器的值到變量temp中

/*訪問GPIOA端口的寄存器*/
GPIOA->BSRR = 0xFFFF;
GPIOA->CRL = 0xFFFF;
GPIOA->ODR =0xFFFF;

uint32_t temp;
temp = GPIOA->IDR; //讀取GPIOA_IDR寄存器的值到變量temp中

這里我們僅是以GPIO這個外設(shè)為例,給大家講解了C語言對寄存器的封裝。以此類推,其他外設(shè)也同樣可以用這種方法來封裝。好消息是, 這部分工作都由固件庫幫我們完成了,這里我們只是分析了下這個封裝的過程,讓大家知其然,也只其所以然。

5.3 修改寄存器的位操作方法

使用C語言對寄存器賦值時,我們常常要求只修改該寄存器的某幾位的值,且其它的寄存器位不變,這個時候我們就需要用到C語言的位操作方法了。

5.3.1 把變量的某位清零

此處我們以變量a代表寄存器,并假設(shè)寄存器中本來已有數(shù)值,此時我們需要把變量a的某一位清零,且其它位不變, 方法見 代碼清單:寄存器-9 。

代碼清單:寄存器-9 對某位清零

//定義一個變量a = 1001 1111 b (二進(jìn)制數(shù))
unsigned char a = 0x9f;

//對bit2 清零

a &= ~(1

5.3.2 把變量的某幾個連續(xù)位清零

由于寄存器中有時會有連續(xù)幾個寄存器位用于控制某個功能,現(xiàn)假設(shè)我們需要把寄存器的某幾個連續(xù)位清零, 且其它位不變,方法見 代碼清單:寄存器-10 。

代碼清單:寄存器-10 對某幾個連續(xù)位清零

//若把a(bǔ)中的二進(jìn)制位分成2個一組
//即bit0、bit1為第0組,bit2、bit3為第1組,
// bit4、bit5為第2組,bit6、bit7為第3組
//要對第1組的bit2、bit3清零

a &= ~(3

5.3.3 對變量的某幾位進(jìn)行賦值。

寄存器位經(jīng)過上面的清零操作后,接下來就可以方便地對某幾位寫入所需要的數(shù)值了,且其它位不變, 方法見 代碼清單:寄存器-11 ,這時候?qū)懭氲臄?shù)值一般就是需要設(shè)置寄存器的位參數(shù)。

代碼清單:寄存器-11 對某幾位進(jìn)行賦值

//a = 1000 0011 b
//此時對清零后的第2組bit4、bit5設(shè)置成二進(jìn)制數(shù)“01 b ”

a |= (1

5.3.4 對變量的某位取反

某些情況下,我們需要對寄存器的某個位進(jìn)行取反操作,即 1變0 ,0變1,這可以直接用如下操作,其它位不變, 見代碼清單:寄存器-12 。

代碼清單:寄存器-12 對某位進(jìn)行取反操作

//a = 1001 0011 b
//把bit6取反,其它位不變

a ^=(1

WIZnet 是一家無晶圓廠半導(dǎo)體公司,成立于 1998 年。產(chǎn)品包括互聯(lián)網(wǎng)處理器 iMCU?,它采用 TOE(TCP/IP 卸載引擎)技術(shù),基于獨(dú)特的專利全硬連線 TCP/IP。iMCU? 面向各種應(yīng)用中的嵌入式互聯(lián)網(wǎng)設(shè)備。

WIZnet 在全球擁有 70 多家分銷商,在香港、韓國、美國設(shè)有辦事處,提供技術(shù)支持和產(chǎn)品營銷。

香港辦事處管理的區(qū)域包括:澳大利亞、印度、土耳其、亞洲(韓國和日本除外)。

審核編輯 黃宇

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6076

    文章

    45492

    瀏覽量

    670137
  • 以太網(wǎng)
    +關(guān)注

    關(guān)注

    41

    文章

    5995

    瀏覽量

    180753
  • 寄存器
    +關(guān)注

    關(guān)注

    31

    文章

    5608

    瀏覽量

    129943
  • WIZnet
    +關(guān)注

    關(guān)注

    3

    文章

    20

    瀏覽量

    42847
收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評論

    相關(guān)推薦
    熱點(diǎn)推薦

    深入解析CY74FCT399T:一款高性能的2輸入寄存器

    深入解析CY74FCT399T:一款高性能的2輸入寄存器 在電子工程師的日常設(shè)計中,選擇合適的寄存器對于實(shí)現(xiàn)高效、穩(wěn)定的電路至關(guān)重要。今天,我們就來深入了解一下德州儀器(Texas
    的頭像 發(fā)表于 01-16 17:10 ?837次閱讀

    LAT1170+如何理解 RAMECC FAR 寄存器的值

    電子發(fā)燒友網(wǎng)站提供《LAT1170+如何理解 RAMECC FAR 寄存器的值.pdf》資料免費(fèi)下載
    發(fā)表于 01-09 16:12 ?0次下載

    【NCS隨筆】nRF54L15使用UICR寄存器保存數(shù)據(jù)

    nRF54L15使用UICR寄存器保存數(shù)據(jù) 本文章主要是講解如何使用nRF54L15的UICR寄存器保存一些基礎(chǔ)數(shù)據(jù) 一、UICR寄存器的說明 UICR(用戶信息配置寄存器)**是非易
    的頭像 發(fā)表于 11-27 17:09 ?1506次閱讀

    嵌入式系統(tǒng)必懂的 20 個寄存器

    嵌入式開發(fā)看起來很復(fù)雜,但很多操作其實(shí)都離不開寄存器。寄存器就是MCU內(nèi)部的存儲單元,它們控制著處理和外設(shè)的行為。熟悉這些寄存器,你就能更精確地操作硬件,提高開發(fā)效率,減少調(diào)試時間。
    的頭像 發(fā)表于 11-14 10:28 ?1081次閱讀
    嵌入式系統(tǒng)必懂的 20 個<b class='flag-5'>寄存器</b>

    NVMe高速傳輸之?dāng)[脫XDMA設(shè)計32:寄存器功能驗(yàn)證與分析2

    寄存器最大值為 64’hFFFFFFFFFFFFFFFF,到達(dá)最大值后一個時鐘周期后翻轉(zhuǎn)回 0, 在隨機(jī)時刻使用 force 將寄存器賦值臨近最大值, 當(dāng)寄存器達(dá)到最大值后, 翻轉(zhuǎn)回到 0, 讀取數(shù)值為 0, 仿真行為符合設(shè)計預(yù)
    的頭像 發(fā)表于 10-14 17:06 ?714次閱讀
    NVMe高速傳輸之?dāng)[脫XDMA設(shè)計32:<b class='flag-5'>寄存器</b>功能驗(yàn)證與分析2

    ?SN74LVC595A 8位移位寄存器技術(shù)文檔總結(jié)

    SN74LVC595A器件包含一個8位串行輸入、并聯(lián)輸出移位寄存器,該寄存器為8位D型存儲寄存器供電。存儲寄存器具有并行的 3 態(tài)輸出。為移位寄存器
    的頭像 發(fā)表于 09-28 15:09 ?1392次閱讀
    ?SN74LVC595A 8位移位<b class='flag-5'>寄存器</b>技術(shù)文檔總結(jié)

    ?SN74HCT595 8位移位寄存器技術(shù)解析與應(yīng)用指南

    Texas Instruments SN74HCT595/SN74HCT595-Q1 8位移位寄存器包含8位串進(jìn)并出移位寄存器,向8位D類存儲寄存器饋送信號。存儲寄存器具有并行 3 狀
    的頭像 發(fā)表于 09-19 14:31 ?935次閱讀
    ?SN74HCT595 8位移位<b class='flag-5'>寄存器</b>技術(shù)解析與應(yīng)用指南

    TPIC6595 8位功率移位寄存器技術(shù)文檔摘要

    該TPIC6595是一款單片、高壓、大電流功率的8位移位寄存器,設(shè)計用于需要相對較高負(fù)載功率的系統(tǒng)。該器件在輸出端包含一個內(nèi)置電壓鉗位,用于電感瞬態(tài)保護(hù)。功率驅(qū)動應(yīng)用包括繼電器、螺線管和其他中電流
    的頭像 發(fā)表于 09-09 11:10 ?920次閱讀
    TPIC6595 8位功率移位<b class='flag-5'>寄存器</b>技術(shù)文檔摘要

    ?TPIC6B595 8位功率移位寄存器技術(shù)文檔總結(jié)

    TPIC6B595器件是一款單片、高壓、中電流功率8位移位寄存器,設(shè)計用于需要相對高負(fù)載功率的系統(tǒng)。該器件在輸出端包含一個內(nèi)置電壓鉗位,用于電感瞬態(tài)保護(hù)。功率驅(qū)動應(yīng)用包括繼電器、螺線管和其他中電流
    的頭像 發(fā)表于 09-09 10:16 ?1008次閱讀
    ?TPIC6B595 8位功率移位<b class='flag-5'>寄存器</b>技術(shù)文檔總結(jié)

    ?TLC6C5912 12通道移位寄存器LED驅(qū)動技術(shù)文檔總結(jié)

    該TLC6C5912是一款單片、中壓、低電流功率 12 位移位寄存器 設(shè)計用于需要相對中等負(fù)載功率的系統(tǒng),例如 LED。 該器件包含一個 12 位串行輸入并行輸出移位寄存器,可為 12 位饋電
    的頭像 發(fā)表于 08-26 14:16 ?993次閱讀
    ?TLC6C5912 12通道移位<b class='flag-5'>寄存器</b>LED驅(qū)動<b class='flag-5'>器</b>技術(shù)文檔總結(jié)

    【「DeepSeek 核心技術(shù)揭秘」閱讀體驗(yàn)】--全書概覽

    講解Deepseek的使用方法 第三 深入剖析Deepseek-V3的模型架構(gòu)、訓(xùn)練框架、推理階段優(yōu)化、后訓(xùn)練優(yōu)化等關(guān)鍵技術(shù) 第四章關(guān)于DeepSeek-R1的技術(shù)剖析 第五 從宏觀角度分析
    發(fā)表于 07-21 00:04

    初級工程師PCB設(shè)計技巧(PPT版)

    目錄第一:PCB 概述第二:PCB 設(shè)計流程及PCB Layout 設(shè)計第三: PROTEL 常用操作第四章: PCB Layout 技巧 獲取完整文檔資料可下載附件哦?。。?!
    發(fā)表于 06-26 15:50

    使用寄存器點(diǎn)亮LED燈

    學(xué)習(xí)本章時,配合以上芯片手冊中的“19. I/O Ports”章節(jié)一起閱讀,效果會更佳,特別是涉及到寄存器說明的部分。本章內(nèi)容涉及到較多寄存器方面的深入內(nèi)容,對于初學(xué)者而言這些內(nèi)容豐富也較難理解,但非常有必要細(xì)讀研究、夯實(shí)基礎(chǔ)。
    的頭像 發(fā)表于 05-28 17:37 ?1305次閱讀
    使用<b class='flag-5'>寄存器</b>點(diǎn)亮LED燈

    第四章 定時任務(wù)】手把手教你玩轉(zhuǎn)新版正點(diǎn)原子云

    第四章 定時任務(wù)】手把手教你玩轉(zhuǎn)新版正點(diǎn)原子云 承接上篇,除了報警聯(lián)動這個功能,原子云還有一個特色功能也是各開發(fā)者喜歡用的,定時任務(wù)功能。 【正點(diǎn)原子】云平臺:原子云(點(diǎn)擊登錄原子云) 前言
    發(fā)表于 03-13 10:19

    汽車電路初識

    第一 汽車電路分析基礎(chǔ)第二 汽車電路圖識讀第三 典型汽車電器電路分析第四章 汽車電路檢修第五 汽車電子電路圖識讀
    發(fā)表于 03-10 18:04 ?7次下載