typedef struct
{
__IO uint32_t CRL;
__IO uint32_t CRH;
__IO uint32_t IDR;
__IO uint32_t ODR;
__IO uint32_t BSRR;
__IO uint32_t BRR;
__IO uint32_t LCKR;
} GPIO_TypeDef;
GPIO输出模式:
推挽输出
一般应用于电平0V和3.3V且需要高速切换开关状态的场合。
开漏输出
应用于“线与”功能的总线电路(I2C)或者是电平不匹配的场合(低电平为0V,高电平为高阻状态,需要外接上拉电阻)。
推挽复用输出
开漏复用输出
void GPIO_SetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //输出高电平
void GPIO_ResetBits(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); //输出低电平
GPIO输入模式:
uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin) //读取对应Pin电平
具体参考STM32F1参考手册中8.1.11章节 外设的GPIO配置.
具体参考STM32F1参考手册中8.3章节 复用功能I/O和调试配置(AFIO)
复用功能I/O和调试配置(AFIO) 为了优化64脚或100脚封装的外设数目,可以把一些复用功能重新映射到其他引脚上。设置复用重映射和调试I/O配置寄存器(AFIO_MAPR)实现引脚的重新映射。这时,复用功能不再映射到它们的原始分配上。
void GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState);
需要注意的是,只有使用了AFIO的事件控制寄存器(AFIO_EVCR)、AFIO的重映射功能(AFIO_MAPR)以及外部中断(AFIO_EXTICRx)控制寄存器才需要开启AFIO的时钟。
//@param p: GPIOx
//@param i: GPIO_Pin_x
#define digitalHi(p,i) {p->BSRR=i;} //输出为高电平
//@param p: GPIOx
//@param i: GPIO_Pin_x
#define digitalLo(p,i) {p->BRR=i;} //输出低电平
//@param p: GPIOx
//@param i: GPIO_Pin_x
#define digitalToggle(p,i) {p->ODR ^=i;} //输出反转状态
GPIO硬件相关宏定义,bsp_gpio.h
#ifndef __BSP_GPIO_H
#define __BSP_GPIO_H
#include "stm32f10x.h"
#define BSP_GPIO_LED_Clk RCC_APB2Periph_GPIOB
#define BSP_GPIO_LED_CLK_Cmd RCC_APB2PeriphClockCmd
#define BSP_GPIO_LED_R_Port GPIOB
#define BSP_GPIO_LED_R_Pin GPIO_Pin_5
#define BSP_GPIO_LED_G_PORT GPIOB
#define BSP_GPIO_LED_G_PIN GPIO_Pin_0
#define BSP_GPIO_LED_B_PORT GPIOB
#define BSP_GPIO_LED_B_PIN GPIO_Pin_1
#define BSP_GPIO_KEY_CLK RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOC
#define BSP_GPIO_KEY_CLK_Cmd RCC_APB2PeriphClockCmd
#define BSP_GPIO_KEY1_Port GPIOA
#define BSP_GPIO_KEY1_Pin GPIO_Pin_0
#define BSP_GPIO_KEY2_Port GPIOC
#define BSP_GPIO_KEY2_Pin GPIO_Pin_13
#define KEY_PRESS 1
#define KEY_UP 0
#endif /* __BSP_GPIO_H */
注:LED低电平亮,高电平灭。按键按下为高电平,释放为低电平。
GPIO模块配置,bsp_gpio.c
static void BSP_GPIO_KEY_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
BSP_GPIO_KEY_CLK_Cmd(BSP_GPIO_KEY_CLK,ENABLE);
GPIO_InitStructure.GPIO_Pin = BSP_GPIO_KEY1_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(BSP_GPIO_KEY1_Port,&GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = BSP_GPIO_KEY2_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_Init(BSP_GPIO_KEY2_Port,&GPIO_InitStructure);
}
static void BSP_GPIO_LED_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
BSP_GPIO_LED_CLK_Cmd(BSP_GPIO_LED_Clk,ENABLE);
GPIO_InitStructure.GPIO_Pin = BSP_GPIO_LED_R_Pin;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(BSP_GPIO_LED_R_Port,&GPIO_InitStructure);
}
主函数,main.c
uint8_t KEY_Scan(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)
{
uint8_t key_val = 0;
if(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == KEY_PRESS)
{
while(GPIO_ReadInputDataBit(GPIOx, GPIO_Pin) == KEY_PRESS);
key_val = KEY_PRESS;
}
else
key_val = KEY_UP;
return key_val;
}
int main(void)
{
BSP_GPIO_Init();
while(1)
{
if(GPIO_KEY_Scan(GPIO_KEY2_PORT,GPIO_KEY2_PIN) == KEY_PRESS)
BSP_GPIO_LED_R_Port->ODR ^=BSP_GPIO_LED_R_Pin;
}
}
按键采用硬件消抖,所以不需要在软件中进行延时处理。
本人能力有限,如果你有好的想法,还望不吝赐教!