GPIO的库函数 |
您所在的位置:网站首页 › gpioreadoutputdatabit怎样用 › 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) GPIO_Pin会确定GPIOX端口中具体哪个管脚被初始化 if (currentpin == pos) //扫描到了需要初始化的管脚,进行配置 { //现在GPIOX是一个指向GPIO_TypeDef的指针,那么GPIO->就是在操作moder寄存器 GPIOx->MODER &= ~(GPIO_MODER_MODER0 MODER |= (((uint32_t)GPIO_InitStruct->GPIO_Mode) 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 OSPEEDR |= ((uint32_t)(GPIO_InitStruct->GPIO_Speed) GPIO_OType)); /* Output mode configuration*/ GPIOx->OTYPER &= ~((GPIO_OTYPER_OT_0) GPIO_OType) GPIO_PuPd) 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) AFR[GPIO_PinSource >> 0x03] &= ~((uint32_t)0xF >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,EVENTOUPA10: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 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |