stm32,gpio设置原理
下图,定义了gpio E的基地址,只要将这个地址强制转换成gpiotypedf的类型,解析时,结构体地址就会自增。这样就可以对不同gpio组,就像定义。
全部gpio定义,强制为结构体类型,指向这个结构体地址
他们地址偏移量,都事先定义好。
如下设置gpio模式,定义好结构体 GPIO_InitTypeDef GPIO_InitStructure,设置好模式,只需将gpiof传给api,就可以设置到gpio f。
void KEY_Init(void)
{GPIO_InitTypeDef GPIO_InitStructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA|RCC_AHB1Periph_GPIOE, ENABLE);//ʹÄÜGPIOA,GPIOEʱÖÓGPIO_InitStructure.GPIO_Pin = GPIO_Pin_2|GPIO_Pin_3|GPIO_Pin_4; //KEY0 KEY1 KEY2¶ÔÓ¦Òý½ÅGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//ÆÕͨÊäÈëģʽGPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MGPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//ÉÏÀGPIO_Init(GPIOE, &GPIO_InitStructure);//³õʼ»¯GPIOE2,3,4GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;//WK_UP¶ÔÓ¦Òý½ÅPA0GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN ;//ÏÂÀGPIO_Init(GPIOA, &GPIO_InitStructure);//³õʼ»¯GPIOA0}
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GPIO_PIN(GPIO_InitStruct->GPIO_Pin));assert_param(IS_GPIO_MODE(GPIO_InitStruct->GPIO_Mode));assert_param(IS_GPIO_PUPD(GPIO_InitStruct->GPIO_PuPd));/* ------------------------- Configure the port pins ---------------- *//*-- GPIO Mode Configuration --*/for (pinpos = 0x00; pinpos < 0x10; pinpos++){pos = ((uint32_t)0x01) << pinpos;/* Get the port pins position */currentpin = (GPIO_InitStruct->GPIO_Pin) & pos;if (currentpin == pos){GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (pinpos * 2));GPIOx->MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) << (pinpos * 2));if ((GPIO_InitStruct->GPIO_Mode == GPIO_Mode_OUT) || (GPIO_InitStruct->GPIO_Mode == GPIO_Mode_AF)){/* Check Speed mode parameters */assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));/* Speed mode configuration */GPIOx->OSPEEDR &= ~(GPIO_OSPEEDER_OSPEEDR0 << (pinpos * 2));GPIOx->OSPEEDR |= ((uint32_t)(GPIO_InitStruct->GPIO_Speed) << (pinpos * 2));/* Check Output mode parameters */assert_param(IS_GPIO_OTYPE(GPIO_InitStruct->GPIO_OType));/* Output mode configuration*/GPIOx->OTYPER &= ~((GPIO_OTYPER_OT_0) << ((uint16_t)pinpos)) ;GPIOx->OTYPER |= (uint16_t)(((uint16_t)GPIO_InitStruct->GPIO_OType) << ((uint16_t)pinpos));}/* Pull-up Pull down resistor configuration*/GPIOx->PUPDR &= ~(GPIO_PUPDR_PUPDR0 << ((uint16_t)pinpos * 2));GPIOx->PUPDR |= (((uint32_t)GPIO_InitStruct->GPIO_PuPd) << (pinpos * 2));}}
}
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GPIO_PIN(GPIO_Pin));GPIOx->BSRRL = GPIO_Pin;
}
如下,也是可以直接这样设置的,不需传gpiox
由于不止一种gpio结构体属性,由是定义了很多结构体,描述不同属性
typedef struct
{__IO uint32_t CR; /*!< DCMI control register 1, Address offset: 0x00 */__IO uint32_t SR; /*!< DCMI status register, Address offset: 0x04 */__IO uint32_t RISR; /*!< DCMI raw interrupt status register, Address offset: 0x08 */__IO uint32_t IER; /*!< DCMI interrupt enable register, Address offset: 0x0C */__IO uint32_t MISR; /*!< DCMI masked interrupt status register, Address offset: 0x10 */__IO uint32_t ICR; /*!< DCMI interrupt clear register, Address offset: 0x14 */__IO uint32_t ESCR; /*!< DCMI embedded synchronization code register, Address offset: 0x18 */__IO uint32_t ESUR; /*!< DCMI embedded synchronization unmask register, Address offset: 0x1C */__IO uint32_t CWSTRTR; /*!< DCMI crop window start, Address offset: 0x20 */__IO uint32_t CWSIZER; /*!< DCMI crop window size, Address offset: 0x24 */__IO uint32_t DR; /*!< DCMI data register, Address offset: 0x28 */
} DCMI_TypeDef;/** * @brief DMA Controller*/typedef struct
{__IO uint32_t CR; /*!< DMA stream x configuration register */__IO uint32_t NDTR; /*!< DMA stream x number of data register */__IO uint32_t PAR; /*!< DMA stream x peripheral address register */__IO uint32_t M0AR; /*!< DMA stream x memory 0 address register */__IO uint32_t M1AR; /*!< DMA stream x memory 1 address register */__IO uint32_t FCR; /*!< DMA stream x FIFO control register */
} DMA_Stream_TypeDef;typedef struct
{__IO uint32_t LISR; /*!< DMA low interrupt status register, Address offset: 0x00 */__IO uint32_t HISR; /*!< DMA high interrupt status register, Address offset: 0x04 */__IO uint32_t LIFCR; /*!< DMA low interrupt flag clear register, Address offset: 0x08 */__IO uint32_t HIFCR; /*!< DMA high interrupt flag clear register, Address offset: 0x0C */
} DMA_T
2、stm32和arm linux一样,将中断进行编号
typedef enum IRQn
{
/****** Cortex-M4 Processor Exceptions Numbers ****************************************************************/NonMaskableInt_IRQn = -14, /*!< 2 Non Maskable Interrupt */MemoryManagement_IRQn = -12, /*!< 4 Cortex-M4 Memory Management Interrupt */BusFault_IRQn = -11, /*!< 5 Cortex-M4 Bus Fault Interrupt */UsageFault_IRQn = -10, /*!< 6 Cortex-M4 Usage Fault Interrupt */SVCall_IRQn = -5, /*!< 11 Cortex-M4 SV Call Interrupt */DebugMonitor_IRQn = -4, /*!< 12 Cortex-M4 Debug Monitor Interrupt */PendSV_IRQn = -2, /*!< 14 Cortex-M4 Pend SV Interrupt */SysTick_IRQn = -1, /*!< 15 Cortex-M4 System Tick Interrupt */
/****** STM32 specific Interrupt Numbers **********************************************************************/WWDG_IRQn = 0, /*!< Window WatchDog Interrupt */PVD_IRQn = 1, /*!< PVD through EXTI Line detection Interrupt */TAMP_STAMP_IRQn = 2, /*!< Tamper and TimeStamp interrupts through the EXTI line */RTC_WKUP_IRQn = 3, /*!< RTC Wakeup interrupt through the EXTI line */FLASH_IRQn = 4, /*!< FLASH global Interrupt */RCC_IRQn = 5, /*!< RCC global Interrupt */EXTI0_IRQn = 6, /*!< EXTI Line0 Interrupt */EXTI1_IRQn = 7, /*!< EXTI Line1 Interrupt */EXTI2_IRQn = 8, /*!< EXTI Line2 Interrupt */EXTI3_IRQn = 9, /*!< EXTI Line3 Interrupt */EXTI4_IRQn = 10, /*!< EXTI Line4 Interrupt */DMA1_Stream0_IRQn = 11, /*!< DMA1 Stream 0 global Interrupt */DMA1_Stream1_IRQn = 12, /*!< DMA1 Stream 1 global Interrupt */DMA1_Stream2_IRQn = 13, /*!< DMA1 Stream 2 global Interrupt */DMA1_Stream3_IRQn = 14, /*!< DMA1 Stream 3 global Interrupt */DMA1_Stream4_IRQn = 15, /*!< DMA1 Stream 4 global Interrupt */DMA1_Stream5_IRQn = 16, /*!< DMA1 Stream 5 global Interrupt */DMA1_Stream6_IRQn = 17, /*!< DMA1 Stream 6 global Interrupt */ADC_IRQn = 18, /*!< ADC1, ADC2 and ADC3 global Interrupts */#if defined (STM32F40_41xxx)CAN1_TX_IRQn = 19, /*!< CAN1 TX Interrupt */CAN1_RX0_IRQn = 20, /*!< CAN1 RX0 Interrupt */CAN1_RX1_IRQn = 21, /*!< CAN1 RX1 Interrupt */CAN1_SCE_IRQn = 22, /*!< CAN1 SCE Interrupt */EXTI9_5_IRQn = 23, /*!< External Line[9:5] Interrupts */TIM1_BRK_TIM9_IRQn = 24, /*!< TIM1 Break interrupt and TIM9 global interrupt */TIM1_UP_TIM10_IRQn = 25, /*!< TIM1 Update Interrupt and TIM10 global interrupt */TIM1_TRG_COM_TIM11_IRQn = 26, /*!< TIM1 Trigger and Commutation Interrupt and TIM11 global interrupt */TIM1_CC_IRQn = 27, /*!< TIM1 Capture Compare Interrupt */TIM2_IRQn = 28, /*!< TIM2 global Interrupt */TIM3_IRQn = 29, /*!< TIM3 global Interrupt */TIM4_IRQn = 30, /*!< TIM4 global Interrupt */I2C1_EV_IRQn = 31, /*!< I2C1 Event Interrupt */I2C1_ER_IRQn = 32, /*!< I2C1 Error Interrupt */I2C2_EV_IRQn = 33, /*!< I2C2 Event Interrupt */I2C2_ER_IRQn = 34, /*!< I2C2 Error Interrupt */SPI1_IRQn = 35, /*!< SPI1 global Interrupt */SPI2_IRQn = 36, /*!< SPI2 global Interrupt */USART1_IRQn = 37, /*!< USART1 global Interrupt */USART2_IRQn = 38, /*!< USART2 global Interrupt */USART3_IRQn = 39, /*!< USART3 global Interrupt */EXTI15_10_IRQn = 40, /*!< External Line[15:10] Interrupts */RTC_Alarm_IRQn = 41, /*!< RTC Alarm (A and B) through EXTI Line Interrupt */OTG_FS_WKUP_IRQn = 42, /*!< USB OTG FS Wakeup through EXTI line interrupt */TIM8_BRK_TIM12_IRQn = 43, /*!< TIM8 Break Interrupt and TIM12 global interrupt */TIM8_UP_TIM13_IRQn = 44, /*!< TIM8 Update Interrupt and TIM13 global interrupt */TIM8_TRG_COM_TIM14_IRQn = 45, /*!< TIM8 Trigger and Commutation Interrupt and TIM14 global interrupt */TIM8_CC_IRQn = 46, /*!< TIM8 Capture Compare Interrupt */DMA1_Stream7_IRQn = 47, /*!< DMA1 Stream7 Interrupt */FSMC_IRQn = 48, /*!< FSMC global Interrupt */SDIO_IRQn = 49, /*!< SDIO global Interrupt */TIM5_IRQn = 50, /*!< TIM5 global Interrupt */SPI3_IRQn = 51, /*!< SPI3 global Interrupt */UART4_IRQn = 52, /*!< UART4 global Interrupt */UART5_IRQn = 53, /*!< UART5 global Interrupt */TIM6_DAC_IRQn = 54, /*!< TIM6 global and DAC1&2 underrun error interrupts */TIM7_IRQn = 55, /*!< TIM7 global interrupt */DMA2_Stream0_IRQn = 56, /*!< DMA2 Stream 0 global Interrupt */DMA2_Stream1_IRQn = 57, /*!< DMA2 Stream 1 global Interrupt */DMA2_Stream2_IRQn = 58, /*!< DMA2 Stream 2 global Interrupt */DMA2_Stream3_IRQn = 59, /*!< DMA2 Stream 3 global Interrupt */DMA2_Stream4_IRQn = 60, /*!< DMA2 Stream 4 global Interrupt */ETH_IRQn = 61, /*!< Ethernet global Interrupt */ETH_WKUP_IRQn = 62, /*!< Ethernet Wakeup through EXTI line Interrupt */CAN2_TX_IRQn = 63, /*!< CAN2 TX Interrupt */CAN2_RX0_IRQn = 64, /*!< CAN2 RX0 Interrupt */CAN2_RX1_IRQn = 65, /*!< CAN2 RX1 Interrupt */CAN2_SCE_IRQn = 66, /*!< CAN2 SCE Interrupt */OTG_FS_IRQn = 67, /*!< USB OTG FS global Interrupt */DMA2_Stream5_IRQn = 68, /*!< DMA2 Stream 5 global interrupt */DMA2_Stream6_IRQn = 69, /*!< DMA2 Stream 6 global interrupt */DMA2_Stream7_IRQn = 70, /*!< DMA2 Stream 7 global interrupt */USART6_IRQn = 71, /*!< USART6 global interrupt */I2C3_EV_IRQn = 72, /*!< I2C3 event interrupt */I2C3_ER_IRQn = 73, /*!< I2C3 error interrupt */OTG_HS_EP1_OUT_IRQn = 74, /*!< USB OTG HS End Point 1 Out global interrupt */OTG_HS_EP1_IN_IRQn = 75, /*!< USB OTG HS End Point 1 In global interrupt */OTG_HS_WKUP_IRQn = 76, /*!< USB OTG HS Wakeup through EXTI interrupt */OTG_HS_IRQn = 77, /*!< USB OTG HS global interrupt */DCMI_IRQn = 78, /*!< DCMI global interrupt */CRYP_IRQn = 79, /*!< CRYP crypto global interrupt */HASH_RNG_IRQn = 80, /*!< Hash and Rng global interrupt */FPU_IRQn
arm linux驱动开发也是一样的,这部分寄存器定义,由芯片厂商完成,驱动移植者,只需要调用设置就可以了。stm32只是没有操作系统,来管理应用程序,驱动,linux有操作系统,进程管理,来调度驱动。
stm32官方定义好的gpio设置api
void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));GPIOx->ODR = PortVal;
}
*/
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));return ((uint16_t)GPIOx->ODR);
}
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GPIO_PIN(GPIO_Pin));GPIOx->BSRRL = GPIO_Pin;
}
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{/* Check the parameters */assert_param(IS_GPIO_ALL_PERIPH(GPIOx));assert_param(IS_GPIO_PIN(GPIO_Pin));GPIOx->BSRRH = GPIO_Pin;
}
其实linux也是一样的,这部分有linux官方已经定义好统一的接口,芯片厂商,调用接口,对接自己的gpio,寄存器,设置好就可以了。
有些不按gpio的标准写驱动,和stm32一样,直接操作寄存器。