STM32F407标准库学习笔记-GPIO
头文件 gpio.h
- 枚举-列举同一寄存器的不同选项
typedef enum
{
GPIO_Low_Speed = 0x00, /*!< Low speed */
GPIO_Medium_Speed = 0x01, /*!< Medium speed */
GPIO_Fast_Speed = 0x02, /*!< Fast speed */
GPIO_High_Speed = 0x03 /*!< High speed */
}GPIOSpeed_TypeDef;
/* Add legacy definition */
#define GPIO_Speed_2MHz GPIO_Low_Speed
#define GPIO_Speed_25MHz GPIO_Medium_Speed
#define GPIO_Speed_50MHz GPIO_Fast_Speed
#define GPIO_Speed_100MHz GPIO_High_Speed
//具体功能可以用宏定义进一步封装
- 枚举-用来体现状态(函数执行、引脚高低、位数据)
typedef enum
{
Bit_RESET = 0,
Bit_SET
}BitAction;
- 结构体-将配置一个引脚所需描述的信息进行封装
typedef struct
{
uint32_t GPIO_Pin;
GPIOMode_TypeDef GPIO_Mode;
GPIOSpeed_TypeDef GPIO_Speed;
GPIOOType_TypeDef GPIO_OType;
GPIOPuPd_TypeDef GPIO_PuPd;
}GPIO_InitTypeDef;
- 宏定义-对引脚在寄存器中对应的位数进行封装
#define GPIO_Pin_0 ((uint16_t)0x0001)
#define GPIO_Pin_1 ((uint16_t)0x0002)
#define GPIO_Pin_2 ((uint16_t)0x0004)
#define GPIO_Pin_3 ((uint16_t)0x0008)
#define GPIO_Pin_4 ((uint16_t)0x0010)
#define GPIO_PIN_MASK ((uint32_t)0x0000FFFF) /* PIN mask for assert test */
- 宏定义-对引脚的复用功能进行封装
//@brief AF 0 selection
#define GPIO_AF_RTC_50Hz ((uint8_t)0x00) /* RTC_50Hz Alternate Function mapping */
#define GPIO_AF_MCO ((uint8_t)0x00) /* MCO (MCO1 and MCO2) Alternate Function mapping */
#define GPIO_AF_TAMPER ((uint8_t)0x00) /* TAMPER (TAMPER_1 and TAMPER_2) Alternate Function mapping */
#define GPIO_AF_SWJ ((uint8_t)0x00) /* SWJ (SWD and JTAG) Alternate Function mapping */
#define GPIO_AF_TRACE ((uint8_t)0x00) /* TRACE Alternate Function mapping */
- 声明GPIO相关函数
void GPIO_DeInit(GPIO_TypeDef* GPIOx);
C文件 gpio.c
1.初始化与配置段
void GPIO_DeInit(GPIO_TypeDef* GPIOx)
{
if (GPIOx == GPIOA)
{
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, ENABLE);
RCC_AHB1PeriphResetCmd(RCC_AHB1Periph_GPIOA, DISABLE);
}
else if (GPIOx == GPIOB)
gpio复位函数
借用RCC中的外设复位功能直接对相关引脚组(模块)全盘复位;
传入引脚组名,借助引脚组宏定义对应的地址进行判断;
先使能复位,后失能复位。
void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct)
{
uint32_t pinpos = 0x00, pos = 0x00 , currentpin = 0x00;
/* ------------------------- 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))
}
}
}
gpio初始化函数
传入引脚组名、引脚初始化结构体;
pinpos代表引脚标号,使pos的1左移到对应的bit位;
利用for循环和&处理GPIO_Pin和pos,寻找选定的引脚;
根据引脚组名和结构体,对寄存器赋值;先复位,后置位。
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初始化结构体复位
与硬件寄存器无关,只是修改引脚初始化结构体里的值
void GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
__IO uint32_t tmp = 0x00010000;
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;
}
锁定引脚配置函数
tmp初始值和函数内部的流程与锁定引脚的读写寄存器有关;
最后要读两次完成锁定,第二次的LCKK位的值可信,用来确认锁定。
2.读与写
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint8_t bitstatus = 0x00;
if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)Bit_RESET)
{
bitstatus = (uint8_t)Bit_SET;
读取特定引脚输入值
将 输入数据寄存器 与 引脚在寄存器中的对应位 的 1 相于,取出特定位的值;
函数有返回值,uint8类型。
uint16_t GPIO_ReadInputData(GPIO_TypeDef* GPIOx)
{
return ((uint16_t)GPIOx->IDR);
}
读取特定引脚组输入值
直接返回一组IDR。
uint8_t GPIO_ReadOutputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
uint16_t GPIO_ReadOutputData(GPIO_TypeDef* GPIOx)
读取输入数据
同上。
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIOx->BSRRL = GPIO_Pin;
}
特定引脚输出1
向BSRR低16位的特定位写1,影响引脚输出。
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIOx->BSRRH = GPIO_Pin;
}
特定引脚输出0
向BSRR高16位的特定位写1,影响引脚输出。
void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal)
{
if (BitVal != Bit_RESET)
{
GPIOx->BSRRL = GPIO_Pin;
}
else
{
GPIOx->BSRRH = GPIO_Pin ;
}
}
将以上两个函数使用if和头文件中的bit状态枚举变量进行结合。
void GPIO_ToggleBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
GPIOx->ODR ^= GPIO_Pin;
}
输出翻转
对一组输出数据寄存器中的值进行按位取反。