1、GPIO 常用的几个寄存器
GPIO可以简单理解为芯片的引脚,芯片有多少个引脚,就有多少个GPIO 口(简单理解),然后每个脚用来干嘛的,就要看手册,看资料了。
1.1 GPIOx_CRL(x=A…E) 配置某组GPIO口中低 8个引脚,例如GPIOC_5, 就是C组里面的第5个引脚
1.2 GPIOx_CRH (x=A…E) 配置某组GPIO口中高 8个引脚,例如GPIOC_12, 就是C组里面的第12个引脚
1.3 GPIOx_IDR (x=A…E) 端口输入数据寄存器,芯片读取引脚上的电平值,存放在这个寄存器里面
1.4 GPIOx_ODR (x=A…E) 端口输出数据寄存器
1.5 GPIOx_BSRR (x=A…E) 端口位设置/清除寄存器
1.6 GPIOx_BRR (x=A…E) 端口位清除寄存器,跟GPIOx_BSRR 重复了
2、GPIO的基地址:每个组(端口)的基地址不同:
Library\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h (芯片的不同型号,不同封装都会有差异)
A组(A端口)GPIOA 0x4001 0800
B组(B端口)GPIOB 0x4001 0C00
C组(C端口)GPIOC 0x4001 1000
D组(D端口)GPIOD 0x4001 1400
E组(E端口)GPIOE 0x4001 1800
F组(F端口)GPIOF 0x4001 1C00
G组(G端口)GPIOG 0x4001 2000
#define PERIPH_BASE ((uint32_t)0x40000000) /*!< Peripheral base address in the alias region */
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800)
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
#define GPIOD_BASE (APB2PERIPH_BASE + 0x1400)
#define GPIOE_BASE (APB2PERIPH_BASE + 0x1800)
#define GPIOF_BASE (APB2PERIPH_BASE + 0x1C00)
#define GPIOG_BASE (APB2PERIPH_BASE + 0x2000)
GPIOA 包含引脚PA0 ~ PA15
GPIOB 包含引脚PA0 ~ PA15
GPIOC 包含引脚PA0 ~ PA15
GPIOD 包含引脚PA0 ~ PA15
GPIOE 包含引脚PA0 ~ PA15
GPIOF 包含引脚PA0 ~ PA7
GPIOG 包含引脚PA0 ~ PA7
3、寄存器介绍
3.1 端口配置低寄存器(GPIOx_CRL) (x=A…E)
============================================== 分割线 =================================================
============================================== 分割线 =================================================
============================================== 分割线 =================================================
3.2、 端口配置高寄存器(GPIOx_CRH) (x=A…E)
============================================== 分割线 =================================================
3.3、端口输入数据寄存器(GPIOx_IDR) (x=A…E)
3.4、端口输出数据寄存器(GPIOx_ODR) (x=A…E)
3.5、 端口位设置/清除寄存器(GPIOx_BSRR) (x=A…E)
3.6、 端口位清除寄存器(GPIOx_BRR) (x=A…E)
3.7GPIO 模块图
3.8、端口配置表,对GPIOx_CRL 和 GPIOx_CRH 两个寄存器配置的补充说明
3.9 GPIO的初始化,以GPIOC_12 为例
使用库函数对GPIO 端口初始化,最底层还是对上面几个寄存器进行配置,只是封装了一下而已。让用户使用起来方便一些。
Library\CMSIS\CM3\DeviceSupport\ST\STM32F10x\stm32f10x.h
#define GPIOA ((GPIO_TypeDef *) GPIOA_BASE)
#define GPIOB ((GPIO_TypeDef *) GPIOB_BASE)
#define GPIOC ((GPIO_TypeDef *) GPIOC_BASE)
#define GPIOD ((GPIO_TypeDef *) GPIOD_BASE)
#define GPIOE ((GPIO_TypeDef *) GPIOE_BASE)
#define GPIOF ((GPIO_TypeDef *) GPIOF_BASE)
#define GPIOG ((GPIO_TypeDef *) GPIOG_BASE)
Library\STM32F10x_StdPeriph_Driver\inc\stm32f10x_gpio.h
#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 */
Library\STM32F10x_StdPeriph_Driver\inc\stm32f10x_gpio.h
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;
typedef enum
{
GPIO_Speed_10MHz = 1,
GPIO_Speed_2MHz,
GPIO_Speed_50MHz
}GPIOSpeed_TypeDef;
main.c
void func(void)
{
GPIO_InitTypeDef GPIO_InitStructure; // stm32f10x_gpio.h 标准化的结构体
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; // 0x10 推挽输出
GPIO_InitStructure.GPIO_Pin= GPIO_Pin_12; // GPIO_Pin_12 = 0x1000, GPIOC_12
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz; // 3
GPIO_Init(GPIOC,&GPIO_InitStructure);
}
Library\STM32F10x_StdPeriph_Driver\src\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;
uint32_t pos = 0x00; // pin position: pin0, pin1, pin2, pin3, pin4, pin5, pin6, pin7, pin8, pin9, pin10, pin11, pin12, pin13, pin14, pin15
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); // currentmode = 0x00 00 00 00
if ((((uint32_t)GPIO_InitStruct->GPIO_Mode) & ((uint32_t)0x10)) != 0x00)
{
/* Check the parameters */
assert_param(IS_GPIO_SPEED(GPIO_InitStruct->GPIO_Speed));
/* Output mode */
currentmode |= (uint32_t)GPIO_InitStruct->GPIO_Speed; // currentmode = 0x00 00 00 03
}
/*---------------------------- 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; // operate pin0, pin1, pin2, pin3, pin4, pin5, pin6, pin7
/* 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;
}
4、 GPIO 的重映射功能
4.1 定时器TIM3 重映射
定时器 TIM3 完全重映射: 引脚PC6、7、8、9 原来是做其它用途的,完全重映射之后就变成了TIM3 的各个通道
引脚 PC6 变成了TIM3 的CH1 通道,(原来TIM3的CH1通道是PA6 引脚)
引脚 PC7 变成了TIM3 的CH2 通道,
引脚 PC8 变成了TIM3 的CH3 通道,
引脚 PC9 变成了TIM3 的CH9 通道,
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE); // TIM3 完全重映射
说白了,就是定时器TIM3 换了几个脚而已