一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

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

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(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,滿足存儲(chǔ)與數(shù)據(jù)處理需求;集成TOE引擎,包含WIZnet全硬件TCP/IP協(xié)議棧、內(nèi)置MAC以及PHY,擁有獨(dú)立的32KB以太網(wǎng)收發(fā)緩存,可供8個(gè)獨(dú)立硬件socket使用。如此配置,真正實(shí)現(xiàn)了All-in-One解決方案,為開發(fā)者提供極大便利。

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

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

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

wKgZPGgbOfaANhwzACodXd3sVzg463.png

第四章 什么是寄存器

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

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

1 什么是寄存器

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

2 W55MH32

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

芯片四周是引腳,開發(fā)板中把芯片的引腳引出來,連接到各種傳感器上,然后在W55MH32L上編程(實(shí)際就是通過程序控制這些引腳輸出高電平或者低電平)來控制各種傳感器工作, 通過做實(shí)驗(yàn)的方式來學(xué)習(xí)W55MH32芯片的各個(gè)資源。開發(fā)板是一種評(píng)估板,板載資源非常豐富,引腳復(fù)用比較多, 力求在一個(gè)板子上驗(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è)計(jì)部件并生產(chǎn)整個(gè)芯片,這些內(nèi)核之外的部件被稱為核外外設(shè)或片上外設(shè)。 如GPIO、USART(串口)、I2C、SPI等都叫做片上外設(shè)。

wKgZO2gtTruAHumwAAElNiRtqW4779.png

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

3.1 ICode總線

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

3.2 驅(qū)動(dòng)單元

3.2.1 DCode總線

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

3.2.2 系統(tǒng)總線

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

3.2.3 DMA總線

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

3.3 被動(dòng)單元

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

內(nèi)部的閃存存儲(chǔ)器即FLASH,我們編寫好的程序就放在這個(gè)地方。內(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)的存儲(chǔ)器控制器, 是W55MH32中一個(gè)很有特色的外設(shè), 通過FSMC,我們可以擴(kuò)展內(nèi)存,如外部的SRAM,NANDFLASH和NORFLASH。但有一點(diǎn)我們要注意的是,F(xiàn)SMC只能擴(kuò)展靜態(tài)的內(nèi)存, 即名稱里面的S:static,不能是動(dòng)態(tài)的內(nèi)存,比如SDRAM就不能擴(kuò)展。

3.3.4 AHB到APB的橋

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

wKgZO2gtbMyAQMsAAAKz8dGRy80597.png

4 存儲(chǔ)器映射

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

4.1 存儲(chǔ)器映射

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

wKgZPGgtTrqAX4OdAAjXV68IGZA800.png

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

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

序號(hào) 用途 地址范圍
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個(gè)Block里面,有3個(gè)塊非常重要,也是我們最關(guān)心的三個(gè)塊。Block0用來設(shè)計(jì)成內(nèi)部FLASH,Block1用來設(shè)計(jì)成內(nèi)部RAM, Block2用來設(shè)計(jì)成片上的外設(shè),下面我們簡(jiǎn)單的介紹下這三個(gè)Block里面的具體區(qū)域的功能劃分。

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

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

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

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

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

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

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

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

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

5 寄存器映射

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

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

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

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

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

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

剛剛我們說了,通過絕對(duì)地址訪問內(nèi)存單元不好記憶且容易出錯(cuò),我們可以通過寄存器的方式來操作,具體見代碼清單:寄存器-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)總線的最低地址我們稱為該總線的基地址,總線基地址也是掛載在該總線上的首個(gè)外設(shè)的地址。其中APB1總線的地址最低,片上外設(shè)從這里開始,也叫外設(shè)基地址。

5.1.1 總線基地址

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

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

5.1.2 外設(shè)基地址

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

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

寄存器名稱 寄存器地址 相對(duì) 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參考手冊(cè)》中具體章節(jié)的寄存器描述部分,在編程的時(shí)候我們需要反復(fù)的查閱外設(shè)的寄存器說明。

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

wKgZO2gtTrqASRfPAAFNDE5jp44811.png

1 名稱

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

2 偏移地址

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

3 寄存器位表

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

4 位功能說明

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

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

5.2 C語言對(duì)寄存器的封裝

以上所有的關(guān)于存儲(chǔ)器映射的內(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上加入各個(gè)總線的地址偏移, 得到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)換成了地址,然后再用“*”號(hào)做取指針操作,對(duì)該地址的賦值, 從而實(shí)現(xiàn)了寫寄存器的功能。同樣,讀寄存器也是用取指針操作,把寄存器中的數(shù)據(jù)取到變量里,從而獲取W55MH32外設(shè)的狀態(tài)。

5.2.2 封裝寄存器列表

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

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

typedef unsigned int uint32_t; /*無符號(hào)32位變量*/
typedef unsigned short int uint16_t; /*無符號(hào)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個(gè) 成員變量,變量名正好對(duì)應(yīng)寄存器的名字。 C語言的語法規(guī)定,結(jié)構(gòu)體內(nèi)變量的存儲(chǔ)空間是連續(xù)的,其中32位的變量占用4個(gè)字節(jié),16位的變量占用2個(gè)字節(jié), 具體見圖 GPIO_TypeDef結(jié)構(gòu)體成員的地址偏移 。

wKgZO2gtTrqAZ7ZjAACSJsGyZ-Q697.png

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

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

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

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

最后,我們更進(jìn)一步,直接使用宏定義好GPIO_TypeDef類型的指針,而且指針指向各個(gè)GPIO端口的首地址, 使用時(shí)我們直接用該宏訪問寄存器即可,具體 代碼清單:寄存器-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這個(gè)外設(shè)為例,給大家講解了C語言對(duì)寄存器的封裝。以此類推,其他外設(shè)也同樣可以用這種方法來封裝。好消息是, 這部分工作都由固件庫幫我們完成了,這里我們只是分析了下這個(gè)封裝的過程,讓大家知其然,也只其所以然。

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

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

5.3.1 把變量的某位清零

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

代碼清單:寄存器-9 對(duì)某位清零

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

//對(duì)bit2 清零

a &= ~(1

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

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

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

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

a &= ~(3

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

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

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

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

a |= (1

5.3.4 對(duì)變量的某位取反

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

代碼清單:寄存器-12 對(duì)某位進(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)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • 單片機(jī)
    +關(guān)注

    關(guān)注

    6067

    文章

    44992

    瀏覽量

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

    關(guān)注

    41

    文章

    5635

    瀏覽量

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

    關(guān)注

    31

    文章

    5434

    瀏覽量

    124485
  • WIZnet
    +關(guān)注

    關(guān)注

    3

    文章

    20

    瀏覽量

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

掃碼添加小助手

加入工程師交流群

    評(píng)論

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

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

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

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

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

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

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

    汽車電路初識(shí)

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

    XILINX FPGA CLB單元之移位寄存器

    )和移出Q31(MC31 LUT引腳)線路將LUT級(jí)聯(lián),以形成更大的移位寄存器。因此,SLICEM中的個(gè)LUT被級(jí)聯(lián)以產(chǎn)生高達(dá)128個(gè)時(shí)鐘周期的延遲。也可以在多個(gè)SLICEM上組合移位寄存器
    的頭像 發(fā)表于 01-16 17:45 ?807次閱讀
    XILINX FPGA CLB單元之移位<b class='flag-5'>寄存器</b>

    中科芯CKS32K148 MCU SCG時(shí)鐘工作頻率范圍和寄存器設(shè)置

    第四十五期的SCG介紹,下文對(duì)SCG時(shí)鐘工作頻率范圍、寄存器設(shè)置等進(jìn)行詳細(xì)闡述。
    的頭像 發(fā)表于 12-09 14:55 ?924次閱讀
    中科芯CKS32K148 MCU SCG時(shí)鐘工作頻率范圍和<b class='flag-5'>寄存器</b>設(shè)置

    接口的控制與狀態(tài)寄存器什么作用

    接口的控制與狀態(tài)寄存器(Control and Status Registers,簡(jiǎn)稱CSR)是計(jì)算機(jī)系統(tǒng)中用于控制和監(jiān)控硬件設(shè)備操作的寄存器。它們是硬件設(shè)備與其驅(qū)動(dòng)程序之間的橋梁,允許軟件控制硬件
    的頭像 發(fā)表于 10-17 10:42 ?1525次閱讀

    【「嵌入式Hypervisor:架構(gòu)、原理與應(yīng)用」閱讀體驗(yàn)】+第三四章閱讀報(bào)告

    與重定向等機(jī)制。 第四章:PRTOS Hypervisor的設(shè)計(jì)與實(shí)現(xiàn) 內(nèi)容概述 : 第四章則聚焦于PRTOS(Portable Real-Time Operating System)Hypervisor
    發(fā)表于 10-09 18:29

    寄存器間接尋址和寄存器尋址的區(qū)別

    寄存器間接尋址和寄存器尋址是計(jì)算機(jī)體系結(jié)構(gòu)中兩種重要的尋址方式,它們?cè)谥噶顖?zhí)行過程中起著關(guān)鍵作用。下面將從定義、原理、特點(diǎn)、應(yīng)用場(chǎng)景以及區(qū)別等方面對(duì)這兩種尋址方式進(jìn)行詳細(xì)闡述。
    的頭像 發(fā)表于 10-05 17:13 ?3680次閱讀

    ARM寄存器的分類及功能

    ARM寄存器是ARM處理內(nèi)部的重要組成部分,它們?cè)谔幚?b class='flag-5'>器的運(yùn)算、控制以及數(shù)據(jù)存儲(chǔ)等方面發(fā)揮著至關(guān)重要的作用。下面,我們將從ARM寄存器的定義、結(jié)構(gòu)、分類以及功能等多個(gè)方面進(jìn)行詳細(xì)闡述
    的頭像 發(fā)表于 09-05 14:18 ?2932次閱讀

    通用寄存器是什么意思

    在計(jì)算機(jī)體系結(jié)構(gòu)中,通用寄存器是中央處理(CPU)內(nèi)部最為核心和基礎(chǔ)的組成部分之一。它們被設(shè)計(jì)為能夠存儲(chǔ)和傳輸各種類型的數(shù)據(jù)和指令,是CPU進(jìn)行數(shù)據(jù)處理和運(yùn)算的關(guān)鍵工具。通用寄存器不僅在程序的執(zhí)行過程中起著至關(guān)重要的作用,還直
    的頭像 發(fā)表于 09-05 14:13 ?2332次閱讀

    寄存器的類型和作用

    在計(jì)算機(jī)科學(xué)中,寄存器(Register)是一種高速存儲(chǔ)單元,它位于CPU內(nèi)部,與CPU的運(yùn)算單元和邏輯控制單元緊密相連。寄存器的主要作用是暫時(shí)存儲(chǔ)指令、操作數(shù)和地址等臨時(shí)數(shù)據(jù),以便CPU快速訪問和處理。由于寄存器直接集成在CP
    的頭像 發(fā)表于 09-05 14:11 ?4771次閱讀

    寄存器的輸入輸出方式

    寄存器的輸入輸出方式是數(shù)字電路設(shè)計(jì)中至關(guān)重要的部分,它決定了數(shù)據(jù)如何在寄存器中進(jìn)出以及處理的效率。下面將詳細(xì)探討寄存器的幾種主要輸入輸出方式,包括并行輸入輸出、串行輸入輸出以及雙向輸入輸出,并會(huì)擴(kuò)展到移位
    的頭像 發(fā)表于 09-05 14:09 ?2636次閱讀

    寄存器故障分析

    寄存器故障分析是計(jì)算機(jī)硬件維護(hù)與系統(tǒng)穩(wěn)定性保障中的重要環(huán)節(jié)。寄存器作為計(jì)算機(jī)中的關(guān)鍵組成部分,負(fù)責(zé)存儲(chǔ)和傳輸數(shù)據(jù),其穩(wěn)定性和可靠性直接影響到整個(gè)計(jì)算機(jī)系統(tǒng)的性能。以下是對(duì)寄存器故障的全面分析,包括故障類型、故障現(xiàn)象、故障原因及診
    的頭像 發(fā)表于 08-29 11:26 ?2175次閱讀

    寄存器是什么意思?寄存器是如何構(gòu)成的?

    在計(jì)算機(jī)科學(xué)中,寄存器(Register)是一個(gè)高速存儲(chǔ)單元,它位于中央處理(CPU)內(nèi)部,用于存儲(chǔ)計(jì)算機(jī)程序執(zhí)行過程中所需要的數(shù)據(jù)、指令地址或狀態(tài)信息。寄存器是計(jì)算機(jī)體系結(jié)構(gòu)中至關(guān)重要的組成部分,對(duì)計(jì)算機(jī)的運(yùn)算速度和性能有著
    的頭像 發(fā)表于 08-02 18:23 ?7561次閱讀
    <b class='flag-5'>寄存器</b>是什么意思?<b class='flag-5'>寄存器</b>是如何構(gòu)成的?