GPIO(General purpose input/output)即通用型 I/O,AFIO(Alternate-function input/output)即复用功能 I/O。
芯片最多支持 65 个 GPIO,共被分为 5 组(GPIOA/GPIOB/GPIOC/GPIOD/GPIOE),GPIOA、GPIOB、GPIOC
每组 16 个端口,GPIOD 共 8 个,GPIOE 共 9 个。GPIO 端口和其他的复用外设共用引脚,用户可以根据需
求灵活配置。每个 GPIO 引脚都可以独立配置成输出、输入或复用的外设功能端口。除了模拟功能引脚外,
其他的 GPIO 引脚都有大电流通过能力。
GPIO 端口可由软件分别配置成以下模式:
■ 输入浮空
■ 输入上拉
■ 输入下拉
■ 模拟功能
■ 开漏输出
■ 推挽式输出
■ 推挽式复用功能
■ 开漏复用功能
每个 I/O 端口位可以任意编程,但必须按照 32 位字访问 I/O 端口寄存器(不允许 16 位半字或 8 位字节访
问)。下图给出了一个 I/O 端口的基本结构。
IO 模式配置
IO 的模式控制由配置寄存器 GPIOx_PL_CFG,GPIOx_PH_CFG(x=A,B,C,D,E,F,G)以及输出寄存器
GPIOx_POD 来设置,不同的操作模式下的配置如下表所示:
表 6-1 IO 模式和配置关系
输入模式 当 I/O 端口配置为输入模式时:
■ 出现在 I/O 脚上的数据在每个 APB2 时钟被采样到输入数据寄存器状态
■ 通过对数据寄存器的读访问得到 I/O
■ 输出缓冲器被禁止
■ 施密特触发输入被激活
■ 根据输入配置(上拉,下拉或浮动)的不同,弱上拉和下拉电阻被连接
输出模式 当 I/O 端口配置为输出时: 施密特触发输入被激活
弱上拉和下拉电阻被禁止
输出缓冲器被激活
开漏模式: 输出寄存器上的’0’激活 N-MOS,引脚输出低电平
输出寄存器上的’1’端口置于高阻状态(P-MOS 从不被激活) 推挽模式: 输出寄存器上的’0’激活 N-MOS,引脚输出低电平
输出寄存器上的’1’激活 P-MOS,引脚输出高电平
出现在 I/O 脚上的数据在每个 APB2 时钟被采样到输入数据寄存器
对输入数据寄存器的读访问可得到 I/O 状态
对输出数据寄存器的读访问得到最后一次写的值
#include
#include "n32g4fr.h"
#include "errorno.h"
#include "bsp_gpio.h"
#include "log.h"
typedef struct {
void *arg;
bsp_gpio_cb_t cbk;
} bsp_gpio_hdl_t;
typedef void (*bsp_gpio_set_level_t)(GPIO_Module* GPIOx, uint16_t Pin);
bsp_gpio_hdl_t g_gpio_hdl[BSP_GPIO_NUM];
bsp_gpio_set_level_t bsp_gpio_set_level[2] = {GPIO_ResetBits, GPIO_SetBits};
typedef struct
{
uint32_t rcc;
GPIO_Module *gpio;
uint16_t pin;
GPIO_ModeType mode;
uint8_t port_src;
uint8_t pin_src;
IRQn_Type irq;
uint8_t preemption_priority;
uint8_t sub_priority;
uint32_t exti_line;
EXTI_TriggerType trigger;
} bsp_gpio_cfg_t;
bsp_gpio_cfg_t pa1_cfg =
{
.rcc = RCC_APB2_PERIPH_GPIOA,
.gpio = GPIOA,
.pin = GPIO_PIN_1,
.mode = GPIO_Mode_IPU,
.port_src = GPIOA_PORT_SOURCE,
.pin_src = GPIO_PIN_SOURCE1,
.irq = EXTI1_IRQn,
.preemption_priority = 4,
.sub_priority = 0,
.exti_line = EXTI_LINE1,
.trigger = EXTI_Trigger_Falling,
};
bsp_gpio_cfg_t pa5_cfg =
{
.rcc = RCC_APB2_PERIPH_GPIOA,
.gpio = GPIOA,
.pin = GPIO_PIN_5,
.mode = GPIO_Mode_IN_FLOATING,
.port_src = GPIOA_PORT_SOURCE,
.pin_src = GPIO_PIN_SOURCE5,
.irq = EXTI9_5_IRQn,
.preemption_priority = 8,
.sub_priority = 0,
.exti_line = EXTI_LINE5,
.trigger = EXTI_Trigger_Rising,
};
bsp_gpio_cfg_t pa0_cfg =
{
.rcc = RCC_APB2_PERIPH_GPIOA,
.gpio = GPIOA,
.pin = GPIO_PIN_0,
.mode = GPIO_Mode_IPU,
.port_src = GPIOA_PORT_SOURCE,
.pin_src = GPIO_PIN_SOURCE0,
.irq = EXTI0_IRQn,
.preemption_priority = 9,
.sub_priority = 0,
.exti_line = EXTI_LINE0,
.trigger = EXTI_Trigger_Rising_Falling,
};
bsp_gpio_cfg_t pa8_cfg =
{
.rcc = RCC_APB2_PERIPH_GPIOA,
.gpio = GPIOA,
.pin = GPIO_PIN_8,
.mode = GPIO_Mode_Out_PP,
};
bsp_gpio_cfg_t pc15_cfg =
{
.rcc = RCC_APB2_PERIPH_GPIOC,
.gpio = GPIOC,
.pin = GPIO_PIN_15,
.mode = GPIO_Mode_Out_PP,
};
bsp_gpio_cfg_t pb12_cfg =
{
.rcc = RCC_APB2_PERIPH_GPIOB,
.gpio = GPIOB,
.pin = GPIO_PIN_12,
.mode = GPIO_Mode_Out_PP,
};
bsp_gpio_cfg_t pb14_cfg =
{
.rcc = RCC_APB2_PERIPH_GPIOB,
.gpio = GPIOB,
.pin = GPIO_PIN_14,
.mode = GPIO_Mode_Out_PP,
};
uint8_t bsp_gpio_read(bsp_gpio_t gpio)
{
if (gpio == BSP_GPIO_0_KEY_POWER)
{
return GPIO_ReadInputDataBit(GPIOA, GPIO_PIN_1);
}
else if (gpio == BSP_GPIO_1_HALL)
{
return GPIO_ReadInputDataBit(GPIOA, GPIO_PIN_5);
}
else if (gpio == BSP_GPIO_2_USB)
{
return GPIO_ReadInputDataBit(GPIOA, GPIO_PIN_0);
}
else if (gpio == BSP_GPIO_3_WCHG_EN)
{
return GPIO_ReadInputDataBit(GPIOA, GPIO_PIN_8);
}
else if (gpio == BSP_GPIO_4_WCHG_SLEEP_EN)
{
return GPIO_ReadInputDataBit(GPIOC, GPIO_PIN_15);
}
else if (gpio == BSP_GPIO_5_CHG_EN)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_PIN_14);
}
else if (gpio == BSP_GPIO_6_IO_VDD)
{
return GPIO_ReadInputDataBit(GPIOB, GPIO_PIN_12);
}
else
{
return RETVAL(E_STATE);
}
}
void bsp_gpio_set(bsp_gpio_t gpio, uint8_t level)
{
if (gpio == BSP_GPIO_2_USB)
{
bsp_gpio_set_level[level](GPIOA, GPIO_PIN_0);
}
else if (gpio == BSP_GPIO_3_WCHG_EN)
{
bsp_gpio_set_level[level](GPIOA, GPIO_PIN_8);
}
else if (gpio == BSP_GPIO_4_WCHG_SLEEP_EN)
{
bsp_gpio_set_level[level](GPIOC, GPIO_PIN_15);
}
else if (gpio == BSP_GPIO_5_CHG_EN)
{
bsp_gpio_set_level[level](GPIOB, GPIO_PIN_14);
}
else if (gpio == BSP_GPIO_6_IO_VDD)
{
bsp_gpio_set_level[level](GPIOB, GPIO_PIN_12);
}
}
int32_t bsp_gpio_register_irq_callback(bsp_gpio_t gpio, bsp_gpio_cb_t cbk, void *arg)
{
if (cbk == NULL)
{
return RETVAL(E_NULL);
}
g_gpio_hdl[gpio].arg = arg;
g_gpio_hdl[gpio].cbk = cbk;
return RETVAL(E_OK);
}
void bsp_gpio_irq_handler(bsp_gpio_t gpio)
{
if (g_gpio_hdl[gpio].cbk)
{
(*g_gpio_hdl[gpio].cbk)(g_gpio_hdl[gpio].arg);
}
}
void bsp_gpio_init(bsp_gpio_t gpio, bsp_gpio_exti_cmd_t cmd)
{
EXTI_InitType EXTI_InitStructure;
NVIC_InitType NVIC_InitStructure;
GPIO_InitType GPIO_InitStructure;
bsp_gpio_cfg_t *cfg = NULL;
if (gpio == BSP_GPIO_0_KEY_POWER)
{
cfg = &pa1_cfg;
}
else if (gpio == BSP_GPIO_1_HALL)
{
cfg = &pa5_cfg;
}
else if (gpio == BSP_GPIO_2_USB)
{
cfg = &pa0_cfg;
}
else if (gpio == BSP_GPIO_3_WCHG_EN)
{
cfg = &pa8_cfg;
}
else if (gpio == BSP_GPIO_4_WCHG_SLEEP_EN)
{
cfg = &pc15_cfg;
}
else if (gpio == BSP_GPIO_5_CHG_EN)
{
cfg = &pb14_cfg;
}
else if (gpio == BSP_GPIO_6_IO_VDD)
{
cfg = &pb12_cfg;
}
RCC_EnableAPB2PeriphClk(cfg->rcc, ENABLE);
GPIO_InitStructure.Pin = cfg->pin;
GPIO_InitStructure.GPIO_Mode = cfg->mode;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitPeripheral(cfg->gpio, &GPIO_InitStructure);
if (cmd == BSP_GPIO_EXTI_ENABLE)
{
GPIO_ConfigEXTILine(cfg->port_src, cfg->pin_src);
NVIC_InitStructure.NVIC_IRQChannel = cfg->irq;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = cfg->preemption_priority;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = cfg->sub_priority;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
EXTI_InitStructure.EXTI_Line = cfg->exti_line;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = cfg->trigger;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_InitPeripheral(&EXTI_InitStructure);
}
}
#ifndef __BSP_GPIO_H__
#define __BSP_GPIO_H__
#include "typedefs.h"
typedef enum
{
BSP_GPIO_0_KEY_POWER = 0,
BSP_GPIO_1_HALL,
BSP_GPIO_2_USB,
BSP_GPIO_3_WCHG_EN,
BSP_GPIO_4_WCHG_SLEEP_EN,
BSP_GPIO_5_CHG_EN,
BSP_GPIO_6_IO_VDD,
BSP_GPIO_NUM,
} bsp_gpio_t;
typedef enum
{
BSP_GPIO_EXTI_DISABLE = 0,
BSP_GPIO_EXTI_ENABLE
} bsp_gpio_exti_cmd_t;
typedef void (*bsp_gpio_cb_t)(void *arg);
void bsp_gpio_init(bsp_gpio_t gpio, bsp_gpio_exti_cmd_t cmd);
int32_t bsp_gpio_register_irq_callback(bsp_gpio_t gpio, bsp_gpio_cb_t cb, void *arg);
void bsp_gpio_irq_handler(bsp_gpio_t gpio);
uint8_t bsp_gpio_read(bsp_gpio_t gpio);
void bsp_gpio_set(bsp_gpio_t gpio, uint8_t level);
#endif // __BSP_GPIO_H__