对于不同底层驱动的GPIO操作实现,统一封装成本文所述hal接口。上层使用相关功能时,统一调用hal层接口,以保证app的通用性。 hal相关头文件位于目录:include/aos/hal。hal相关实现位于具体的mcu目录下,如:platform/mcu/stm32f1xx/hal/

API列表

hal_gpio_init 初始化指定GPIO管脚
hal_gpio_output_high 使指定GPIO输出高电平
hal_gpio_output_low 使指定GPIO输出低电平
hal_gpio_output_toggle 使指定GPIO输出翻转
hal_gpio_input_get 获取指定GPIO管脚的输入值
hal_gpio_enable_irq 使能指定GPIO的中断模式,挂载中断服务函数
hal_gpio_disable_irq 关闭指定GPIO的中断
hal_gpio_clear_irq 清除指定GPIO的中断状态
hal_gpio_finalize 关闭指定GPIO

API详情

请参考include/aos/hal/gpio.h

相关结数据结构

gpio_dev_t

typedef struct {
    uint8_t       port;    /* gpio逻辑端口号 */
    gpio_config_t config;  /* gpio配置信息 */
    void         *priv;    /* 私有数据 */
} gpio_dev_t;

gpio_config_t

typedef enum {
    ANALOG_MODE,               /* 管脚用作功能引脚,如用于pwm输出,uart的输入引脚 */
    IRQ_MODE,                  /* 中断模式,配置为中断源 */
    INPUT_PULL_UP,             /* 输入模式,内部包含一个上拉电阻 */
    INPUT_PULL_DOWN,           /* 输入模式,内部包含一个下拉电阻 */
    INPUT_HIGH_IMPEDANCE,      /* 输入模式,内部为高阻模式 */
    OUTPUT_PUSH_PULL,          /* 输出模式,普通模式 */
    OUTPUT_OPEN_DRAIN_NO_PULL, /* 输出模式,输出高电平时,内部为高阻状态 */
    OUTPUT_OPEN_DRAIN_NO_PULL, /* 输出模式,输出高电平时,被内部电阻拉高 */
} gpio_config_t;

gpio_irq_trigger_t

typedef enum {
    IRQ_TRIGGER_RISING_EDGE  = 0x1, /* 上升沿触发 */
    IRQ_TRIGGER_FALLING_EDGE = 0x2, /* 下降沿触发 */
    IRQ_TRIGGER_BOTH_EDGES   = IRQ_TRIGGER_RISING_EDGE | IRQ_TRIGGER_FALLING_EDGE,                                    /* 上升沿下降沿均触发 */
} gpio_irq_trigger_t;

gpio_irq_handler_t

typedef void (*gpio_irq_handler_t)(void *arg);

hal_gpio_init

GPIO 初始化

函数原型

int32_t hal_gpio_init(gpio_dev_t *gpio);

参数

gpio_dev_t *gpio 入参 GPIO设备描述,定义需要初始化的GPIO管脚的相关特性 用户自定义该结构体

返回值

类型:int 返回成功或失败, 返回0表示GPIO初始化成功,非0表示失败

调用示例

#define GPIO_LED_IO 18
gpio_dev_t led;
led.port = GPIO_LED_IO;
/* set as output mode */
led.config = OUTPUT_PUSH_PULL;
ret = hal_gpio_init(&led);

hal_gpio_output_high

某GPIO输出高电平

函数原型

int32_t hal_gpio_output_high(gpio_dev_t *gpio)

参数

gpio_dev_t *gpio 入参 GPIO设备描述 使用hal_gpio_init初始化传入值 ,需要预设输出模式

返回值

类型:int 返回成功或失败, 返回0表示GPIO输出高电平成功,非0表示失败

调用示例

#define GPIO_IO_OUT 19
gpio_dev_t gpio_out;
gpio_out.port = GPIO_IO_OUT;
/* set as output mode */
gpio_out.config = OUTPUT_PUSH_PULL;
ret = hal_gpio_init(&gpio_out);

ret= hal_gpio_output_high(&gpio_out);

hal_gpio_output_low

某GPIO输出低电平

函数原型

int32_t hal_gpio_output_low(gpio_dev_t *gpio)

参数

gpio_dev_t *gpio 入参 GPIO设备描述 使用hal_gpio_init初始化传入值 ,需要预设输出模式

返回值

类型:int 返回成功或失败, 返回0表示GPIO输出低电平成功,非0表示失败

调用示例

#define GPIO_IO_OUT 19
gpio_dev_t gpio_out;
gpio_out.port = GPIO_IO_OUT;
/* set as output mode */
gpio_out.config = OUTPUT_PUSH_PULL;
ret = hal_gpio_init(&gpio_out);

ret= hal_gpio_output_low(&gpio_out);

hal_gpio_output_toggle

某GPIO输出翻转

函数原型

int32_t hal_gpio_output_toggle(gpio_dev_t* gpio)

参数

gpio_dev_t *gpio 入参 GPIO设备描述 使用hal_gpio_init初始化传入值 ,需要预设输出模式

返回值

类型:int 返回成功或失败, 返回0表示GPIO翻转成功,非0表示失败。

调用示例

#define GPIO_IO_OUT 19
gpio_dev_t gpio_out;
gpio_out.port = GPIO_IO_OUT;
/* set as output mode */
gpio_out.config = OUTPUT_PUSH_PULL;
ret = hal_gpio_init(&gpio_out);

ret= hal_gpio_output_toggle(&gpio_out);

hal_gpio_input_get

获取某GPIO管脚输入值

函数原型

int32_t hal_gpio_input_get(gpio_dev_t *gpio, uint32_t *value)

参数

gpio_dev_t *gpio 入参 GPIO设备描述 使用hal_gpio_init初始化传入值 ,需要预设输入模式
uint32_t *value 出参 需要获取的管脚值存放地址 自定义uint32_t数据结构,传入地址

返回值

类型:int 返回成功或失败, 返回0表示GPIO输入获取成功,非0表示失败。

调用示例

#define GPIO_IO_OUT 19
uint32_t pinval = 0;
gpio_dev_t gpio_out;
gpio_out.port = GPIO_IO_OUT;
/* set as input mode */
gpio_out.config = INPUT_PULL_UP;
ret = hal_gpio_init(&gpio_out);

ret= hal_gpio_input_get(&gpio_out,&pinval);

hal_gpio_enable_irq

使能指定GPIO的中断模式,挂载中断服务函数,需要预先调用hal_gpio_init,设置IRQ_MODE。

函数原型

int32_t hal_gpio_enable_irq(gpio_dev_t *gpio, gpio_irq_trigger_t trigger,gpio_irq_handler_t handler, void *arg)

参数

gpio_dev_t *gpio 入参 GPIO设备描述 使用hal_gpio_init初始化传入值
gpio_irq_trigger_t 入参 中断的触发模式,上升沿、下降沿还是都触发 直接使用gpio_irq_trigger_t枚举
gpio_irq_handler_t handler 入参 中断服务函数指针,中断触发后将执行指向的函数
void *arg 入参 中断服务函数的入参

返回值

类型:int 返回成功或失败, 返回0使能中断成功,非0表示失败。

调用示例

#define GPIO_IO_INT 19
void gpio_irq_fun(void *arg)
{
}
gpio_dev_t gpio_int;
gpio_int.port = GPIO_IO_INT;
/* set as int mode */
gpio_int.config = IRQ_MODE;
ret = hal_gpio_init(&gpio_int);
/* int triggered int rising edge */
ret= hal_gpio_enable_irq(&gpio_int, IRQ_TRIGGER_RISING_EDGE,gpio_irq_fun,NULL);

hal_gpio_disable_irq

关闭指定GPIO的中断。

函数原型

int32_t hal_gpio_disable_irq(gpio_dev_t *gpio)

参数

gpio_dev_t *gpio 入参 GPIO设备描述 使用hal_gpio_init初始化传入值

返回值

类型:int 返回成功或失败, 返回0表示中断去使能成功,非0表示失败。

调用示例

ret= hal_gpio_disable_irq(&gpio_int);

hal_gpio_clear_irq

清除指定GPIO的中断。

函数原型

int32_t hal_gpio_clear_irq(gpio_dev_t *gpio)

参数

gpio_dev_t *gpio 入参 GPIO设备描述 使用hal_gpio_init初始化传入值

返回值

类型:int 返回成功或失败, 返回0表示清中断成功,非0表示失败。

调用示例

ret= hal_gpio_clear_irq(&gpio_int);

hal_gpio_finalize

关闭指定GPIO,及其中断。

函数原型

int32_t hal_gpio_finalize(gpio_dev_t *gpio)

参数

gpio_dev_t *gpio 入参 GPIO设备描述 使用hal_gpio_init初始化传入值

返回值

类型:int 返回成功或失败, 返回0表示关闭成功,非0表示失败。

调用示例

ret= hal_gpio_finalize(&gpio_int);

使用

添加该组件

在相应的platform/mcu的mk内,添加对应hal文件的编译包含。

包含头文件

#include "aos/hal/gpio.h"

使用示例

GPIO作为输出

#include <aos/hal/gpio.h>

#define GPIO_LED_IO 18

/* define dev */
gpio_dev_t led;

int application_start(int argc, char *argv[])
{
    int ret = -1;

    /* gpio port config */
    led.port = GPIO_LED_IO;

    /* set as output mode */
    led.config = OUTPUT_PUSH_PULL;

    /* configure GPIO with the given settings */
    ret = hal_gpio_init(&led);
    if (ret != 0) {
        printf("gpio init error !\n");
    }

    /* output high */
    hal_gpio_output_high(&led);

    /* output low */
    hal_gpio_output_low(&led);

    /* toggle the LED every 1s */
    while(1) {

        /* toggle output */
        hal_gpio_output_toggle(&led);

        /* sleep 1000ms */
        aos_msleep(1000);
    };
}

注:port为逻辑端口号,其与物理端口号的对应关系见具体的对接实现

GPIO作为中断输入

#include <aos/hal/gpio.h>

#define GPIO_BUTTON_IO 5

/* define dev */
gpio_dev_t button1;

/* pressed flag */
int button1_pressed = 0;

void button1_handler(void *arg)
{
	button1_pressed = 1;
}

int application_start(int argc, char *argv[])
{
    int ret = -1;

	/* input pin config */
	button1.port = GPIO_BUTTON_IO;

	/* set as interrupt mode */
	button1.config = IRQ_MODE;

	/* configure GPIO with the given settings */
	ret = hal_gpio_init(&button1);
	if (ret != 0) {
	    printf("gpio init error !\n");
	}

	/* gpio interrupt config */
	ret = hal_gpio_enable_irq(&button1, IRQ_TRIGGER_BOTH_EDGES, 
                              button1_handler, NULL);
	if (ret != 0) {
	    printf("gpio irq enable error !\n");
	}

    /* if button is pressed, print "button 1 is pressed !" */
    while(1) {
        if (button1_pressed == 1) {
        	button1_pressed = 0;
            printf("button 1 is pressed !\n");
        }

        /* sleep 100ms */
        aos_msleep(100);
    };
}

当button被按下后,串口会打印"button 1 is pressed !"

移植说明

新建hal_gpio_xxmcu.c和hal_gpio_xxmcu.h的文件,并将这两个文件放到platform/mcu/xxmcu/hal目录下。在hal_gpio_xxmcu.c中实现所需要的hal函数,hal_gpio_xxmcu.h中放置相关宏定义。 参考platform/mcu/stm32l4xx/src/STM32L496G-Discovery/hal/hal_gpio_stm32l4.c