在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

第四章 什么是寄存器

W55MH32 ? 來源:W55MH32 ? 作者:W55MH32 ? 2025-05-21 14:23 ? 次閱讀

單芯片解決方案,開啟全新體驗——W55MH32 高性能以太網單片機

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

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

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

此外,本W55MH32支持硬件加密算法單元,WIZnet還推出TOE+SSL應用,涵蓋TCP SSL、HTTP SSL以及 MQTT SSL等,為網絡通信安全再添保障。

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

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

wKgZPGgbOfaANhwzACodXd3sVzg463.png

第四章 什么是寄存器

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

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

1 什么是寄存器

我們經常說寄存器,那么什么是寄存器?這是我們本章需要講解的內容,在學習的過程中,大家帶著這個疑問好好思考下,到最后看看大家能否用一句話給寄存器下一個定義。

2 W55MH32

我們開發板中使用的芯片是100pin的W55MH32L,具體見下圖。這個就是我們接下來要學習的高性能以太網單片機,它將帶領我們進入嵌入式的殿堂。

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

wKgZPGgtTrqATxpWAAjzNQE-9Xg370.pngwKgZPGgRskSACVm2AAGG5sO9Q70099.png

3 芯片里面有什么

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

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

wKgZO2gtTruAHumwAAElNiRtqW4779.png

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

3.1 ICode總線

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

3.2 驅動單元

3.2.1 DCode總線

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

3.2.2 系統總線

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

3.2.3 DMA總線

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

3.3 被動單元

3.3.1 內部的閃存存儲器

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

3.3.2 內部的SRAM

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

3.3.3 FSMC

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

3.3.4 AHB到APB的橋

從AHB總線延伸出來的兩條APB2和APB1總線,上面掛載著W55MH32各種各樣的特色外設。我們經常說的GPIO、串口、I2C、SPI這些外設就掛載在這兩條總線上, 這個是我們學習W55MH32的重點,就是要學會編程這些外設去驅動外部的各種設備。

wKgZO2gtbMyAQMsAAAKz8dGRy80597.png

4 存儲器映射

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

4.1 存儲器映射

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

wKgZPGgtTrqAX4OdAAjXV68IGZA800.png

4.1.1 存儲器區域功能劃分

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

序號 用途 地址范圍
Block 0 Code 0x0000 0000 ~ 0x1FFF FFFF(512MB)
Block 1 SRAM 0x2000 0000 ~ 0x3FFF FFFF(512MB)
Block 2 片上外設 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 內部外設 0xE000 0000 ~ 0xFFFF FFFF(512MB)

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

4.1.1.1 存儲器Block0內部區域功能劃分

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

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

4.1.1.2 儲存器Block1內部區域功能劃分

Block1用于設計片內的SRAM,Block內部區域的功能劃分具體見表格 存儲器Block1內部區域功能劃分 。

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

4.1.1.3 儲存器Block2內部區域功能劃分

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

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

5 寄存器映射

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

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

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

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

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

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

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

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

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

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

代碼清單:寄存器-3 通過寄存器別名訪問內存單元

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

5.1 W55MH32的外設地址映射

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

5.1.1 總線基地址

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

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

5.1.2 外設基地址

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

GPIO有很多個寄存器,每一個都有特定的功能。每個寄存器為32bit,占四個字節,在該外設的基地址上按照順序排列, 寄存器的位置都以相對該外設基地址的偏移地址來描述。這里我們以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

有關外設的寄存器說明可參考《W55MH32參考手冊》中具體章節的寄存器描述部分,在編程的時候我們需要反復的查閱外設的寄存器說明。

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

wKgZO2gtTrqASRfPAAFNDE5jp44811.png

1 名稱

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

2 偏移地址

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

3 寄存器位表

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

4 位功能說明

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

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

5.2 C語言對寄存器的封裝

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

5.2.1 封裝總線和外設基地址

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

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

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

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


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

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

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

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

5.2.2 封裝寄存器列表

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

代碼清單:寄存器-6 使用結構體對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數據輸入寄存器 地址偏移: 0x08 */
uint32_t ODR; /*GPIO數據輸出寄存器 地址偏移: 0x0C */
uint32_t BSRR; /*GPIO位設置/清除寄存器 地址偏移: 0x10 */
uint32_t BRR; /*GPIO端口位清除寄存器 地址偏移: 0x14 */
uint16_t LCKR; /*GPIO端口配置鎖定寄存器 地址偏移: 0x18 */
} GPIO_TypeDef;

這段代碼用typedef 關鍵字聲明了名為GPIO_TypeDef的結構體類型,結構體內有7個 成員變量,變量名正好對應寄存器的名字。 C語言的語法規定,結構體內變量的存儲空間是連續的,其中32位的變量占用4個字節,16位的變量占用2個字節, 具體見圖 GPIO_TypeDef結構體成員的地址偏移 。

wKgZO2gtTrqAZ7ZjAACSJsGyZ-Q697.png

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

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

代碼清單:寄存器-7 通過結構體指針訪問寄存器

GPIO_TypeDef * GPIOx; //定義一個GPIO_TypeDef型結構體指針GPIOx
GPIOx = GPIOB_BASE; //把指針地址設置為宏GPIOB_BASE地址
GPIOx->IDR = 0xFFFF;
GPIOx->ODR = 0xFFFF;

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

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

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

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

/*使用GPIO_TypeDef把地址強制轉換成指針*/
#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這個外設為例,給大家講解了C語言對寄存器的封裝。以此類推,其他外設也同樣可以用這種方法來封裝。好消息是, 這部分工作都由固件庫幫我們完成了,這里我們只是分析了下這個封裝的過程,讓大家知其然,也只其所以然。

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

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

5.3.1 把變量的某位清零

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

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

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

//對bit2 清零

a &= ~(1

5.3.2 把變量的某幾個連續位清零

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

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

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

a &= ~(3

5.3.3 對變量的某幾位進行賦值。

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

代碼清單:寄存器-11 對某幾位進行賦值

//a = 1000 0011 b
//此時對清零后的第2組bit4、bit5設置成二進制數“01 b ”

a |= (1

5.3.4 對變量的某位取反

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

代碼清單:寄存器-12 對某位進行取反操作

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

a ^=(1

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

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

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

審核編輯 黃宇

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 單片機
    +關注

    關注

    6061

    文章

    44866

    瀏覽量

    646008
  • 以太網
    +關注

    關注

    40

    文章

    5573

    瀏覽量

    174569
  • 寄存器
    +關注

    關注

    31

    文章

    5412

    瀏覽量

    123115
  • WIZnet
    +關注

    關注

    3

    文章

    21

    瀏覽量

    42362
收藏 人收藏

    評論

    相關推薦
    熱點推薦

    第四章 定時任務】手把手教你玩轉新版正點原子云

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

    接口的控制與狀態寄存器什么作用

    接口的控制與狀態寄存器(Control and Status Registers,簡稱CSR)是計算機系統中用于控制和監控硬件設備操作的寄存器。它們是硬件設備與其驅動程序之間的橋梁,允許軟件控制硬件
    的頭像 發表于 10-17 10:42 ?1321次閱讀

    【「嵌入式Hypervisor:架構、原理與應用」閱讀體驗】+第三四章閱讀報告

    與重定向等機制。 第四章:PRTOS Hypervisor的設計與實現 內容概述 : 第四章則聚焦于PRTOS(Portable Real-Time Operating System)Hypervisor
    發表于 10-09 18:29

    寄存器間接尋址和寄存器尋址的區別

    寄存器間接尋址和寄存器尋址是計算機體系結構中兩種重要的尋址方式,它們在指令執行過程中起著關鍵作用。下面將從定義、原理、特點、應用場景以及區別等方面對這兩種尋址方式進行詳細闡述。
    的頭像 發表于 10-05 17:13 ?3116次閱讀

    通用寄存器是什么意思

    在計算機體系結構中,通用寄存器是中央處理(CPU)內部最為核心和基礎的組成部分之一。它們被設計為能夠存儲和傳輸各種類型的數據和指令,是CPU進行數據處理和運算的關鍵工具。通用寄存器不僅在程序的執行過程中起著至關重要的作用,還直
    的頭像 發表于 09-05 14:13 ?1902次閱讀

    寄存器的類型和作用

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

    寄存器故障分析

    寄存器故障分析是計算機硬件維護與系統穩定性保障中的重要環節。寄存器作為計算機中的關鍵組成部分,負責存儲和傳輸數據,其穩定性和可靠性直接影響到整個計算機系統的性能。以下是對寄存器故障的全面分析,包括故障類型、故障現象、故障原因及診
    的頭像 發表于 08-29 11:26 ?1893次閱讀

    寄存器是什么意思?寄存器是如何構成的?

    在計算機科學中,寄存器(Register)是一個高速存儲單元,它位于中央處理(CPU)內部,用于存儲計算機程序執行過程中所需要的數據、指令地址或狀態信息。寄存器是計算機體系結構中至關重要的組成部分,對計算機的運算速度和性能有著
    的頭像 發表于 08-02 18:23 ?6746次閱讀
    <b class='flag-5'>寄存器</b>是什么意思?<b class='flag-5'>寄存器</b>是如何構成的?

    寄存器尋址和直接尋址的區別

    寄存器尋址和直接尋址是計算機指令系統中的兩種基本尋址方式。它們在指令的執行過程中起著至關重要的作用,決定了指令操作數的來源和目標。下面我們將介紹這兩種尋址方式的特點、區別以及在實際應用中的優缺點
    的頭像 發表于 07-12 10:42 ?3843次閱讀

    寄存器尋址的實現方式

    在計算機體系結構中,寄存器尋址是一種常見的尋址方式,它允許程序直接訪問CPU內部的寄存器寄存器尋址可以提高程序的執行效率,因為它避免了對內存的訪問。 寄存器尋址的基本概念
    的頭像 發表于 07-12 10:36 ?1304次閱讀

    寄存器有哪幾種?可以實現什么功能?

    寄存器是計算機中用于存儲數據和指令的高速存儲設備,是計算機硬件的重要組成部分。寄存器的種類很多,不同的寄存器具有不同的功能。 通用寄存器(General-Purpose Registe
    的頭像 發表于 07-12 10:32 ?1979次閱讀

    寄存器分為基本寄存器和什么兩種

    寄存器是計算機中用于存儲數據的高速存儲單元,它們是CPU內部的重要組成部分。寄存器可以分為基本寄存器和擴展寄存器兩種類型。 一、基本寄存器
    的頭像 發表于 07-12 10:31 ?2013次閱讀

    移位寄存器中使用的儲存單元是什么

    移位寄存器是一種常見的數字電路組件,用于存儲和傳輸數字信號。在移位寄存器中,存儲單元是其核心組成部分,負責存儲數字信號的每一位。本文將介紹移位寄存器中使用的存儲單元。 移位寄存器概述
    的頭像 發表于 07-12 10:21 ?741次閱讀

    移位寄存器右移是怎么移位的

    移位寄存器是一種在數字電路和計算機科學中廣泛使用的存儲設備,它可以用來存儲和傳輸數據。在移位寄存器中,數據可以通過移位操作來實現數據的傳輸和處理。移位寄存器的移位操作有兩種基本形式:左移和右移。本文
    的頭像 發表于 07-12 10:14 ?2587次閱讀

    MAX31856單次轉換模式下,怎么設置開路檢測?是重置寄存器CR0的第四第五位嗎?

    MAX31856單次轉換模式下,怎么設置開路檢測,是重置寄存器CR0的第四第五位嗎?因為我初始化時已經將CR0第四第五為設置為了01,就是使能開路檢測。
    發表于 05-24 07:03
    主站蜘蛛池模板: 亚洲天堂视频一区 | 一级毛片黄色 | 国模在线观看 | 天天舔天天射 | 免费级毛片 | 国产牛仔裤系列在线观看 | 久久精品看片 | 久久久久综合 | 久久大香线蕉综合爱 | 三级黄色短视频 | 欧美爱爱帝国综合社区 | 国产情侣自拍小视频 | 日本视频网站在线www色 | 91久久精品青青草原伊人 | 涩涩爱影院 | 69午夜视频| 欧美com| 色噜噜狠狠狠狠色综合久 | 女人张开双腿让男人桶爽免 | 一二三区电影 | 广东毛片 | 日干夜干天天干 | 短篇禁伦小说 | 黄色三级视频在线观看 | 欧美成人精品一级高清片 | 六月婷婷导航福利在线 | 天天拍天天色 | 四虎影院在线视频 | 色噜噜噜噜噜在线观看网站 | a爱视频 | 99综合在线| 四虎三级 | 日日爱夜夜爱 | 色视频免费国产观看 | 黄频免费 | 久久刺激 | 午夜免费片 | 男男扒开后菊惩罚 | 亚洲成a人不卡在线观看 | 劳拉淫欲护士bd字幕 | 特黄aaaaaa久久片 |