GPIO
1.GPIO配置为输入、输出、复合输入输出(AF)。
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;
当GPIO用作输入时,Mode1,Mode0 = 00,只有在输出时,才对输出速度进行设置。
GPIO_Mode允许同时设置GPIO方向(输入/ 输出)和对应的输入/ 输出设置,:位[7:4] 对应GPIO方向,位[3:0] 对应配置。
GPIO方向有如下索引
- GPIO输入模式 = 0x00
- GPIO输出模式 = 0x01
在应用程序中,只要对GPIO_InitStructure结构体(即GPIO_InitTypeDef)进行初始化,然后调用库函数GPIO_Init(GPIOA, &GPIO_InitStructure)进行初始化就行。
2.GPIO_Pin的值
该参数选择待设置的GPIO管脚,使用操作符“|”可以一次选中多个管脚。可以使用下表中的任意组合
GPIO_Pin_None | 无管脚被选中 |
GPIO_Pin_0 | 选中管脚0 |
GPIO_Pin_1 | 选中管脚1 |
... ... | ... .... |
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, u16 GPIO_Pin) -->清除指定的数据端口位
/* Clears the GPIOA port pin 10 and pin 15 */
GPIO_ResetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15);
void GPIO_SetBits(GPIO_TypeDef* GPIOx, u16 GPIO_Pin) -->设置指定的数据端口位
/* Set the GPIOA port pin 10 and pin 15 */
GPIO_SetBits(GPIOA, GPIO_Pin_10 | GPIO_Pin_15);
参考数据手册和库函数,后续继续补充。
3.GPIO的寄存器映射
GPIO挂在APB2总线上,因此涉及APB2_peripheral外围的内容,GPIOx在RCC_APB2_GPIOx
#define RCC_APB2Periph_AFIO ((uint32_t)0x00000001)
#define RCC_APB2Periph_GPIOA ((uint32_t)0x00000004)
#define RCC_APB2Periph_GPIOB ((uint32_t)0x00000008)
#define RCC_APB2Periph_GPIOC ((uint32_t)0x00000010)
.... ..... .....
在stm32f10x.h中定义了许多关于寄存器映射的内容,芯片手册28页表1列出了外围寄存器的起始地址
#define PERIPH_BASE ((uint32_t)0x40000000) //寄存器组起始地址,后续的外围寄存器都是以该基址加上相应的便宜来实现对存储器的操作的
/*!< Peripheral memory map */
#define APB1PERIPH_BASE PERIPH_BASE
#define APB2PERIPH_BASE (PERIPH_BASE + 0x10000)
#define AHBPERIPH_BASE (PERIPH_BASE + 0x20000)
APB1总线上的起始地址,APB1PERIPH_BASE就是PERIPH_BASE,结合表1,
0x4000 0000-0x4000 03FF TIM2定时器--------0x4000 7800 - 0x4000FFFF 保留 属于APB1 起始地址--- 0x4000 0000
0x4001 0000 - 0x4001 03FF AFIO---------------0x4001 4000 - 0x4001 7FFF 保留 属于APB2 起始地址-- 0x4001 0000
0x4002 0000 - 0x4002 03FF DMA1 --------------0x5000 0000 – 0x5003 FFFF USB OTG 全速 属于AHB 起始地址---0x4002 0000
针对具体的外围设备,stm32f10x.h定义了具体外围设备的基地址,这里只列出一部分
#define AFIO_BASE (APB2PERIPH_BASE + 0x0000)
#define EXTI_BASE (APB2PERIPH_BASE + 0x0400)
#define GPIOA_BASE (APB2PERIPH_BASE + 0x0800) //GPIOA寄存器起始地址
#define GPIOB_BASE (APB2PERIPH_BASE + 0x0C00)
#define GPIOC_BASE (APB2PERIPH_BASE + 0x1000)
表1中列出的,在这里只做个示例
0x4001 0800 - 0x4001 0BFF | GPIO端口A |
0x4001 0000 - 0x4001 03FF | AFIO |
4.在GPIO初始化的时候,需要对RCC_APBxRSTR外设复位寄存器和RCC_APBxENR时钟使能寄存器进行相应的设置
复位需要用到APB2 外设复位寄存器 (RCC_APB2RSTR) 或APB1 外设复位寄存器 (RCC_APB1RSTR), 在stm32f10x_rcc.h文件中,我们会看到
#define RCC_APB2Periph_AFIO ((uint32_t)0x00000001)
#define RCC_APB2Periph_GPIOA ((uint32_t)0x00000004)
#define RCC_APB2Periph_GPIOB ((uint32_t)0x00000008)
#define RCC_APB2Periph_GPIOC ((uint32_t)0x00000010)
#define RCC_APB2Periph_GPIOD ((uint32_t)0x00000020)
这里其实就是定义了外围设备在复位时,RCC_APB2RSTR中对应的某一位,如RCC_APB2RSTR寄存器中第4位为“IO端口C复位 (IO port C reset) ”。
查看RCC_APBxRSTR外设复位寄存器和RCC_APBxENR时钟使能寄存器就会发现,外围设备在这些寄存器里面的位是对应的。
在使能或者失能外部时钟时,用到了上述定义
RCC_APB2PeriphClockCmd(RCC_GPIO_LED | RCC_APB2Periph_AFIO , ENABLE);
RCC_GPIO_LED在开头定义
#define RCC_GPIO_LED RCC_APB2Periph_GPIOD