首页 > 其他分享 >[单片机框架][bsp层][AT32F415][bsp_gpio] GPIO配置和使用

[单片机框架][bsp层][AT32F415][bsp_gpio] GPIO配置和使用

时间:2022-10-31 18:02:28浏览次数:55  
标签:AT32F415 pin gpiox bsp 单片机 init GPIO gpio


6.1 简介
GPIO 接口包括 5 组通用输入/输出端口。
每个 GPIO 组提供 16 个通用输入/输出引脚;每个 GPIO 端口都有相关的控制和配置寄存器来满足特定的功能,GPIO 引脚上的外部中断都有相关的控制和配置寄存器在外部中断控制器,参考章节 6.中断和事件。
GPIO 端口和其他复用功能同用一个引脚,在特定的封装下获得最大的灵活性。GPIO 引脚可以用于复用功能引脚,通过配置相关的寄存器用作复用功能输入和复用功能输出。
每个 GPIO 引脚可通过软件配置为输出(推挽或开漏),输入(上拉,下拉或无上拉/下拉)或作为外设复用功能。大部分的 GPIO 引脚都有数字或模拟的复用功能。所有的 GPIO 都具备大电流驱动能力。

6.2 主要特征

  • 输入/输出方向控制
  • 每个引脚都有弱上拉/下拉功能
  • 推挽/开漏输出使能控制
  • 输出置位/复位控制
  • 可编程触发沿的外部中断–在外部中断配置寄存器中
  • 模拟输入/模拟输出配置
  • 复用功能输入/输出配置
  • 端口配置锁定

6.3 功能描述
6.3.1 GPIO引脚配置
每个 GPIO 端口有两个 32 位配置寄存器(GPIOx_CTRLL,GPIOx_CTRLH) ,两个 32 位数据寄存器(GPIOx_IPTDT 和 GPIOx_OPTDT) ,一个 32 位置位/复位寄存器(GPIOx_BSRE) ,一个 16 位复位寄存器(GPIOx_BRE)和一个 32 位锁定寄存器(GPIOx_LOCK) 。
根据数据手册中列出的每个 I/O 端口的特定硬件特征,GPIO 端口的每个位可以由软件分别配置成多种模式。

敲重点

[单片机框架][bsp层][AT32F415][bsp_gpio] GPIO配置和使用_初始化


使用PB3引脚时,一定要重映射,因为这个引脚内部有上拉电阻,会导致引脚无法完全拉低。

RCC_APB2PeriphClockCmd(RCC_APB2PERIPH_AFIO, ENABLE);
// 将GPIOB-3,重映射为普通脚
GPIO_PinsRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);

bsp_gpio文件

/********************************************************************************
* @file bsp_gpio.c
* @author jianqiang.xue
* @version V1.0.0
* @date 2021-09-30
* @brief gpio初始化
********************************************************************************/

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>

#include "RTE_Components.h"
#include CMSIS_device_header

#include "bsp_exti.h"
#include "bsp_gpio.h"

/* Private Includes ----------------------------------------------------------*/
#include "business_gpio.h"
#include "business_function.h"

/* Private Variables ---------------------------------------------------------*/
/* Public Function Prototypes ------------------------------------------------*/
/**
* @brief [反初始化] 关闭指定引脚功能(恢复为浮空输入)
* @param *gpiox: gpio组号(GPIOA/GPIOB/GPIOC/GPIOD等等)
* @param pin: 引脚号
*/
void bsp_gpio_deinit(void *gpiox, uint8_t pin)
{
bsp_gpio_init_input(gpiox, (1 << pin), BSP_GPIO_PIN_NOPULL);
}

/**
* @brief [初始化] 引脚设置为输出模式
* @param *gpiox: gpio组号(GPIOA/GPIOB/GPIOC/GPIOD等等)
* @param pin: 引脚号
* @param out_mode: BSP_GPIO_PIN_OUT_OD 开漏输出, BSP_GPIO_PIN_OUT_PP 推免输出, BSP_GPIO_PIN_AF_OD 复用开漏, BSP_GPIO_PIN_AF_PP 复用推免
*/
void bsp_gpio_init_output(void *gpiox, uint8_t pin, bsp_gpio_pin_out_t out_mode)
{
volatile GPIO_InitType gpio_init_struct;

gpio_init_struct.GPIO_Pins = (1 << pin);
gpio_init_struct.GPIO_MaxSpeed = GPIO_MaxSpeed_10MHz;
if (out_mode == BSP_GPIO_PIN_OUT_OD)
{
gpio_init_struct.GPIO_Mode = GPIO_Mode_OUT_OD;
}
else if (out_mode == BSP_GPIO_PIN_OUT_PP)
{
gpio_init_struct.GPIO_Mode = GPIO_Mode_OUT_PP;
}
else if (out_mode == BSP_GPIO_PIN_AF_OD)
{
gpio_init_struct.GPIO_Mode = GPIO_Mode_AF_OD;
}
else if (out_mode == BSP_GPIO_PIN_AF_PP)
{
gpio_init_struct.GPIO_Mode = GPIO_Mode_AF_PP;
}
GPIO_Init(gpiox, (GPIO_InitType *)&gpio_init_struct);
}

/**
* @brief [初始化] 引脚设置为输入模式
* @param *gpiox: gpio组号(GPIOA/GPIOB/GPIOC/GPIOD等等)
* @param pin: 引脚号
* @param pull: BSP_GPIO_PIN_NOPULL 无上下拉, BSP_GPIO_PIN_PULLUP 上拉输入, BSP_GPIO_PIN_PULLDOWN 下拉输入
*/
void bsp_gpio_init_input(void *gpiox, uint8_t pin, bsp_gpio_pin_pull_t pull)
{
volatile GPIO_InitType gpio_init_struct;

gpio_init_struct.GPIO_Pins = (1 << pin);
gpio_init_struct.GPIO_MaxSpeed = GPIO_MaxSpeed_10MHz;
if (pull == BSP_GPIO_PIN_NOPULL)
{
gpio_init_struct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
}
else if (pull == BSP_GPIO_PIN_PULLUP)
{
gpio_init_struct.GPIO_Mode = GPIO_Mode_IN_PU;
}
else if (pull == BSP_GPIO_PIN_PULLDOWN)
{
gpio_init_struct.GPIO_Mode = GPIO_Mode_IN_PD;
}
GPIO_Init(gpiox, (GPIO_InitType *)&gpio_init_struct);
}

static uint8_t get_exti_event(bsp_gpio_exti_int_event_t exti_type)
{
if (BSP_GPIO_EXTI_INT_LOWFALL == exti_type)
{
return EXTI_Trigger_Falling;
}
else if (BSP_GPIO_EXTI_INT_HIGHRISE == exti_type)
{
return EXTI_Trigger_Rising;
}
else if (BSP_GPIO_EXTI_INT_FALLRISE == exti_type)
{
return EXTI_Trigger_Rising_Falling;
}
else
{
return EXTI_Trigger_Rising_Falling;
}
}

/**
* @brief [初始化] 引脚设置为[输入+中断]模式
* @param *gpiox: gpio组号(GPIOA/GPIOB/GPIOC/GPIOD等等)
* @param pin: 引脚号
* @param irqn: 中断号(在typedef enum IRQn中,例如:USART1_IRQn)
* @param exti_type: BSP_GPIO_EXTI_INT_LEVEL 电平触发, BSP_GPIO_EXTI_INT_EDGE 边沿触发
* @param exti_event: BSP_GPIO_EXTI_INT_LOWFALL 低电平触发(下降沿), BSP_GPIO_EXTI_INT_HIGHRISE 高电平触发(上降沿), BSP_GPIO_EXTI_INT_FALLRISE 高低电平触发或任意电平变化
* @param pull: BSP_GPIO_PIN_NOPULL 无上下拉, BSP_GPIO_PIN_PULLUP 上拉输入, BSP_GPIO_PIN_PULLDOWN 下拉输入
*/
void bsp_gpio_init_input_exit(void *gpiox, uint8_t pin, uint8_t irqn,
bsp_gpio_exti_int_type_t exti_type,
bsp_gpio_exti_int_event_t exti_event,
bsp_gpio_pin_pull_t pull)
{
EXTI_InitType EXTI_InitStructure;
GPIO_Type* GPIOx = gpiox;
uint8_t PortSource = 0;
bsp_gpio_init_input(gpiox, (1 << pin), pull);
//<Connect EXTIx Line to Pxx pin
if (GPIOx == GPIOA)
{
PortSource = GPIO_PortSourceGPIOA;
}
else if (GPIOx == GPIOB)
{
PortSource = GPIO_PortSourceGPIOB;
}
else if (GPIOx == GPIOC)
{
PortSource = GPIO_PortSourceGPIOC;
}
else if (GPIOx == GPIOD)
{
PortSource = GPIO_PortSourceGPIOD;
}
GPIO_EXTILineConfig(PortSource, pin);
/* Configure Button pin as input with External interrupt */
EXTI_InitStructure.EXTI_Line = (1 << pin);
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = (EXTITrigger_Type)get_exti_event(exti_event);
EXTI_InitStructure.EXTI_LineEnable = ENABLE;
EXTI_Init(&EXTI_InitStructure);

bsp_exit_clear_flag(gpiox, pin);
/* Enable and set Button EXTI Interrupt to the lowest priority */
bsp_exit_set(irqn, pin % 4);
}

/**
* @brief 设置引脚电平状态
* @param *gpiox: gpio组号(GPIOA/GPIOB/GPIOC/GPIOD等等)
* @param pin: 引脚号
* @param state: BSP_GPIO_PIN_RESET 低电平, BSP_GPIO_PIN_SET 高电平
*/
void bsp_gpio_set_pin(void *gpiox, uint8_t pin, bsp_gpio_pin_state_t state)
{
GPIO_WriteBit(gpiox, (1 << pin), (BitState)state);
}

/**
* @brief 翻转引脚电平状态
* @param *gpiox: gpio组号(GPIOA/GPIOB/GPIOC/GPIOD等等)
* @param pin: 引脚号
*/
void bsp_gpio_set_toggle(void *gpiox, uint8_t pin)
{
bsp_gpio_set_pin(gpiox, pin, (bsp_gpio_pin_state_t)!bsp_gpio_get_state(gpiox, pin));
}

/**
* @brief 得到指定gpio状态
* @param *gpiox: gpio组号(GPIOA/GPIOB/GPIOC/GPIOD等等)
* @param pin: 引脚号
* @retval 0 -- 低电平, 1 -- 高电平
*/
bool bsp_gpio_get_state(void *gpiox, uint8_t pin)
{
return (bool)GPIO_ReadInputDataBit(gpiox, (1 << pin));
}

/**
* @brief 设置gpio时钟
* @param aphn: AHB外围x (High Speed APB)外围时钟。APB == 0 APB2 == 1
* @param periph: 时钟号
*/
void bsp_gpio_set_clk(bool aphn, uint32_t periph, bool state)
{
if (aphn == 0)
{
RCC_AHBPeriphClockCmd(periph, state);
}
else if(aphn == 1)
{
RCC_APB2PeriphClockCmd(periph, state);
}
}

/**
* @brief 将指定引脚复用为ADC引脚(复用模拟输入)
* @param *gpiox: gpio组号(GPIOA/GPIOB/GPIOC/GPIOD等等)
* @param pin: 引脚号
*/
void bsp_gpio_init_adc(void *gpiox, uint8_t pin)
{
GPIO_InitType gpio_init_struct;

gpio_init_struct.GPIO_Pins = (1 << pin);
gpio_init_struct.GPIO_MaxSpeed = GPIO_MaxSpeed_10MHz;
gpio_init_struct.GPIO_Mode = GPIO_Mode_IN_ANALOG;
GPIO_Init(gpiox, (GPIO_InitType *)&gpio_init_struct);
}

/**
* @brief 初始化i2c引脚
* @param *gpiox: gpio组号(GPIOA/GPIOB/GPIOC/GPIOD等等)
* @param pin: 引脚号
* @param arf: [复用脚 0--SCL 1--SDA] (0代表初始化SCL脚,1同理初始化SDA脚)
*/
void bsp_gpio_init_i2c(void *gpiox, uint8_t pin, uint8_t arf)
{
GPIO_InitType gpio_init_struct;

gpio_init_struct.GPIO_Pins = (1 << pin);
gpio_init_struct.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
gpio_init_struct.GPIO_Mode = GPIO_Mode_AF_OD;
GPIO_Init(gpiox, (GPIO_InitType *)&gpio_init_struct);
}

/**
* @brief 初始化uart引脚
* @param *gpiox: gpio组号(GPIOA/GPIOB/GPIOC/GPIOD等等)
* @param pin: 引脚号
* @param arf: [复用脚 0--TX 1--RX] (0代表初始化TX脚,1同理初始化RX脚)
*/
void bsp_gpio_init_uart(void *gpiox, uint8_t pin, uint8_t arf)
{
volatile GPIO_InitType gpio_init_struct;
gpio_init_struct.GPIO_Pins = (1 << pin);
gpio_init_struct.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
if (arf == 0)
{
gpio_init_struct.GPIO_Mode = GPIO_Mode_AF_PP;
}
else
{
gpio_init_struct.GPIO_Mode = GPIO_Mode_IN_FLOATING;
}
GPIO_Init(gpiox, (GPIO_InitType *)&gpio_init_struct);
}

void bsp_gpio_init_tim(void *gpiox, uint8_t pin, uint8_t arf)
{
GPIO_InitType gpio_init_struct;
gpio_init_struct.GPIO_Pins = (1 << pin);
gpio_init_struct.GPIO_MaxSpeed = GPIO_MaxSpeed_50MHz;
gpio_init_struct.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(gpiox, (GPIO_InitType *)&gpio_init_struct);
}
/********************************************************************************
* @file bsp_gpio.h
* @author jianqiang.xue
* @version V1.0.0
* @date 2021-04-09
* @brief GPIO控制
********************************************************************************/

#ifndef __BSP_GPIO_H
#define __BSP_GPIO_H

/* Includes ------------------------------------------------------------------*/
#include <stdint.h>
#include <stdbool.h>

/* Public Enum ---------------------------------------------------------------*/
/**
* @brief GPIO Bit SET and Bit RESET enumeration
*/
typedef enum
{
BSP_GPIO_PIN_RESET = 0U,
BSP_GPIO_PIN_SET
} bsp_gpio_pin_state_t;

typedef enum
{
BSP_GPIO_PIN_NOPULL = 0U,
BSP_GPIO_PIN_PULLUP,
BSP_GPIO_PIN_PULLDOWN
} bsp_gpio_pin_pull_t;

typedef enum
{
BSP_GPIO_PIN_OUT_OD = 0U,
BSP_GPIO_PIN_OUT_PP,
BSP_GPIO_PIN_AF_OD,
BSP_GPIO_PIN_AF_PP
} bsp_gpio_pin_out_t;

typedef enum
{
BSP_GPIO_EXTI_INT_LEVEL = 0U, // 电平触发
BSP_GPIO_EXTI_INT_EDGE, // 边沿触发
} bsp_gpio_exti_int_type_t;

typedef enum
{
BSP_GPIO_EXTI_INT_LOWFALL = 0U, // 低电平触发(下降沿)
BSP_GPIO_EXTI_INT_HIGHRISE, // 高电平触发(上降沿)
BSP_GPIO_EXTI_INT_FALLRISE // 高低电平触发或任意电平变化
} bsp_gpio_exti_int_event_t;

/* Public Struct -------------------------------------------------------------*/
typedef struct
{
void* port; // 端点号
uint32_t pin; // 引脚号
uint32_t periph; // GPIO外设时钟 比如 RCC_APB2PERIPH_GPIOA
bool level; // 电平有效状态,比如低电平点亮led,则level设置0,反之。
bsp_gpio_pin_pull_t pull; // 内部电阻
bool is_exti; // 是否开启中断
uint8_t irqn; // 中断号 比如 EXT0_IRQn
bsp_gpio_exti_int_type_t exti_type; // 中断触发类型
bsp_gpio_exti_int_event_t exti_event; // 中断触发事件
} bsp_gpio_t;
/* Public Function Prototypes ------------------------------------------------*/

// 常规引脚初始化
void bsp_gpio_set_clk(bool aphn, uint32_t periph, bool state);
void bsp_gpio_deinit(void *gpiox, uint8_t pin);
void bsp_gpio_init_output(void *gpiox, uint8_t pin, bsp_gpio_pin_out_t out_mode);
void bsp_gpio_init_input(void *gpiox, uint8_t pin, bsp_gpio_pin_pull_t pull);
void bsp_gpio_init_input_exit(void *gpiox, uint8_t pin, uint8_t irqn, bsp_gpio_exti_int_type_t exti_type, bsp_gpio_exti_int_event_t exti_event, bsp_gpio_pin_pull_t pull);

// 外设引脚初始化

void bsp_gpio_init_adc(void *gpiox, uint8_t pin);
void bsp_gpio_init_i2c(void *gpiox, uint8_t pin, uint8_t arf);
void bsp_gpio_init_uart(void *gpiox, uint8_t pin, uint8_t arf);
void bsp_gpio_init_tim(void *gpiox, uint8_t pin, uint8_t arf);

// 引脚控制和状态获取

void bsp_gpio_set_pin(void *gpiox, uint8_t pin, bsp_gpio_pin_state_t state);
void bsp_gpio_set_toggle(void *gpiox, uint8_t pin);
bool bsp_gpio_get_state(void *gpiox, uint8_t pin);

#endif


标签:AT32F415,pin,gpiox,bsp,单片机,init,GPIO,gpio
From: https://blog.51cto.com/xuejianqiang/5810734

相关文章