娇小w搡bbbb搡bbb,《第一次の人妻》,中国成熟妇女毛茸茸,边啃奶头边躁狠狠躁视频免费观看

歷史上的今天

今天是:2025年03月13日(星期四)

正在發(fā)生

2019年03月13日 | 【STM32】GPIO的相關(guān)配置寄存器、庫函數(shù)、位操作

發(fā)布者:柔情細語 來源: eefocus關(guān)鍵字:STM32  GPIO  配置寄存器  庫函數(shù)  位操作 手機看文章 掃描二維碼
隨時隨地手機看文章

STM32F1xx官方資料:


《STM32中文參考手冊V10》-第8章通用和復(fù)用功能IO(GPIO和AFIO)

Cortex-M3權(quán)威指南(中文)》第5章 位帶操作


硬件連接


假設(shè)跑馬燈實驗的硬件連接如上圖所示,LED0連接PB5,LED1連接PE5。由于在LED的另一端是VCC3.3,所以當(dāng)PB5或PE5為低電平的時候,LED燈會亮。此時GPIO應(yīng)采取推挽輸出的模式。


GPIO的相關(guān)配置寄存器

STM32的每組GPIO口包括7個寄存器。也就是說,每個寄存器可以控制一組GPIO的16個GPIO口。這7個寄存器分別為:


GPIOx_CRL:端口配置低寄存器(32位)

GPIOx_CRH:端口配置高寄存器(32位)

GPIOx_IDR:端口輸入寄存器(32位)

GPIOx_ODR:端口輸出寄存器(32位)

GPIOx_BSRR:端口位設(shè)置/清除寄存器(32位)

GPIOx_BRR:端口位清除寄存器(16位)

GPIOx_LCKR:端口配置鎖存寄存器(32位)

端口配置低寄存器(GPIOx_CRL)



由于每個GPIO口需要4位來進行配置輸入輸出模式(2位配置MODE,2位配置CNF),這樣的話每組16個GPIO口則需要64位,這也就表明需要兩個32位寄存器。于是GPIOx_CRL用于配置GPIO0-GPIO7的輸入輸出模式。同理GPIOx_CRH則用于配置GPIO8-GPIO15的輸入輸出模式。


同時對于上面的這個表可以總結(jié)出端口位配置的信息:



需要注意的是,當(dāng)MODE選擇00,CNF為選擇10時,代表著上拉/下拉輸入模式。到底是上拉還是下拉呢?此時需要PxODR(端口輸出寄存器)來確定,0為下拉輸入,1為上拉輸入。


端口輸入寄存器(GPIOx_IDR)



IDR寄存器低16位,每個位控制該組GPIO口的一個IO口,對應(yīng)的是該IO口的輸入電平。在輸入模式下,可以讀取I/O端口的電平值;在輸出模式下,也可以讀取I/O端口的電平值(在開漏輸出時,讀取到的I/O端口的電平值,不一定就是輸出的電平值)。


端口輸出寄存器(GPIOx_ODR)



ODR寄存器的低16位,每個位控制該組GPIO口的一個IO口,對應(yīng)的是該IO口的輸出電平。在輸出模式下,可以通過寫寄存器的值,來達到某個IO口的電平輸出;在輸入模式下,還可以通過寫值,來確定是上拉還是下拉輸入模式。


端口位設(shè)置/清除寄存器(GPIOx_BSRR)



在GPIO的開漏輸出模式或者推挽輸出模式下,都可以直接給ODR寄存器賦值來進行某個IO口的電平輸出;同時,也可以通過對BSRR進行賦值來達到對ODR寄存器的控制來進行對IO口的電平輸出。其實,BSRR寄存器的底層也是對ODR寄存器的控制。


BSRR寄存器的低16位可以只對ODR賦1,高16位可以只對ODR賦0。這樣的好處是,只可以對ODR的某些特定位產(chǎn)生影響,而不對其他的位產(chǎn)生影響。而且可以一次性對ODR的許多位同時進行控制。


端口位清除寄存器(GPIOx_BRR)



BRR寄存器的功能其實和BSRR寄存器的高16位的功能是一樣的,通常情況下,使用BSRR寄存器的低16位來賦1,使用BRR寄存器來賦0。


 


GPIO的寄存器版本

 


使能IO口時鐘。配置寄存器RCC_APB2ENR;

初始化IO口模式。配置寄存器GPIOx_CRH/CRL;

操作IO口,輸出高低電平。配置寄存器GPIOX_ODR或者BSRR/BRR。

具體的程序內(nèi)容:


void LED_Init(void){

RCC->APB2ENR|=1<<3;

RCC->APB2ENR|=1<<6;


GPIOB->CRL&=0xFF0FFFFF;

GPIOB->CRL|=0x00300000;


GPIOB->ODR|=1<<5;


GPIOE->CRL&=0xFF0FFFFF;

GPIOE->CRL|=0x00300000;


GPIOE->ODR|=1<<5;

}

 int main(void)

 {

LED_Init();

delay_init();

while(1){

GPIOB->ODR|=1<<5;

GPIOE->ODR|=1<<5;


delay_ms(500);


GPIOB->ODR&=~(1<<5);

GPIOE->ODR&=~(1<<5);


delay_ms(500);


}

 }

 


GPIO的庫函數(shù)版本

需引用的文件:stm32f10x_gpio.h、stm32f10x_rcc.h、misc.h


需定義的文件:led.h


GPIO庫函數(shù)介紹

1個初始化函數(shù):

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);

作用:初始化一個或者多個IO口(同一組)的工作方式和速度。該函數(shù)主要是操作GPIO_CRL(CRH)寄存器,在上拉或者下拉的時候有設(shè)置BSRR或者BRR寄存器 。


注意:外設(shè)(包括GPIO)在使用之前,幾乎都要先使能對應(yīng)的時鐘。


2個讀取輸入電平函數(shù):

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);

作用:讀取某個(某組)GPIO的輸入電平。實際操作的是GPIOx_IDR寄存器。


2個讀取輸出電平函數(shù):

uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);

作用:讀取某個(某組)GPIO的輸出電平。實際操作的是GPIO_ODR寄存器。


4個設(shè)置輸出電平函數(shù):

void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);

void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);

void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);

作用:設(shè)置某個IO口輸出為高電平(低電平)。實際操作BSRR寄存器。后兩個函數(shù)的作用類似。


GPIO庫函數(shù)版本的跑馬燈

使能IO口時鐘。調(diào)用函數(shù)RCC_APB2PeriphColckCmd();

初始化IO口模式。調(diào)用函數(shù)GPIO_Init();

操作IO口,輸出高低電平。調(diào)用函數(shù)GPIO_SetBits();GPIO_ResetBits()。

具體的程序內(nèi)容:


void LED_Init(void){

GPIO_InitTypeDef GPIO_InitStructure;


RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);

RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOE,ENABLE);


GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_Init(GPIOB,&GPIO_InitStructure);


GPIO_SetBits(GPIOB,GPIO_Pin_5);


GPIO_InitStructure.GPIO_Pin=GPIO_Pin_5;

GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;

GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;

GPIO_Init(GPIOE,&GPIO_InitStructure);


GPIO_SetBits(GPIOE,GPIO_Pin_5);


}

 int main(void)

 {

LED_Init();

delay_init();

while(1){

GPIO_SetBits(GPIOB,GPIO_Pin_5);

GPIO_SetBits(GPIOE,GPIO_Pin_5);


delay_ms(500);


GPIO_ResetBits(GPIOB,GPIO_Pin_5);

GPIO_ResetBits(GPIOE,GPIO_Pin_5);


delay_ms(500);


}

 }

 


GPIO的位操作版本

位操作的原理

把每位膨脹為一個32位的地址,當(dāng)訪問這些地址的時候就達到了訪問該位的目的。比如說BSRR寄存器有32個位,那么可以映射到32個地址上,我們?nèi)ピL問(讀-改-寫)這32個地址就達到訪問32個比特的目的。


也就是說,位操作就是可以讀、寫單獨的一個比特位,由于在STM32中沒有像51單片機的sbit來實行位定義,但是它可以通過位帶別名區(qū)來實現(xiàn)。 


哪些區(qū)域支持位操作:


SRAM 區(qū)的最低 1MB 范圍,0x20000000 ‐ 0x200FFFFF(SRAM區(qū)中的最低 1MB);

片內(nèi)外設(shè)區(qū)的最低 1MB范圍,0x40000000 ‐ 0x400FFFFF(片上外設(shè)區(qū)中最低 1MB)。

位帶區(qū):支持位帶操作的地址區(qū)


位帶別名:對別名地址的訪問最終作用到位帶區(qū)的訪問上(注意:這中間有一個地址映射過程)


這兩個1MB的空間可以像普通RAM一樣操作外(修改內(nèi)容時用讀、改、寫),它們還有自己的位帶別名區(qū),位帶別名區(qū)把這1MB的空間的每一位膨脹為一個32位的字。確切的說,這個字就是一個地址,當(dāng)操作這個地址時,就可以達到操作這個位帶區(qū)某個位的目的。 


在位帶區(qū)中,每個比特位都映射到別名地址區(qū)的一個地址,注意,這只是只有LSB有效的字(最低一位有效的字)。當(dāng)一個別名地址被訪問時,會把該地址轉(zhuǎn)換為為位帶操作。


映射方式

對片內(nèi)外設(shè)位帶區(qū)的某個比特位,記它的所在字節(jié)的地址為A,位序號為n(0<=n<=7),則該比特位在別名區(qū)的地址為:


AliasAddr = 0x42000000 + ((A - 0x40000000) * 8 + n) * 4

          = 0x42000000 + (A - 0x40000000) * 32 + n * 4

上式中,4表示一個字4個字節(jié),8表示一個字節(jié)8個比特。


一開始,我對n(0<=n<=7)很不理解,既然n表示位序號,為什么不是0<=n<=31呢?其實是我忽略了“所在字節(jié)”四個字,也就是說在位帶區(qū)中,不是以一個寄存器一個寄存器為分隔單元,而是以一個字節(jié)一個字節(jié)來分隔單元的。 


對于映射的公式,稍微解釋一下:


A - 0x40000000 = 當(dāng)前字節(jié)偏離外設(shè)基地址的偏移字節(jié)數(shù) ;

偏移字節(jié)數(shù) * 8 = 偏移了多少位 ;

因為位帶區(qū)每一位對應(yīng)位帶別名區(qū)的一個地址(32位4字節(jié)),而地址是以字節(jié)計算的,所以位帶別名區(qū)對應(yīng)偏移量最后一個的地址 = 偏移了多少位 * 4 ;

n * 4 = 偏移量后面的n位對應(yīng)位帶別名區(qū)的地址。

同理,對于SRAM位帶區(qū)的某個比特位,記它所在字節(jié)地址為A,位序號為n(0<=n<=7),則該比特位在別名區(qū)的地址為:


AliasAddr = 0x22000000 + ((A - 0x20000000) * 8 + n) * 4 

          = 0x22000000 + (A - 0x20000000) * 32 + n * 4

只是對位帶基地址和位帶別名區(qū)基地址做了改變即可。


為了方便操作,我們可以把這兩個公式合并成一個公式,把“位帶地址 + 位序號”轉(zhuǎn)換成別名地址:


//把位帶區(qū)地址 + 位序號轉(zhuǎn)換成位帶別名去的宏

#define BITBAND(addr, bit_num) ((addr & 0xf0000000) + 0x02000000 + ((addr & 0x00ffffff) << 5) + (bit_num << 2))

位帶操作的優(yōu)越性


位帶操作可以簡化跳轉(zhuǎn)的判斷。比如之前需要跳轉(zhuǎn)到某一位時,必須這樣做:


讀取整個寄存器;

掩蔽不需要的位;

比較并跳轉(zhuǎn)。

現(xiàn)在使用位帶操作只需要:


從位帶別名區(qū)讀取狀態(tài)位;

比較并跳轉(zhuǎn)。

在SYSTEM文件夾的sys.h文件中,對GPIO輸入輸出部分功能實現(xiàn)了位帶操作。具體的實現(xiàn)過程如下面的程序所示:


#define BITBAND(addr, bitnum) ((addr & 0xF0000000)+0x2000000+((addr &0xFFFFF)<<5)+(bitnum<<2)) 

#define MEM_ADDR(addr)  *((volatile unsigned long  *)(addr)) 

#define BIT_ADDR(addr, bitnum)   MEM_ADDR(BITBAND(addr, bitnum)) 

//IO口地址映射

#define GPIOA_ODR_Addr    (GPIOA_BASE+12) //0x4001080C  

#define GPIOA_IDR_Addr    (GPIOA_BASE+8) //0x40010808 

 

//IO口操作,只對單一的IO口!

//確保n的值小于16!

#define PAout(n)   BIT_ADDR(GPIOA_ODR_Addr,n)  //輸出 

#define PAin(n)    BIT_ADDR(GPIOA_IDR_Addr,n)  //輸入 

通過PAout(n)實現(xiàn)對GPIOA_ODR寄存器的第n位賦值的功能,通過PAin(n)實現(xiàn)對GPIOA_IDR寄存器的第n位賦值的功能。按照這種寫法,之前庫函數(shù)版本的主程序可以改寫成:


 int main(void)

 {

LED_Init();

delay_init();

while(1){

PBout(5)=1;

PEout(5)=1;


delay_ms(500);


PBout(5)=0;

PEout(5)=0;


delay_ms(500);


}

 }

關(guān)鍵字:STM32  GPIO  配置寄存器  庫函數(shù)  位操作 引用地址:【STM32】GPIO的相關(guān)配置寄存器、庫函數(shù)、位操作

上一篇:【STM32】串口通信基本原理(超基礎(chǔ)、詳細版)
下一篇:【STM32】GPIO工作原理(八種工作方式超詳細分析)

推薦閱讀

英特爾(Intel)的專用繪圖芯片(GPU)發(fā)展夢雖然在約9年前看似結(jié)束,但英特爾似乎仍未放棄,在2017年11月曾挖角來超微(AMD)前GPU架構(gòu)大將Raja Koduri,顯現(xiàn)打算開發(fā)自有獨立繪圖解決方案企圖,因此英特爾近日在2018年國際固態(tài)電路會議(ISSCC)所發(fā)表采14納米制程GPU原型樣式便獲外界矚目,猜測是否英特爾準備推自有獨立GPU搶進NVIDIA及超微盤據(jù)的市場。?根據(jù)...
對于人工智能能夠為各企業(yè)機構(gòu)完成哪些任務(wù),IT與業(yè)務(wù)領(lǐng)導(dǎo)者們時常感到困惑,并深受多個人工智能錯誤觀念的困擾。全球領(lǐng)先的信息技術(shù)研究和顧問公司Gartner認為,開發(fā)人工智能項目的IT與業(yè)務(wù)領(lǐng)導(dǎo)者必須分清現(xiàn)實與謬見,以制定其未來戰(zhàn)略。Gartner研究副總裁Alexander Linden表示:“隨著IT技術(shù)不斷進入各企業(yè)機構(gòu),業(yè)務(wù)與IT領(lǐng)導(dǎo)者必需充分了解人工智能將...
本系列教程以AVR單片機為對象,介紹單片機的快速開發(fā)方法。參考教材:《單片機技術(shù)及應(yīng)用項目教程》 欒秋平 電子工業(yè)出版社 2019.6 第1版本文介紹應(yīng)用層次化軟件設(shè)計思想實現(xiàn)多路LED閃爍的方法。一、認知層次化軟件設(shè)計思想二、將硬件原理圖直譯成映射層#ifndef HAL_H_#define HAL_H_ //引腳定義//////////////////////////////////////////////////...
有媒體統(tǒng)計,今年《政府工作報告》中“創(chuàng)新”一詞出現(xiàn)了45次,“科技”出現(xiàn)了24次。出現(xiàn)頻率為近三年來最高。 相信大家都能在兩會當(dāng)中感覺到,強化科技自立自強已經(jīng)成為了國家目前階段發(fā)展的重中之重。多種科技創(chuàng)新方向中,《政府工作報告》尤其強調(diào)了“依靠創(chuàng)新推動實體經(jīng)濟高質(zhì)量發(fā)展,培育壯大新動能”“促進科技創(chuàng)新與實體經(jīng)濟深度融合,更好發(fā)揮創(chuàng)...

史海拾趣

問答坊 | AI 解惑

射頻集成電路設(shè)計基礎(chǔ)講義.pdf

射頻集成電路設(shè)計基礎(chǔ)講義…

查看全部問答∨

手機發(fā)射功率

手機發(fā)射功率 手機發(fā)射功率的兩個方面 手機發(fā)射功率在PHS、GSM、cdma2000 1x、wcdma等協(xié)議中,被設(shè)計得越來越復(fù)雜,它的重要性已不言而喻,哪手機發(fā)射功率是大些好哪,還是小些好哪?事實上單純的說大些好或者小些好,都實在不是一個明智的 ...…

查看全部問答∨

AVR單片機睡眠模式

我正在學(xué)習(xí)ATmega16 對AVR的單片機的睡眠模式有點迷惑 不能很好的使用啊 又沒有找到好的詳細的資料 希望高手幫幫忙 把睡眠模式和各種睡眠模式喚醒的條件講清楚啊…

查看全部問答∨

中斷如何調(diào)試?

在MPC8247的單板上調(diào)試BOOTROM,現(xiàn)在感覺不能產(chǎn)生中斷,如何調(diào)試中斷的驅(qū)動?…

查看全部問答∨

誰知道如何在提高2440LCD,VCLK頻率,的同時能不降低它的幅值!

   發(fā)現(xiàn)2440,LCD控制器的VCLK在頻率提高到25MHZ時候,高低電平會變成0.9,2.4v。這樣的電平超過我的LVDS轉(zhuǎn)接芯片,對TTL信號的電平閾值要求,0.8~2.2v。低電平高于0.8v了。     請問有辦法,在VCLK提高的時候不降低幅值嗎?…

查看全部問答∨

wince dns 如何通過api設(shè)置

目前采用修改注冊表方法修改IP,dns,修改后用IOCTRL重啟網(wǎng)卡, 但是在沒有連接情況下重啟網(wǎng)卡,設(shè)備會出現(xiàn)異常。所以想采用 WINDOWS的api去設(shè)置,MSDN上有IP,gateway的API說明,但是我 沒找到DNS用哪個API設(shè)置。 有XDJM做過相關(guān)的東西嗎,DNS用 ...…

查看全部問答∨

大家有玩過camera模塊的沒有

我現(xiàn)在在用三星的ARM11做一個項目,要用到camera模塊,有做過的在這里留下個聯(lián)系方式啊。…

查看全部問答∨

新手的Altera的PLL及工程問題

各位大俠,小弟剛?cè)胧諪PGA,請大家多多指教。我想使能Altera cyclone II的PLL,但根據(jù)官方的文檔,只找到用原理圖方式實現(xiàn),做了測試,也沒問題,現(xiàn)在的問題有兩個:1- Altera cyclone II能否用VHDL方式來實現(xiàn)PLL功能?2- 如何在Quartus里, ...…

查看全部問答∨
小廣播
設(shè)計資源 培訓(xùn) 開發(fā)板 精華推薦

最新單片機文章

 
EEWorld訂閱號

 
EEWorld服務(wù)號

 
汽車開發(fā)圈

 
機器人開發(fā)圈

電子工程世界版權(quán)所有 京ICP證060456號 京ICP備10001474號-1 電信業(yè)務(wù)審批[2006]字第258號函 京公網(wǎng)安備 11010802033920號 Copyright ? 2005-2025 EEWORLD.com.cn, Inc. All rights reserved
主站蜘蛛池模板: 旌德县| 江城| 旌德县| 贺兰县| 贞丰县| 左云县| 温泉县| 盖州市| 皮山县| 陆河县| 宜昌市| 普格县| 斗六市| 正镶白旗| 宜兰市| 资源县| 新和县| 化德县| 巴彦县| 江陵县| 华亭县| 岢岚县| 贞丰县| 嘉禾县| 抚州市| 开江县| 澳门| 常宁市| 富川| 哈密市| 射阳县| 资兴市| 卫辉市| 安龙县| 广宁县| 怀宁县| 游戏| 大宁县| 额尔古纳市| 通化县| 蛟河市|