則相應的GPIO口如何配置
① 如何實現gpio口模式的配置
一、 STM32的輸入輸出管腳有下面8種(4輸入 2輸出 2復用輸出)可能的配置:
① 浮空輸入_IN_FLOATING
② 帶上拉輸入_IPU
③ 帶下拉輸入_IPD
④ 模擬輸入_AIN
⑤ 開漏輸出_OUT_OD
⑥ 推挽輸出_OUT_PP
⑦ 復用功能的推挽輸出_AF_PP
⑧ 復用功能的開漏輸出_AF_OD
1.1 I/O口的輸出模式下,有3種輸出速度可選(2MHz、10MHz和50MHz),這個速度是指I/O口驅動電路的響應速度而不是輸出信號的速度,輸出信號的速度與程序有關(晶元內部在I/O口 的輸出部分安排了多個響應速度不同的輸出驅動電路,用戶可以根據自己的需要選擇合適的驅動電路)。通過選擇速度來選擇不同的輸出驅動模塊,達到最佳的雜訊控制和降低功耗的目的。高頻的驅動電路,雜訊也高,當不需要高的輸出頻率時,請選用低頻驅動電路,這樣非常有利於提高系統的EMI性能。當然如果要輸出較高頻率的信號,但卻選用了較低頻率的驅動模塊,很可能會得到失真的輸出信號。
輸出速度又稱輸出驅動電路的響應速度,可理解為:輸出驅動電路的帶寬,即一個驅動電路可以不失真地通過信號的最大頻率。
如果一個信號的頻率超過了驅動電路的響應速度,就有可能信號失真。如果信號頻率為10MHz,而你配置了2MHz的帶寬,則10MHz的方波很可能就變成了正弦波。就好比是公路的設計時速,汽車速度低於設計時速時,可以平穩地運行,如果超過設計時速就會顛簸,甚至翻車。
關鍵是: GPIO的引腳速度跟應用相匹配,速度配置越高,雜訊越大,功耗越大。
帶寬速度高的驅動器耗電大、雜訊也大,帶寬低的驅動器耗電小、雜訊也小。使用合適的驅動器可以降低功耗和雜訊。
GPIO的引腳速度跟應用匹配(推薦10倍以上)。比如:
1.1.1 對於串口,假如最大波特率只需115.2k,那麼用2M的GPIO的引腳速度就夠了,既省電也雜訊小。
1.1.2 對於I2C介面,假如使用400k波特率,若想把餘量留大些,那麼用2M的GPIO的引腳速度或許不夠,這時可以選用10M的GPIO引腳速度。
1.1.3 對於SPI介面,假如使用18M或9M波特率,用10M的GPIO的引腳速度顯然不夠了,需要選用50M的GPIO的引腳速度。
1.2 GPIO口設為輸入時,輸出驅動電路與埠是斷開,所以輸出速度配置無意義。
1.3 在復位期間和剛復位後,復用功能未開啟,I/O埠被配置成浮空輸入模式。
1.4 所有埠都有外部中斷能力。為了使用外部中斷線,埠必須配置成輸入模式。
1.5 GPIO口的配置具有上鎖功能,當配置好GPIO口後,可以通過程序鎖住配置組合,直到下次晶元復位才能解鎖。
二、GPIO的翻轉速度指:輸入/輸出寄存器的0 ,1 值反映到外部引腳(APB2上)高低電平的速度.手冊上指出GPIO最大翻轉速度可達18MHz。通過簡單的程序測試,用示波器觀察到的翻轉時間是綜合的時間,包括取指令的時間、指令執行的時間、指令執行後信號傳遞到寄存器的時間(這其中可能經過很多環節,比如AHB、APB、匯流排仲裁等),最後才是信號從寄存器傳輸到引腳所經歷的時間。如有上拉電阻,其阻值越大,RC延時越大,即邏輯電平轉換的速度越慢,功耗越大。
三、在STM32中如何配置片內外設使用的IO埠
首先,一個外設經過 ①配置輸入的時鍾和 ②初始化後即被激活(開啟);③如果使用該外設的輸入輸出管腳,則需要配置相應的GPIO埠(否則該外設對應的輸入輸出管腳可以做普通GPIO管腳使用);④再對外設進行詳細配置。
對應到外設的輸入輸出功能有下述三種情況:
① 外設對應的管腳為輸出:需要根據外圍電路的配置選擇對應的管腳為復用功能的推挽輸出或復用功能的開漏輸出。
② 外設對應的管腳為輸入:則根據外圍電路的配置可以選擇浮空輸入、帶上拉輸入或帶下拉輸入。
③ ADC對應的管腳:配置管腳為模擬輸入。
如果把埠配置成復用輸出功能,則引腳和輸出寄存器斷開,並和片上外設的輸出信號連接。將管腳配置成復用輸出功能後,如果外設沒有被激活,那麼它的輸出將不確定。
四、 通用IO埠(GPIO)初始化
4.1 GPIO初始化
41.1 RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | B | C, ENABLE):使能APB2匯流排外設時鍾;
41.2 RCC_ APB2PeriphResetCmd (RCC_APB2Periph_GPIOA | B | C, DISABLE):釋放GPIO復位。
4.2 置各個PIN埠(模擬輸入_AIN、輸入浮空_IN_FLOATING、輸入上拉_IPU、輸入下拉_IPD、開漏輸出_OUT_OD、推挽式輸出_OUT_PP、推挽式復用輸出_AF_PP、開漏復用輸出_AF_OD)。
4.3GPIO初始化完成。
五、 的GPIO操作函數
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//讀GPIO某一位的輸入
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);//讀GPIO的輸入
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//讀GPIO某一位的輸出
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);//讀GPIO的輸出
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//將GPIO的某個位置位
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);//將GPIO的某個位復位
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);//寫GPIO的某個位
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);//寫GPIO
六、管腳的復用功能 重映射
1、復用功能:內置外設是與I/O口共用引出管腳(不同的功能對應同一管腳)
STM32 所有內置外設的外部引腳都是與標准GPIO引腳復用的,如果有多個復用功能模塊對應同一個引腳,只能使能其中之一,其它模塊保持非使能狀態。
2、重映射功能:復用功能的引出腳可以通過重映射,從不同的I/O管腳引出,即復用功 能的引出腳位是可通過程序改變到其他的引腳上!
直接好處:PCB電路板的設計人員可以在需要的情況下,不必把某些信號在板上繞一大圈完成聯接,方便了PCB的設計同時潛在地減少了信號的交叉干擾。
如:USART1: 0: 沒有重映像(TX/PA9,RX/PA10); 1: 重映像(TX/PB6,RX/PB7)。
(參考AFIO_MAPR寄存器介紹)[0,1為一寄存器的bit值]
【注】 下述復用功能的引出腳具有重映射功能:
- 晶體振盪器的引腳在不接晶體時,可以作為普通I/O口
- CAN模塊; - JTAG調試介面;- 大部分定時器的引出介面; - 大部分USART引出介面
- I2C1的引出介面; - SPI1的引出介面;
舉例:對於STM32F103VBT6,47引腳為PB10,它的復用功能是I2C2_SCL和 USART3_TX,表示在上電之後它的默認功能為PB10,而I2C2的SCL和USART3的TX為它的復用功能;另外在TIM2的引腳重映射後,TIM2_CH3也成為這個引腳的復用功能。
(1)要使用STM32F103VBT6的47、48腳的USART3功能,則需要配置47腳為復用推挽輸出或復用開漏輸出,配置48腳為某種輸入模式,同時使能USART3並保持I2C2的非使能狀態。
(2)使用STM32F103VBT6的47腳作為TIM2_CH3,則需要對TIM2進行重映射,然後再按復用功能的方式配置對應引腳。
② stm32如果一個gpio口既需要輸出也需要輸入,應該怎麼配置
STM32F407ZG集成8個16引腳GPIO埠,支持168MHz最高時鍾頻率,可承受5V電壓。每個埠擁有16個GPIO引腳,功能獨立配置,具備雙向保護二極體與可選上拉或下拉電阻。輸入/輸出數據可單獨讀取或輸出。埠配置模式包括輸入浮點、輸出、開漏/推挽及外部中斷/事件。在復位時,I/O埠默認為輸入浮點模式,提供微弱內部電阻。輸出模式下,可選開漏或推挽類型,速度取決於VDD值。每個埠支持16條外部中斷/事件線,具有23個邊緣檢測器用於生成中斷請求。
為實現4個按鍵控制2個LED燈的實驗,選擇正點原子原理圖中的4個按鍵與2個LED燈。按鍵配置為輸入模式,使用上拉或下拉電阻保持斷開狀態,LED燈配置為輸出模式,用於顯示狀態。通過STM32CubeMX配置GPIO埠,將按鍵與LED燈與具體引腳關聯。選擇外部晶振作為時鍾源,配置JTAG調試介面,設置時鍾頻率至168MHz,完成系統配置。
使用STM32CubeIDE集成開發環境進行代碼編寫、編譯與調試。該環境整合了STM32CubeMX配置工具和Eclipse IDE,提供一站式解決方案。實現按鍵觸發LED燈的輪詢Polling方式代碼,檢測按鍵按下狀態,點亮相應LED燈,反之關閉,完成功能驗證。
③ 請問如何根據硬體或是數據手冊配置GPIO的輸入輸出模式
用的最多的推挽輸出 模擬輸入,用庫的方式直接寫就完了,用寄存器麻煩一點。現在已經很多資料了,庫的方式很多,寄存器的正點原子的不錯。希望幫到你。
④ 求一個stm32的GPIO配置函數,就是使用這個函數可以配置任何一個GPIO埠(如下)
voidconfig_gpio(u32PORTx,u32MODE,u32PINxs,PULL_STATstat)//PORTx=0,則代表GPIOA,類推。PINxs從0開始。MODE和stat見如下對照表,需要你自己實現PULL_STAT枚舉型
{
/*IO配置對照,4bit一個引腳(y)
高2位(CNFy):
輸入00=模擬,01=浮空,10=上/下拉,11=保留
輸出[推挽][開漏]
[通用]0001
[復用]1011
低2位(MODEy):
輸入00
輸出01=10MHz,10=2MHz,11=50MHz
*/
GPIO_TypeDef*GPIOs[]={GPIOA,GPIOB,GPIOC,GPIOD,GPIOE,GPIOF,GPIOG};
MODE|=stat<<2;
if(PINxs>15)
{
PINxs-=8;
GPIOs[PORTx]->CRH=MODE<<(PINxs*4);
}
else
{
GPIOs[PORTx]->CRL=MODE<<(PINxs*4);
}
}
至於
voidset_PINxs(u32 PORTx,u32PINxs,PIN_VALval)
{
}
可以用位帶實現,如下:
保存為system.h
#ifndef__SYS_H
#define__SYS_H
#include"stm32f10x.h"
//0,不支持ucos
//1,支持ucos
#defineSYSTEM_SUPPORT_UCOS 0 //定義系統文件夾是否支持UCOS
//位帶操作,實現51類似的GPIO控制功能
//具體實現思想,參考<<CM3權威指南>>第五章(87頁~92頁).
//IO口操作宏定義
#defineBITBAND(addr,bitnum)((addr&0xF0000000)+0x2000000+((addr&0xFFFFF)<<5)+(bitnum<<2))
#defineMEM_ADDR(addr)*((volatileunsignedlong*)(addr))
#defineBIT_ADDR(addr,bitnum)MEM_ADDR(BITBAND(addr,bitnum))
//IO口地址映射
#defineGPIOA_ODR_Addr(GPIOA_BASE+12)//0x4001080C
#defineGPIOB_ODR_Addr(GPIOB_BASE+12)//0x40010C0C
#defineGPIOC_ODR_Addr(GPIOC_BASE+12)//0x4001100C
#defineGPIOD_ODR_Addr(GPIOD_BASE+12)//0x4001140C
#defineGPIOE_ODR_Addr(GPIOE_BASE+12)//0x4001180C
#defineGPIOF_ODR_Addr(GPIOF_BASE+12)//0x40011A0C
#defineGPIOG_ODR_Addr(GPIOG_BASE+12)//0x40011E0C
#defineGPIOA_IDR_Addr(GPIOA_BASE+8)//0x40010808
#defineGPIOB_IDR_Addr(GPIOB_BASE+8)//0x40010C08
#defineGPIOC_IDR_Addr(GPIOC_BASE+8)//0x40011008
#defineGPIOD_IDR_Addr(GPIOD_BASE+8)//0x40011408
#defineGPIOE_IDR_Addr(GPIOE_BASE+8)//0x40011808
#defineGPIOF_IDR_Addr(GPIOF_BASE+8)//0x40011A08
#defineGPIOG_IDR_Addr(GPIOG_BASE+8)//0x40011E08
//IO口操作,只對單一的IO口!
//確保n的值小於16!
#definePAout(n)BIT_ADDR(GPIOA_ODR_Addr,n)//輸出
#definePAin(n)BIT_ADDR(GPIOA_IDR_Addr,n)//輸入
#definePBout(n)BIT_ADDR(GPIOB_ODR_Addr,n)//輸出
#definePBin(n)BIT_ADDR(GPIOB_IDR_Addr,n)//輸入
#definePCout(n)BIT_ADDR(GPIOC_ODR_Addr,n)//輸出
#definePCin(n)BIT_ADDR(GPIOC_IDR_Addr,n)//輸入
#definePDout(n)BIT_ADDR(GPIOD_ODR_Addr,n)//輸出
#definePDin(n)BIT_ADDR(GPIOD_IDR_Addr,n)//輸入
#definePEout(n)BIT_ADDR(GPIOE_ODR_Addr,n)//輸出
#definePEin(n)BIT_ADDR(GPIOE_IDR_Addr,n)//輸入
#definePFout(n)BIT_ADDR(GPIOF_ODR_Addr,n)//輸出
#definePFin(n)BIT_ADDR(GPIOF_IDR_Addr,n)//輸入
#definePGout(n)BIT_ADDR(GPIOG_ODR_Addr,n)//輸出
#definePGin(n)BIT_ADDR(GPIOG_IDR_Addr,n)//輸入//voidNVIC_Configuration(void);#endif
使用時直接:
PAout(0)=0;
//或
a=PAin(0);
當然,你還可以使用STM32的庫函數
⑤ 如何實現一次對多GPIO進行配置
以LED燈為例子:
void led(void)
{
/*定義一個GPIO_InitTypeDef類型的結構體*/
GPIO_InitTypeDef GPIO_InitStructure;
/*開啟GPIOB的外設時鍾*/
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOA, ENABLE);
/*選擇要控制的GPIOB引腳*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_8;
/*設置引腳模式為通用推挽輸出*/
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
/*設置引腳速率為50MHz */
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
/*調用庫函數,初始化GPIOB*/
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_Init(GPIOA, &GPIO_InitStructure);
/* 讓選擇引腳輸出高電平*/
GPIO_SetBits(GPIOB, GPIO_Pin_0 | GPIO_Pin_1);
}
其中GPIO有多個模式,需要按照不同功能和使用來配置。這里LED燈需要輸出,所以我設置為通用推挽。