1,概述
通用型之输入输出(General-purpose input/output,通常称为GPIO),GPIO管理功能提供GPIO控制寄存器,实现软件对 GPIO 属性的配置,使用户能够方便地操作 GPIO。每个GPIO可以配置为输入、输出和可选功能三种模式。在每个模式下(除模拟可选功能),提供设置上拉,下拉,浮空三种端口状态,此外GPIO还提供中断功能,可以配置为上升沿触发,下降沿触发或者高电平/低电平触发。
2,API参考
2.1 重要结构体、枚举介绍
2.1.1GPIO配置结构体
- 用于设置GPIO工作模式、电平以及是否上拉
struct HAL_IOMUX_PIN_FUNCTION_MAP {
enum HAL_IOMUX_PIN_T pin;
enum HAL_IOMUX_FUNCTION_T function;
enum HAL_IOMUX_PIN_VOLTAGE_DOMAINS_T volt;
enum HAL_IOMUX_PIN_PULL_SELECT_T pull_sel;
};
2.1.2 GPIO输入输出枚举
enum HAL_GPIO_DIR_T { HAL_GPIO_DIR_IN = 0, //GPIO_IN HAL_GPIO_DIR_OUT = 1, //GPIO_OUT };
2.1.3 GPIO中断类型枚举
enum HAL_GPIO_IRQ_TYPE_T { HAL_GPIO_IRQ_TYPE_LEVEL_SENSITIVE = 0, //电平触发 HAL_GPIO_IRQ_TYPE_EDGE_SENSITIVE, //边沿触发 };
2.1.4 GPIO中断触发电平枚举
enum HAL_GPIO_IRQ_POLARITY_T { HAL_GPIO_IRQ_POLARITY_LOW_FALLING = 0, //低电平/下降沿 HAL_GPIO_IRQ_POLARITY_HIGH_RISING, //高电平/上升沿 };
2.1.5 GPIO中断函数指针
函数参数:
pin :GPIO接口枚举
typedef void (* HAL_GPIO_PIN_IRQ_HANDLER)(enum HAL_GPIO_PIN_T pin);
2.1.6 GPIO中断配置结构体
在配置GPIO中断时,所有中断相关参数都包含在此结构体中
struct HAL_GPIO_IRQ_CFG_T { uint8_t irq_enable:1; //中断使能 uint8_t irq_debounce:1; //GPIO消抖使能 enum HAL_GPIO_IRQ_TYPE_T irq_type; //GPIO中断类型 enum HAL_GPIO_IRQ_POLARITY_T irq_polarity; //GPIO中断电平 HAL_GPIO_PIN_IRQ_HANDLER irq_handler; //中断处理函数 };
2.2 主要函数介绍
2.2.1 GPIO初始化
函数原型:
uint32_t hal_iomux_init(const struct HAL_IOMUX_PIN_FUNCTION_MAP *map, uint32_t count)
功能描述:设置GPIO工作模式
函数参数:
函数原型:
void hal_gpio_pin_set_dir(enum HAL_GPIO_PIN_T pin, enum HAL_GPIO_DIR_T dir, uint8_t val_for_out);
功能描述:设置指定GPIO为输入或者输出模式,如为输出模式则规定初始电平
函数参数:
函数原型:
void hal_gpio_pin_set(enum HAL_GPIO_PIN_T pin);
功能描述:将指定GPIO的电平置高
函数参数:
函数原型:
void hal_gpio_pin_clr(enum HAL_GPIO_PIN_T pin);
功能描述:将指定GPIO的电平置低
函数参数:
函数原型:
enum HAL_GPIO_DIR_T hal_gpio_pin_get_dir(enum HAL_GPIO_PIN_T pin);
功能描述:获取指定GPIO当前为输入或是输出模式
- 函数参数:
- pin:需要判断的GPIO
返回值:
函数原型:
uint8_t hal_gpio_pin_get_val(enum HAL_GPIO_PIN_T pin);
功能描述:获取指定GPIO当前电平
- 函数参数:
- pin:指定GPIO
返回值:
函数原型:
uint8_t hal_gpio_setup_irq(enum HAL_GPIO_PIN_T pin, const struct HAL_GPIO_IRQ_CFG_T *cfg);
功能描述:将设置好的GPIO中断参数配置给指定GPIO
- 函数参数:
- pin:指定GPIO
- *cfg:GPIO中断配置结构体指针
返回值:
-
3.2 初始化GPIO
首先引用HAL_IOMUX_PIN_FUNCTION_MAP结构体来配置IO以及模式
struct HAL_IOMUX_PIN_FUNCTION_MAP cfg_hw_gpio; cfg_hw_gpio.pin = gpio->port; //端口选择 cfg_hw_gpio.function = HAL_IOMUX_FUNC_AS_GPIO; //功能选择,选择GPIO功能 cfg_hw_gpio.volt = HAL_IOMUX_PIN_VOLTAGE_VIO; //电平选择,VIO:高,MEM:低 cfg_hw_gpio.pull_sel = HAL_IOMUX_PIN_NOPULL; //选择是否上拉
也可以一次性配置多个IO
struct HAL_IOMUX_PIN_FUNCTION_MAP pinmux[] = { {HAL_GPIO_PIN_P0_2, HAL_IOMUX_FUNC_AS_GPIO, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL}, {HAL_GPIO_PIN_P0_4, HAL_IOMUX_FUNC_AS_GPIO, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL}, {HAL_GPIO_PIN_P0_5, HAL_IOMUX_FUNC_AS_GPIO, HAL_IOMUX_PIN_VOLTAGE_MEM, HAL_IOMUX_PIN_NOPULL}, };
结构体配置完成后使用 hal_iomux_init ()来初始化IO
hal_iomux_init(pinmux, ARRAY_SIZE(pinmux));
-
3.3 API使用
在初始化GPIO后便可以使用前文介绍过的各个函数
初始化后的GPIO还没有设置输入输出模式,需要手动设置
hal_gpio_pin_set_dir(HAL_GPIO_PIN_P0_2, HAL_GPIO_DIR_OUT, 0); //配置P0_2口为输出口,初始电平为低电平 hal_gpio_pin_set_dir(HAL_GPIO_PIN_P0_4, HAL_GPIO_DIR_IN, 0); //配置P0_4口为输入口 hal_gpio_pin_set_dir(HAL_GPIO_PIN_P0_5, HAL_GPIO_DIR_IN, 0); //配置P0_5口为输入口
配置好输入或输出后可以使用相应的函数
static void gpio_output_test(void) { printf("set gpio %d high\r\n", HAL_GPIO_PIN_P0_2); hal_gpio_pin_set(HAL_GPIO_PIN_P0_2); // set high mdelay(1000); //delay 1000ms printf("set gpio %d low\r\n", HAL_GPIO_PIN_P0_2); hal_gpio_pin_clr(HAL_GPIO_PIN_P0_2); // set low }
static void gpio_input_test(void) { uint8_t val = 0; while (1) { uint8_t tmp = hal_gpio_pin_get_val(HAL_GPIO_PIN_P0_4); //读取P0_4的电平 if (tmp != val) { printf("gpio %d toggle from %d to %d\r\n", HAL_GPIO_PIN_P0_4, val, tmp); val = tmp; } mdelay(100); } }
3.4 GPIO中断使用
要使用GPIO中断首先要对中断结构体HAL_GPIO_IRQ_CFG_T进行配置
struct HAL_GPIO_IRQ_CFG_T cfg; cfg.irq_debounce = 1; cfg.irq_enable = 1; cfg.irq_type = HAL_GPIO_IRQ_TYPE_EDGE_SENSITIVE; // 边沿触发 cfg.irq_handler = gpio_irq_handler; //中断回调函数 cfg.irq_polarity = HAL_GPIO_IRQ_POLARITY_HIGH_RISING; // 上升沿触发
在结构体中已经引用了回调函数,因此下一步便是设置回调函数
static void gpio_irq_handler(enum HAL_GPIO_PIN_T pin) { uint8_t val = hal_gpio_pin_get_val(pin); printf("irq: gpio %d, val %d\r\n", pin, val); }
最后再注册中断回调函数
hal_gpio_setup_irq(HAL_GPIO_PIN_P0_5, &cfg); //将回调函数注册给GPIO P0_5
3.5 Demo演示
将前文中使用到的各个例程结合起来可以得到:
void gpio_test(void) { //IO配置 struct HAL_IOMUX_PIN_FUNCTION_MAP pinmux[] = { {HAL_GPIO_PIN_P0_2, HAL_IOMUX_FUNC_AS_GPIO, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL}, {HAL_GPIO_PIN_P0_4, HAL_IOMUX_FUNC_AS_GPIO, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_NOPULL}, {HAL_GPIO_PIN_P0_5, HAL_IOMUX_FUNC_AS_GPIO, HAL_IOMUX_PIN_VOLTAGE_MEM, HAL_IOMUX_PIN_NOPULL}, }; hal_iomux_init(pinmux, ARRAY_SIZE(pinmux)); //IO初始化 //IO输入输出设置 hal_gpio_pin_set_dir(HAL_GPIO_PIN_P0_2, HAL_GPIO_DIR_OUT, 0); hal_gpio_pin_set_dir(HAL_GPIO_PIN_P0_4, HAL_GPIO_DIR_IN, 0); hal_gpio_pin_set_dir(HAL_GPIO_PIN_P0_5, HAL_GPIO_DIR_IN, 0); //IRQ cfg配置 struct HAL_GPIO_IRQ_CFG_T cfg; cfg.irq_debounce = 1; cfg.irq_enable = 1; cfg.irq_type = HAL_GPIO_IRQ_TYPE_EDGE_SENSITIVE; cfg.irq_handler = gpio_irq_handler; //回调函数 cfg.irq_polarity = HAL_GPIO_IRQ_POLARITY_HIGH_RISING; hal_gpio_setup_irq(HAL_GPIO_PIN_P0_5, &cfg); //注册 gpio_output_test(); //见前文 gpio_input_test(); //见前文 }
此例程配置了P0_2、P0_4、P0_5三个GPIO,02设置为输出口,初始低电平,04、05设置为输入口
- 02口用于输出电平测试,04口用于输入电平测试,05口用于中断测试
- 02口输出高电平后1s输出低电平,并串口打印信息
- 将02口与04口连接,04口输入高电平时与初始值(0)不同,串口打印信息与当前电平
- 将02口与05口连接,电平上升沿触发中断,串口打印相应信息
注:在wifi_app/app/bes_test中可查看源码