打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033

LiSun

打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

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 <string.h>

#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__

posted on 2022-09-09 09:13  xuejianqiang  阅读(25)  评论(0编辑  收藏  举报  来源
打造一个通用性MCU架构,支持CX32/AT32/NRF51/NRF52等。 OS支持RTX4/RTX5/FreeRtos。 采用VsCode+GCC组合,VsCode+KEIL5,超强开发方式。 QQ群:524408033