與GPIO相關的寄存器
STM32F10x處理器公有7個IO端口:A、B、C、D、E、F、G,每個端口上有16個引腳。 每個IO端口都有2個32位的配置寄存器,2個32位的數(shù)據(jù)寄存器(input output),一個32位的置位/復位寄存器,一個16位的復位寄存器,一個32位的鎖定寄存器。 具體有: 端口配置寄存器低位 GPIO_CRL 端口配置寄存器高位 GPIO_CRH 端口輸入數(shù)據(jù)寄存器 GPIO_IDR 端口輸出數(shù)據(jù)寄存器 GPIO_ODR 端口位置位/復位寄存器 GPIO_BSRR 端口位復位寄存器 GPIO_BRR 端口配置鎖定寄存器 GPIO_LCKR 事件控制寄存器 EVCR 復用重映射和調(diào)試I/O配置寄存器 MAPR 外部中斷線路0-15配置寄存器 EXTICR 這些寄存器在系統(tǒng)頭文件stm32f10x.h的定義如下: typedef struct { __IO uint32_t CRL; __IO uint32_t CRH; __IO uint32_t IDR; __IO uint32_t ODR; __IO uint32_t BSRR; __IO uint32_t BRR; __IO uint32_t LCKR; } GPIO_TypeDef; /** * @brief Alternate Function I/O */ typedef struct { __IO uint32_t EVCR; __IO uint32_t MAPR; __IO uint32_t EXTICR[4]; uint32_t RESERVED0; __IO uint32_t MAPR2; } AFIO_TypeDef; /** 端口引腳的設置 l引腳原理圖 l可以設置的狀態(tài) l不同狀態(tài)相關寄存器的設置值 l程序設計時不同狀態(tài)引用的宏定義 函數(shù) 與GPIO相關的函數(shù):在stm32f10x_gpio.h中進行了聲明 1.void GPIO_DeInit(GPIO_TypeDef* GPIOx);//IO缺省值初始化函數(shù) 2.void GPIO_AFIODeInit(void);//初始化復用功能寄存器為初始化值 3.void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct);//使用GPIO_InitStruct中的參數(shù)對IO口進行初始化 4.void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct);把GPIO_InitStruct中的每個參數(shù)按缺省值填入 5.uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);讀取指定端口引腳的輸入 6.uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx);讀取指定端口的輸入 7.uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);讀取指定端口引腳的輸出 8.uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx);讀取指定端口的輸出 9.void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);設置指定端口引腳的位 10.void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);清除指定端口引腳的位 11.void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal);設置或清除指定的數(shù)據(jù)端口為 12.void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);向指定的端口寫入數(shù)據(jù) 13.void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin);鎖定端口引腳的設置寄存器 14.void GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);//選擇端口引腳作為事件輸出 15.void GPIO_EventOutputCmd(FunctionalState NewState);使能 或失能事件輸出 16.void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);改變指定管腳的地址映射 17.void GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource);選擇端口引腳用作外部中斷線路 18.void GPIO_ETH_MediaInterfaceConfig(uint32_t GPIO_ETH_MediaInterface);選擇以太網(wǎng)的接口 外設初始化和設置操作過程 1、在主應用文件中,聲明一個PPP_InitTypeDef結(jié)構(gòu)體類型 ,如PPP_InitTypeDef PPP_InitStructure; 這個PPP_InitTypeDef結(jié)構(gòu)體已經(jīng)在PPP對應的頭文件中進行了定義。 可以看到這個結(jié)構(gòu)體中有3個元素。管腳、端口速度、端口模式 2、為變量PPP_InitStructure的各個結(jié)構(gòu)成員填入允許的值。 采用兩種方式: PPP_InitStructure.member1=val1; PPP_InitStructure.member2=val2; PPP_InitStructure.memberN=valN; 以上步驟可以合并在同一行里,用于優(yōu)化代碼大小: PPP_InitTypeDef PPP_InitStructure={val1,val2,……valN} 僅設置結(jié)構(gòu)體中的部分成員:這種情況下,用戶應當首先調(diào)用函數(shù)PPP_SturcInit( )來初始化變量PPP_InitStructure,然后再修改其中需要修改的成員。這樣可以保證其他成員(多為缺省值)被正確填入。 PPP_StructInit (&PPP_InitStructure); PPP_InitStructure.memberX=valX; PPP_InitStructure.memberY=valY; 3、調(diào)用函數(shù)PPP_Init( )來初始化外設PPP。 4、在這一步,外設PPP已被初始化。可以調(diào)用函數(shù)PPP_Cmd( )來使能之。 PPP_Cmd(PPP,ENABLE); 注意: 1、在設置一個外設之前,必須調(diào)用以下一個函數(shù)來使能它的時鐘: RCC_AHBPeriphClockCmd(RCC_AHBPeriph_PPPx,ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_PPPx,ENABLE); RCC_APB1PeriphClockCmd(RCC_APB1Periph_PPPx,ENABLE); 具體應該調(diào)用那個函數(shù)看下圖 2、可以調(diào)用函數(shù)PPP_DeInit(PPP)來把外設PPP的所用寄存器復位為缺省值 3、在外設設置完成后,繼續(xù)修改它的一些參數(shù),可以參照如下步驟: PPP_InitStructure.memberX=valx; PPP_InitStructure.memberY=valy; PPP_Init(PPP,&PPP_InitStructure); 總結(jié) 如何將GPIOA設置成浮動輸入模式 下面看一個實際的例子。  循環(huán)點亮如圖的三個發(fā)光二極管。 在模板的文件中新建一個文件夾led. 在MDK中新建led.h和led.c文件 Led.c文件內(nèi)容如下: #include"led.h" /* 函數(shù)名:LED_GPIO_Config 描述: 配置LED用到的I/O口 輸入 : 無 輸出: 無 */
void LED_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure;//定義一個GPIO_InitTypeDef類型的結(jié)構(gòu)體 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5; //選擇要控制的引腳 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//設置引腳模式為通用推挽輸出 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//設置引腳速率為50MHz GPIO_Init(GPIOC,&GPIO_InitStructure);//調(diào)用庫函數(shù)初始化GPIOC RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOC, ENABLE); //開啟GPIOC的外設時鐘 GPIO_SetBits(GPIOC,GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5);//關閉所有的led } Led.h文件如下: #ifndef __LED_H #define __LED_H #include"stm32f10x.h"
#define ON 0 #define OFF 1 #define LED1(a) if(a) GPIO_SetBits(GPIOC,GPIO_Pin_3);\ else GPIO_ResetBits(GPIOC,GPIO_Pin_3)//調(diào)用置位和復位函數(shù)函數(shù) #define LED2(a) if(a)GPIO_SetBits(GPIOC,GPIO_Pin_4);\ else GPIO_ResetBits(GPIOC,GPIO_Pin_4) #define LED3(a) if(a) GPIO_SetBits(GPIOC,GPIO_Pin_5);\ else GPIO_ResetBits(GPIOC,GPIO_Pin_5) /*也可以調(diào)用void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal);向指定的端口寫入數(shù)據(jù) #define LED1(a) if(a) GPIO_Write(GPIOC,0xfffb );\ else GPIO_Write(GPIOC,0xffff ) #define LED2(a) if(a) GPIO_Write(GPIOC,0xfff7 );\ else GPIO_Write(GPIOC,0xffff ) #define LED3(a) if(a) GPIO_Write(GPIOC,0xffef );\ else GPIO_Write(GPIOC,0xffff ) */ void LED_GPIO_Config(void); #endif 在main.c文件中輸入如下代碼: #include "stm32f10x.h" #include "led.h" void Delay(vu32 nCount); int main(void) { LED_GPIO_Config();// while(1) { LED1(ON); Delay(0x0fffef); LED1(OFF); LED2(ON); Delay(0x0fffef); LED2(OFF); LED3(ON); Delay(0x0fffef); LED3(OFF); } } void Delay(vu32 nCount) { for(;nCount!=0;nCount--); } 打開stm32f10x_conf.h文件,將不需要的頭文件注釋掉 /* Includes ------------------------------------------------------------------*/ /* Uncomment/Comment the line below to enable/disable peripheral header file inclusion */ //#include "stm32f10x_adc.h" //#include "stm32f10x_bkp.h" //#include "stm32f10x_can.h" //#include "stm32f10x_cec.h" //#include "stm32f10x_crc.h" //#include "stm32f10x_dac.h" //#include "stm32f10x_dbgmcu.h" //#include "stm32f10x_dma.h" //#include "stm32f10x_exti.h" //#include "stm32f10x_flash.h" //#include "stm32f10x_fsmc.h" #include "stm32f10x_gpio.h" //#include "stm32f10x_i2c.h" ///#include "stm32f10x_iwdg.h" //#include "stm32f10x_pwr.h" #include "stm32f10x_rcc.h" //#include "stm32f10x_rtc.h" //#include "stm32f10x_sdio.h" //#include "stm32f10x_spi.h" //#include "stm32f10x_tim.h" //#include "stm32f10x_usart.h" //#include "stm32f10x_wwdg.h" //#include "misc.h" /* High level functions for NVIC and SysTick (add-on to CMSIS functions) */ “編譯”----“debug” 運行結(jié)果如下圖 具體的代碼分析如下: 在led.c文件中定義了一個函數(shù), void LED_GPIO_Config(void).作用是對端口進行初始化。 初始化設置的步驟,就像前面說明的那樣。 1、GPIO_InitTypeDef GPIO_InitStructure;//定義一個GPIO_InitTypeDef類型的結(jié)構(gòu)體 對于GPIO_InitTypeDef這個結(jié)構(gòu)體在stm32f10x_gpio.h頭文件中做了如下定義 typedef struct { uint16_t GPIO_Pin; /*!< Specifies the GPIO pins to be configured. This parameter can be any value of @ref GPIO_pins_define */ GPIOSpeed_TypeDef GPIO_Speed; /*!< Specifies the speed for the selected pins. This parameter can be a value of @ref GPIOSpeed_TypeDef */ GPIOMode_TypeDef GPIO_Mode; /*!< Specifies the operating mode for the selected pins. This parameter can be a value of @ref GPIOMode_TypeDef */ }GPIO_InitTypeDef; 包含3個不同類型的成員,引腳、速度、模式。 2、然后是對這3個成員賦值 GPIO_InitStructure.GPIO_Pin=GPIO_Pin_3|GPIO_Pin_4|GPIO_Pin_5; //選擇要控制的引腳 GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;//設置引腳模式為通用推挽輸出 GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;//設置引腳速率為50MHz 其中引腳的選項在stm32f10x_gpio.h中是如下定義的, /** @defgroup GPIO_pins_define * @{ */ #define GPIO_Pin_0 ((uint16_t)0x0001) /*!< Pin 0 selected */ #define GPIO_Pin_1 ((uint16_t)0x0002) /*!< Pin 1 selected */ #define GPIO_Pin_2 ((uint16_t)0x0004) /*!< Pin 2 selected */ #define GPIO_Pin_3 ((uint16_t)0x0008) /*!< Pin 3 selected */ #define GPIO_Pin_4 ((uint16_t)0x0010) /*!< Pin 4 selected */ #define GPIO_Pin_5 ((uint16_t)0x0020) /*!< Pin 5 selected */ #define GPIO_Pin_6 ((uint16_t)0x0040) /*!< Pin 6 selected */ #define GPIO_Pin_7 ((uint16_t)0x0080) /*!< Pin 7 selected */ #define GPIO_Pin_8 ((uint16_t)0x0100) /*!< Pin 8 selected */ #define GPIO_Pin_9 ((uint16_t)0x0200) /*!< Pin 9 selected */ #define GPIO_Pin_10 ((uint16_t)0x0400) /*!< Pin 10 selected */ #define GPIO_Pin_11 ((uint16_t)0x0800) /*!< Pin 11 selected */ #define GPIO_Pin_12 ((uint16_t)0x1000) /*!< Pin 12 selected */ #define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Pin 13 selected */ #define GPIO_Pin_14 ((uint16_t)0x4000) /*!< Pin 14 selected */ #define GPIO_Pin_15 ((uint16_t)0x8000) /*!< Pin 15 selected */ #define GPIO_Pin_All ((uint16_t)0xFFFF) /*!< All pins selected */ 模式在stm32f10x_gpio.h頭文件中是如下定義的, /** * @brief Configuration Mode enumeration */ typedef enum //枚舉 { GPIO_Mode_AIN = 0x0, GPIO_Mode_IN_FLOATING = 0x04, GPIO_Mode_IPD = 0x28, GPIO_Mode_IPU = 0x48, GPIO_Mode_Out_OD = 0x14, GPIO_Mode_Out_PP = 0x10, GPIO_Mode_AF_OD = 0x1C, GPIO_Mode_AF_PP = 0x18 }GPIOMode_TypeDef; 速度在stm32f10x_gpio.h頭文件中是如下定義的, /** * @brief Output Maximum frequency selection */ typedef enum { GPIO_Speed_10MHz = 1, GPIO_Speed_2MHz, GPIO_Speed_50MHz }GPIOSpeed_TypeDef; 3、GPIO_Init(GPIOC,&GPIO_InitStructure);//調(diào)用庫函數(shù)初始化GPIOC 這個函數(shù)在stm32f10x_gpio.c文件中是如下定義的, /** * @brief Initializes the GPIOx peripheral according to the specified * parameters in the GPIO_InitStruct. * @param GPIOx: where x can be (A..G) to select the GPIO peripheral. * @param GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that * contains the configuration information for the specified GPIO peripheral. * @retval None */ void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct) { uint32_t currentmode = 0x00, currentpin = 0x00, pinpos = 0x00, pos = 0x00; uint32_t tmpreg = 0x00, pinmask = 0x00; /* Check the parameters */ assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode)); assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin)); /*---------------------------- GPIO Mode Configuration -----------------------*/ currentmode = ((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x0F);//只取低4位 if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)//為輸出模式 { /* Check the parameters */ assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));//檢查輸出的參數(shù)是否正確 /* Output mode */ currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; } /*---------------------------- GPIO CRL Configuration ------------------------*/ /* Configure the eight low port pins */ if (((uint32_t)GPIO_InitStruct->GPIO_Pin & ((uint32_t)0x00FF)) != 0x00)//如果是輸入模式 { tmpreg = GPIOx->CRL; for (pinpos = 0x00; pinpos < 0x08; pinpos++) { pos = ((uint32_t)0x01) << pinpos; /* Get the port pins position */ currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; if (currentpin == pos) { pos = pinpos << 2; /* Clear the corresponding low control register bits */ pinmask = ((uint32_t)0x0F) << pos; tmpreg &= ~pinmask; /* Write the mode configuration in the corresponding bits */ tmpreg |= (currentmode << pos); /* Reset the corresponding ODR bit */ if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) { GPIOx->BRR = (((uint32_t)0x01) << pinpos); } else { /* Set the corresponding ODR bit */ if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) { GPIOx->BSRR = (((uint32_t)0x01) << pinpos); } } } } GPIOx->CRL = tmpreg; } /*---------------------------- GPIO CRH Configuration ------------------------*/ /* Configure the eight high port pins */ if (GPIO_InitStruct->GPIO_Pin > 0x00FF) { tmpreg = GPIOx->CRH; for (pinpos = 0x00; pinpos < 0x08; pinpos++) { pos = (((uint32_t)0x01) << (pinpos + 0x08)); /* Get the port pins position */ currentpin = ((GPIO_InitStruct->GPIO_Pin) & pos); if (currentpin == pos) { pos = pinpos << 2; /* Clear the corresponding high control register bits */ pinmask = ((uint32_t)0x0F) << pos; tmpreg &= ~pinmask; /* Write the mode configuration in the corresponding bits */ tmpreg |= (currentmode << pos); /* Reset the corresponding ODR bit */ if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPD) { GPIOx->BRR = (((uint32_t)0x01) << (pinpos + 0x08)); } /* Set the corresponding ODR bit */ if (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_IPU) { GPIOx->BSRR = (((uint32_t)0x01) << (pinpos + 0x08)); } } } GPIOx->CRH = tmpreg; } } GPIO_Init(GPIOC,&GPIO_InitStructure);//調(diào)用庫函數(shù)初始化GPIOC函數(shù)中的 GPIO_InitStructure是我們自己定義的一個結(jié)構(gòu)體變量名 GPIO_InitTypeDef GPIO_InitStructure;//定義一個GPIO_InitTypeDef類型的結(jié)構(gòu)體變量 后記: 熟悉了GPIO的應用,對如何查找固件庫和參考手冊中的相關內(nèi)容、系統(tǒng)頭文件及外設的.H和.C文件構(gòu)成、函數(shù)的功能及調(diào)用,就有了一定的了解。舉一反三對于其他的外設基本數(shù)據(jù)的架構(gòu)及應用與GPIO類似。至于.S的啟動文件的分析以后再做說明。
|