【STM32】STM32埠複用和重對映(AFIO輔助功能時鐘)
STM32F1xx官方資料:
《STM32中文參考手冊V10》-第8章通用和複用功能IO(GPIO和AFIO)
埠複用功能
埠複用的定義
STM32有許多的內建外設(如串列埠、ADC、DCA等等),這些外設的外部引腳都是和GPIO複用的。也就是說,一個GPIO如果可以複用為內建外設的功能引腳,那麼當這個GPIO作為內建外設使用的時候,就叫複用。詳細的可以參考《STM32F103ZET6資料手冊》p30的內容,表格的倒數第二欄就表示埠複用功能。
比如說,STM32的串列埠1的引腳對應的I/O位PA9、PA10。而PA9、PA10預設的功能都是GPIO,所以說當PA9、PA10引腳作為串列埠1使用的時候就是埠複用。
那麼,什麼時候埠是預設功能,什麼時候埠是複用功能呢?
STM32時鐘系統的配置除了初始化的時候在system_stm32f10x.c中的SystemInit函式中外,其他的配置主要在stm32f10x_rcc.c檔案中, 所以GPIO等等外設的時鐘使能函式都是在此檔案中。同時我們通過函式名可以得到規律:GPIOA-GPIOC是掛載在APB2下面,TIM2-TIM4是掛載在APB1下面,DMA是掛載在AHB下面。所以呼叫函式的名稱是需要根據這個來確定的。
埠複用初始化過程
接下來看一下埠複用初始化過程的步驟,拿串列埠1為例:
1、GPIO埠時鐘使能。要使用到埠複用,首先是要使能埠的時鐘了;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
2、複用的外設時鐘使能。比如要將PA9、PA10引腳複用成串列埠,必須也要使能串列埠時鐘;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
3、埠模式配置。在I/O複用位內建外設功能引腳的時候,必須設定GPIO埠的模式。至於在複用功能下,GPIO的模式怎麼設定,可以檢視手冊《STM32中文參考手冊》p110的內容。這裡拿USART1為例,進行配置,要配置全雙工的串列埠1,TX引腳需要推輓複用輸出,RX引腳需要浮空輸入或者上拉輸入;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9//複用推輓輸出 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //複用推輓輸出 GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10 PA.10 浮空輸入 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空輸入 GPIO_Init(GPIOA, &GPIO_InitStructure);
總而言之,使用複用功能的時候至少要使能2時鐘:GPIO時鐘使能、複用的外設時鐘使能。同時還要初始化GPIO以及複用外設功能(埠模式配置)。
埠重對映
埠重對映的定義
為了使不同的器件封裝的外設I/O功能數量達到最優,可以把一些複用功能重新對映到其他的引腳上。STM32中有許多的內建外設的輸入、輸出引腳都具有重對映(Remap)的功能。
我們知道,每個內建外設都有若干個輸入、輸出引腳,一般這些引腳的輸出埠都是固定不變的,為了更好地安排引腳的走向和功能,在STM32中引入了外設引腳重對映的概念,即一個外設的引腳除了具有預設的埠之外,還可以通過設定重對映暫存器的方式把這個外設的引腳對映到其他的埠。
簡單講,就是把引腳的外設功能對映到其他的引腳上,但不是可以隨便對映的,具體的對應關係參考《STM32F103ZET6資料手冊》p30的內容,表格的最後一欄就表示埠重對映功能。
這裡同樣用串列埠1為例來說明。
可以看出,我們可以將串列埠1重對映到PB6、PB7引腳上。
埠重對映初始化過程
接下來看一下埠重對映初始化過程的步驟,拿串列埠1為例,除了之前使能複用功能的2個時鐘之外,還需要使能AFIO功能時鐘,然後呼叫重對映函式:
1、GPIO埠時鐘使能。要使用到埠複用,首先是要使能埠的時鐘了;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
2、複用的外設時鐘使能。比如要將PB6、PB7引腳複用成串列埠,必須也要使能串列埠時鐘;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
3、使能AFIO時鐘。重對映必須使能AFIO時鐘;RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
4、開啟重對映;
GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
這樣,就將串列埠1的TX和RX引腳對映到PB6、PB7引腳上面了。至於哪些功能可以重對映,除了檢視中文參考手冊之外,還可以從GPIO_PinRemapConfig函式入手檢視第一個入口引數的取值範圍的值。stm32f10x_gpio.h中定義了一些巨集定義的識別符號:
#define GPIO_Remap_SPI1 ((uint32_t)0x00000001) /*!< SPI1 Alternate Function mapping */
#define GPIO_Remap_I2C1 ((uint32_t)0x00000002) /*!< I2C1 Alternate Function mapping */
#define GPIO_Remap_USART1 ((uint32_t)0x00000004) /*!< USART1 Alternate Function mapping */
#define GPIO_Remap_USART2 ((uint32_t)0x00000008) /*!< USART2 Alternate Function mapping */
#define GPIO_PartialRemap_USART3 ((uint32_t)0x00140010) /*!< USART3 Partial Alternate Function mapping */
#define GPIO_FullRemap_USART3 ((uint32_t)0x00140030) /*!< USART3 Full Alternate Function mapping */
#define GPIO_PartialRemap_TIM1 ((uint32_t)0x00160040) /*!< TIM1 Partial Alternate Function mapping */
#define GPIO_FullRemap_TIM1 ((uint32_t)0x001600C0) /*!< TIM1 Full Alternate Function mapping */
#define GPIO_PartialRemap1_TIM2 ((uint32_t)0x00180100) /*!< TIM2 Partial1 Alternate Function mapping */
#define GPIO_PartialRemap2_TIM2 ((uint32_t)0x00180200) /*!< TIM2 Partial2 Alternate Function mapping */
#define GPIO_FullRemap_TIM2 ((uint32_t)0x00180300) /*!< TIM2 Full Alternate Function mapping */
#define GPIO_PartialRemap_TIM3 ((uint32_t)0x001A0800) /*!< TIM3 Partial Alternate Function mapping */
#define GPIO_FullRemap_TIM3 ((uint32_t)0x001A0C00) /*!< TIM3 Full Alternate Function mapping */
可以看出,USART1只有一種重對映,而USART3存在部分重對映和完全重對映。所謂部分重對映就是部分引腳和預設的是一樣的,完全重對映就是所有引腳都對映到了新的引腳。可以檢視《STM32中文參考手冊》p119的內容檢視部分重對映和完全重對映的內容。而在之前最後開啟重對映的函式中,根據第一個引數,來確定是部分重對映還是全部重對映。
AFIO輔助功能時鐘
之前在埠重對映的時候,講到要使能AFIO輔助功能時鐘。那麼什麼時候需要開啟(使能)呢?
對暫存器AFIO_MAPR、AFIO_EXTICRx和AFIO_EVCR進行讀寫操作前,應當首先開啟AFIO時鐘。
- AFIO_MAPR:配置複用功能重對映
- AFIO_EXTICRx:配置外部中斷線對映
- AFIO_EVCR: 配置事件輸出