您好,欢迎来到爱go旅游网。
搜索
您的当前位置:首页GPIO的库函数

GPIO的库函数

来源:爱go旅游网
GPIO的库函数

1 void GPIO_DeInit(GPIO_TypeDef* GPIOx)

这个函数调⽤了rcc.c⾥⾯的RCC_AHB1PeriphResetCmd,对外设端⼝进⾏复位,最终操作的是RCC_AHB1RSTR和RCC_AHB2RSTR,这样操作后,使端⼝寄存器恢复默认值void GPIO_DeInit(GPIO_TypeDef* GPIOx){

/* Check the parameters */

assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

if (GPIOx == GPIOA) {

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, ENABLE); //复位端⼝ RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, DISABLE);//不复位 }

else if (GPIOx == GPIOB) {

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOB, ENABLE); RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOB, DISABLE); }

else if (GPIOx == GPIOC) {

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOC, ENABLE); RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOC, DISABLE); }

else if (GPIOx == GPIOD) {

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOD, ENABLE); RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOD, DISABLE); }

else if (GPIOx == GPIOE) {

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOE, ENABLE); RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOE, DISABLE); }

else if (GPIOx == GPIOF) {

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOF, ENABLE); RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOF, DISABLE); }

else if (GPIOx == GPIOG) {

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOG, ENABLE); RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOG, DISABLE); }

else if (GPIOx == GPIOH) {

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOH, ENABLE); RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOH, DISABLE); }

else if (GPIOx == GPIOI) {

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOI, ENABLE); RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOI, DISABLE); }

else if (GPIOx == GPIOJ) {

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOJ, ENABLE); RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOJ, DISABLE); } else {

if (GPIOx == GPIOK) {

RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOK, ENABLE); RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOK, DISABLE); } }}

2 这个函数传⼊的参数是GPIO_TypeDef和GPIO_InitStruct,GPIO_TypeDef是⼀个数组,包含了所有GPIO相关的寄存器。GPIO_InitTypeDef也是⼀个数组,包含了对GPIO的具体配置选项,⽐如输⼊输出选择等等。

void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct){

uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00; // 参数检查

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));

for (pinpos = 0x00; pinpos < 0x10; pinpos++) //从第0个pin开始扫描要赋值哪个pin {

pos = ((uint32_t)0x01) << pinpos; /* Get the port pins position */

currentpin = (GPIO_InitStruct->GPIO_Pin) & pos; //GPIO_InitStruct->GPIO_Pin会确定GPIOX端⼝中具体哪个管脚被初始化 if (currentpin == pos) //扫描到了需要初始化的管脚,进⾏配置

{ //现在GPIOX是⼀个指向GPIO_TypeDef的指针,那么GPIO->就是在操作moder寄存器

GPIOx->MODER &= ~(GPIO_MODER_MODER0 << (pinpos * 2)); // 把这个要配置的pin对于的moder寄存器的两位清零 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)); //这⾥和moder寄存器的配置是⼀样的 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)); //配置输出或者推挽,⼀个bit对应⼀个pin,所以不需要pinpos*2 }

/* 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 myGPIO_Init(void){

GPIO_InitTypeDef GPIO_InitStructure;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOF, ENABLE);//使能F端⼝的时钟//GPIOF9,F10初始化

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9 | GPIO_Pin_10;//选择需要配置的管脚。GPIO_Pin_9的值被定义成0x0200 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;// 配置成输出

GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;// 配置成push-pull GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//配置成上拉 GPIO_Init(GPIOF, &GPIO_InitStructure);// 调⽤上⾯这个初始化函数}

以上有很多例如:GPIO_Pin_9 ,GPIO_Mode_OUT,都是定义在stm32f4xx_gpio.h的枚举类的值。以上这个函数,把各种值赋给

GPIO_InitTypeDef类型的GPIO_InitStructure数组,然后调⽤GPIO_Init这个函数,把这些设置写⼊寄存器。GPIOF是F端⼝的寄存器基地址。3.void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct)这个函数和上⾯这个调⽤类似,是把这些GPIO寄存器恢复默认值

void GPIO_StructInit(GPIO_InitTypeDef* GPIO_InitStruct){

/* Reset GPIO init structure parameters values */ GPIO_InitStruct->GPIO_Pin = GPIO_Pin_All; GPIO_InitStruct->GPIO_Mode = GPIO_Mode_IN;

GPIO_InitStruct->GPIO_Speed = GPIO_Speed_2MHz; GPIO_InitStruct->GPIO_OType = GPIO_OType_PP; GPIO_InitStruct->GPIO_PuPd = GPIO_PuPd_NOPULL;}

4.void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)

端⼝配置锁定寄存器,传⼊的参数的哪个端⼝,哪个管脚,具体见GPIOx_LCKR寄存器。是⽤来锁定管脚的配置,这个寄存器低16位是具体某个管脚的锁定使能。LCKK管脚是总的锁定激活。这⾥的5步操作,在⼿册中是由规定的:“锁定键写序列”

void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin){

__IO uint32_t tmp = 0x00010000;

/* Check the parameters */

assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GPIO_PIN(GPIO_Pin)); tmp |= GPIO_Pin; /* Set LCKK bit */

GPIOx->LCKR = tmp; /* Reset LCKK bit */

GPIOx->LCKR = GPIO_Pin; /* Set LCKK bit */

GPIOx->LCKR = tmp; /* Read LCKK bit*/ tmp = GPIOx->LCKR; /* Read LCKK bit*/ tmp = GPIOx->LCKR;}

5. uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) 这个函数其实是读IDR寄存器,即管脚的输⼊值

uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin){

uint8_t bitstatus = 0x00;

/* Check the parameters */

assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GET_GPIO_PIN(GPIO_Pin));

if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET) //IDR寄存器中,需要读的这个管脚如果不是0 {

bitstatus = (uint8_t)Bit_SET; } else {

bitstatus = (uint8_t)Bit_RESET; }

return bitstatus;}

6、uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx) 这个函数是读16⽐特

uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx){

/* Check the parameters */

assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); return ((uint16_t)GPIOx->IDR);}

7、uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)这个函数是读ODR寄存器,即输出的值,可以看GPIO的结构,输出也是可以读的。

uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin){

uint8_t bitstatus = 0x00;

/* Check the parameters */

assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GET_GPIO_PIN(GPIO_Pin));

if (((GPIOx->ODR) & GPIO_Pin) != (uint32_t)Bit_RESET) {

bitstatus = (uint8_t)Bit_SET; } else {

bitstatus = (uint8_t)Bit_RESET; }

return bitstatus;

8、uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)类似,这⾥读16⽐特

uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx){

/* Check the parameters */

assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); return ((uint16_t)GPIOx->ODR);}

9、void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)写1

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;}

10、void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)写0

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;}

11、void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal)把GPIO的某⼀位写0或者写1

void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal){

/* Check the parameters */

assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); assert_param(IS_GET_GPIO_PIN(GPIO_Pin)); assert_param(IS_GPIO_BIT_ACTION(BitVal)); if (BitVal != Bit_RESET) {

GPIOx->BSRRL = GPIO_Pin; } else {

GPIOx->BSRRH = GPIO_Pin ; }}

12、void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal)对某个端⼝16位赋值

void GPIO_Write(GPIO_TypeDef* GPIOx, uint16_t PortVal){

/* Check the parameters */

assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); GPIOx->ODR = PortVal;}

13、void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)对某个端⼝的值进⾏取反

void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin){

/* Check the parameters */

assert_param(IS_GPIO_ALL_PERIPH(GPIOx)); GPIOx->ODR ^= GPIO_Pin;}

14、void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF)配置GPIO的复⽤功能,具体见AFRL和AFRH寄存器

void GPIO_PinAFConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_PinSource, uint8_t GPIO_AF){

uint32_t temp = 0x00; uint32_t temp_2 = 0x00;

/* Check the parameters */

assert_param(IS_GPIO_ALL_PERIPH(GPIOx));

assert_param(IS_GPIO_PIN_SOURCE(GPIO_PinSource)); assert_param(IS_GPIO_AF(GPIO_AF)); //每个管脚的AF配置,在寄存器中都占了4位

temp = ((uint32_t)(GPIO_AF) << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ;//表⽰移到这两个寄存器中的哪个4位 GPIOx->AFR[GPIO_PinSource >> 0x03] &= ~((uint32_t)0xF << ((uint32_t)((uint32_t)GPIO_PinSource & (uint32_t)0x07) * 4)) ;//先清零 //AFR有两个寄存器,AFR[GPIO-PinSource>>0x03]确定哪个寄存器

temp_2 = GPIOx->AFR[GPIO_PinSource >> 0x03] | temp; //把寄存器中需要赋值的⼏个bit赋值 GPIOx->AFR[GPIO_PinSource >> 0x03] = temp_2; //写⼊需要的值}

调⽤⽅式如下:

GPIO_PinAFConfig(GPIOA,GPIO_PinSource9,GPIO_AF_USART1)GPIO_PinAFConfig(GPIOA,GPIO_PinSource10,GPIO_AF_USART1)

不是所有的管脚,可以复⽤成任意的管脚,PA9和PA10有如下说明。可以看到PA9和USART1_TX,PA10是USART1_RX。PA9:TIM1_CH2, USART1_TX,LCD_COM1, TIM15_BKIN,EVENTOU

PA10:TIM1_CH3, USART1_RX,OTG_FS_ID, LCD_COM2,TIM17_BKIN, EVENTOUT

另外还需要说明的是,这⼏个接⼝,定义的AF的配置都是7,都是⼀样的。但是某个管脚是限定成哪个接⼝的,所以不会搞错。即把PA9和PA10的AF配置成7.是不会映射到USART2去的。同时,不同的USART对应不同的寄存器偏移地址。

#define GPIO_AF_USART1 ((uint8_t)0x07) /* USART1 Alternate Function mapping */#define GPIO_AF_USART2 ((uint8_t)0x07) /* USART2 Alternate Function mapping */#define GPIO_AF_USART3 ((uint8_t)0x07) /* USART3 Alternate Function mapping */#define GPIO_AF7_SPI3 ((uint8_t)0x07) /* SPI3/I2S3ext Alternate Function mapping */

因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- igat.cn 版权所有 赣ICP备2024042791号-1

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务