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);
}
}
上一篇:【STM32】串口通信基本原理(超基礎(chǔ)、詳細版)
下一篇:【STM32】GPIO工作原理(八種工作方式超詳細分析)
推薦閱讀
史海拾趣
在集成電路的封裝領(lǐng)域,ALD同樣展現(xiàn)出了強大的創(chuàng)新能力。公司不僅提供了塑封、PDIP、小型裝(SOIC)等常見的封裝形式,還開發(fā)出了密封陶瓷封裝(CDIP)等高性能封裝技術(shù)。這些封裝技術(shù)不僅提高了集成電路的可靠性和穩(wěn)定性,還降低了生產(chǎn)成本,為客戶提供了更具競爭力的產(chǎn)品。
在集成電路的封裝領(lǐng)域,ALD同樣展現(xiàn)出了強大的創(chuàng)新能力。公司不僅提供了塑封、PDIP、小型裝(SOIC)等常見的封裝形式,還開發(fā)出了密封陶瓷封裝(CDIP)等高性能封裝技術(shù)。這些封裝技術(shù)不僅提高了集成電路的可靠性和穩(wěn)定性,還降低了生產(chǎn)成本,為客戶提供了更具競爭力的產(chǎn)品。
隨著市場需求的不斷增長,ALD不斷拓展其產(chǎn)品線。除了最初的CMOS線性集成電路外,公司還研發(fā)出了軌到軌運算放大器、雙斜率A/D前端轉(zhuǎn)換器、電壓比較器等一系列產(chǎn)品。這些產(chǎn)品不僅滿足了不同行業(yè)的需求,還進一步提升了ALD在電子行業(yè)的市場地位。同時,公司還針對特定應(yīng)用,如醫(yī)療儀器和汽車領(lǐng)域,推出了定制化的解決方案,贏得了客戶的廣泛贊譽。
隨著產(chǎn)品線的不斷豐富和技術(shù)實力的提升,Bomar Interconnect公司開始積極拓展國內(nèi)外市場。公司通過參加各類行業(yè)展會、舉辦技術(shù)研討會等方式,加強與客戶的溝通與合作。同時,公司還注重品牌建設(shè),通過提升產(chǎn)品質(zhì)量、優(yōu)化客戶服務(wù)等舉措,樹立了良好的企業(yè)形象。這些努力不僅幫助公司贏得了更多客戶的信任和支持,也為公司的長遠發(fā)展奠定了堅實基礎(chǔ)。
90年代初期,隨著全球化進程的加速,Hokuriku Electric開始將目光投向國際市場。公司首先在歐洲和北美設(shè)立了銷售分支機構(gòu),隨后又逐步拓展至亞洲其他地區(qū)。通過參加國際展會、建立合作伙伴關(guān)系等多種方式,Hokuriku Electric成功將其優(yōu)質(zhì)產(chǎn)品推向全球市場。這一過程中,公司不僅積累了豐富的國際銷售經(jīng)驗,還提升了品牌知名度和影響力,為后續(xù)的全球化發(fā)展奠定了堅實基礎(chǔ)。
手機發(fā)射功率 手機發(fā)射功率的兩個方面 手機發(fā)射功率在PHS、GSM、cdma2000 1x、wcdma等協(xié)議中,被設(shè)計得越來越復(fù)雜,它的重要性已不言而喻,哪手機發(fā)射功率是大些好哪,還是小些好哪?事實上單純的說大些好或者小些好,都實在不是一個明智的 ...… 查看全部問答∨ |
|
我正在學(xué)習(xí)ATmega16 對AVR的單片機的睡眠模式有點迷惑 不能很好的使用啊 又沒有找到好的詳細的資料 希望高手幫幫忙 把睡眠模式和各種睡眠模式喚醒的條件講清楚啊… 查看全部問答∨ |
|
誰知道如何在提高2440LCD,VCLK頻率,的同時能不降低它的幅值! 發(fā)現(xiàn)2440,LCD控制器的VCLK在頻率提高到25MHZ時候,高低電平會變成0.9,2.4v。這樣的電平超過我的LVDS轉(zhuǎn)接芯片,對TTL信號的電平閾值要求,0.8~2.2v。低電平高于0.8v了。 請問有辦法,在VCLK提高的時候不降低幅值嗎?… 查看全部問答∨ |
|
目前采用修改注冊表方法修改IP,dns,修改后用IOCTRL重啟網(wǎng)卡, 但是在沒有連接情況下重啟網(wǎng)卡,設(shè)備會出現(xiàn)異常。所以想采用 WINDOWS的api去設(shè)置,MSDN上有IP,gateway的API說明,但是我 沒找到DNS用哪個API設(shè)置。 有XDJM做過相關(guān)的東西嗎,DNS用 ...… 查看全部問答∨ |
|
各位大俠,小弟剛?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ā)板 精華推薦
- 人形機器人馬拉松背后的思考,兆易創(chuàng)新如何賦能機器人產(chǎn)業(yè)
- 一種基于STM32的智能柜控制器設(shè)計
- 小型傾轉(zhuǎn)旋翼機的無刷直流電機驅(qū)動器設(shè)計
- 超高速攝影機電控系統(tǒng)設(shè)計
- 基于GPS自動授時的無線智能控制器的設(shè)計
- 基于PTR2000的無線氣象信息采集系統(tǒng)設(shè)計
- Microchip推出MEC175xB系列器件,為嵌入式控制器引入硬件 抗量子攻擊能力
- 無人飛行器機載穩(wěn)定云臺控制系統(tǒng)的設(shè)計
- 匠芯創(chuàng)推出面向具身智能高性能實時處理器M7000
- 自動駕駛卡車公司Aurora重新引入駕駛員
- 全固態(tài)電池新標準出臺,明確定義解決行業(yè)界定義及測試難題
- 長城死磕增程!下代平臺用6C充電,插混純電續(xù)航竟然破400公里!
- 寶馬全固態(tài)電池電動汽車上路測試
- 基于數(shù)采系統(tǒng)的車載A2B信號測試解決方案
- 從夢想到落地:固態(tài)激光雷達的十年發(fā)展史
- AI 座艙芯片,走入全民時代
- 2025年1-3月ADAS供應(yīng)商裝機量排行榜:自主廠商引領(lǐng)技術(shù)融合新趨勢
- 又一廠商官宣大動作,汽車零部件企業(yè)緣何涌向機器人領(lǐng)域?
- 總規(guī)模50億!蘇州吳中區(qū)成立機器人專項基金