Skip to content

GPIO/PIN

GPIO/PIN简介

芯片上的引脚一般分为 4 类:电源、时钟、控制与 I/O,I/O 口在使用模式上又分为 General Purpose Input Output(通用输入 / 输出),简称 GPIO。

GPIO控制器可以驱动或者获取信号/数据,定义I/O的功能、方向、状态以及中断,也称为PIN。

访问GPIO设备

访问GPIO设备,库中提供了以下接口:

函数 描述
rt_pin_mode() 设置GPIO工作模式
rt_pin_write() 设置GPIO输出高低电平
rt_pin_read() 读取GPIO电平
rt_pin_attach_irq() 绑定GPIO中断回调函数
rt_pin_irq_enable() 使能GPIO中断
rt_pin_detach_irq() 解绑GPIO中断回调函数

设置GPIO工作模式

设置指定的GPIO的工作模式,函数原型如下所示:

void rt_pin_mode(rt_base_t pin, rt_base_t mode);
  • 参数

    [IN]pin:GPIO引脚编号,IoTE板子支持的GPIO有五个,对应如下表所示:

    枚举定义 枚举值 引脚名称 连接LED灯
    GPIO_PIN_2 2 IO_2 D15
    GPIO_PIN_3 3 IO_3 D14
    GPIO_PIN_7 7 IO_7 D2
    GPIO_PIN_16 16 IO_16 D10
    GPIO_PIN_17 17 IO_17 D11

    [IN]mode:GPIO引脚工作模式,目前支持的引脚工作模式可取如所示的 4 种宏定义值之一:

    // 头文件相对路径:rt-thread/components/drivers/include/drivers/pin.h
    #define PIN_MODE_OUTPUT         0x00    // 输出 
    #define PIN_MODE_INPUT          0x01    // 输入 
    #define PIN_MODE_INPUT_PULLUP   0x02    // 上拉输入
    #define PIN_MODE_OUTPUT_OD      0x04    // 开漏输出 
    
  • 返回值

    无。

设置GPIO输出电平

设置指定GPIO引脚输出电平,函数原型如下所示:

void rt_pin_write(rt_base_t pin, rt_base_t value);
  • 参数

    [IN]pin:GPIO引脚编号,IoTE板子支持的GPIO有 5 个,请查看设置GPIO工作模式中的表格描述。

    [IN]value:电平逻辑值,可取如下2 种宏定义值之一:

    // 头文件相对路径:rt-thread/components/drivers/include/drivers/pin.h
    #define PIN_LOW     0x00    // 低电平
    #define PIN_HIGH    0x01    // 高电平
    
  • 返回值

读取GPIO电平

读取指定GPIO引脚输入电平,函数原型如下所示:

int rt_pin_read(rt_base_t pin);

绑定引脚中断回调函数

若要使用到GPIO引脚的中断功能,可以使用如下函数将某个引脚配置为某种中断触发模式并绑定一个中断回调函数到对应引脚,当引脚中断发生时,就会执行回调函数,函数原型如下所示:

rt_err_t rt_pin_attach_irq(rt_int32_t pin, 
                           rt_uint32_t mode, 
                           void (*hdr)(void* args), 
                           void* args);
  • 参数

    [IN]pin:GPIO引脚编号,IoTE板子支持的GPIO有五个,请查看设置GPIO工作模式中的表格描述。

    [IN]mode:中断触发模式,共定义了如下 5 种宏定义值:

    // 头文件相对路径:rt-thread/components/drivers/include/drivers/pin.h
    #define PIN_IRQ_MODE_RISING         0x00    // 上升沿触发
    #define PIN_IRQ_MODE_FALLING        0x01    // 下降沿触发
    #define PIN_IRQ_MODE_RISING_FALLING 0x02    // 边沿触发(上升沿和下降沿都触发)
    #define PIN_IRQ_MODE_HIGH_LEVEL     0x03    // 高电平触发
    #define PIN_IRQ_MODE_LOW_LEVEL      0x04    // 低电平触发
    

    [IN]hdr:中断回调函数,用户需要自行定义这个函数

    [INOUT]args:中断回调函数的参数,不需要时设置为 RT_NULL

  • 返回值

    0:成功。

    其他:错误,RT-Thread定义的错误类型。

使能GPIO脚中断

绑定好引脚中断回调函数后使用下面的函数使能引脚中断,函数原型如下所示:

rt_err_t rt_pin_irq_enable(rt_base_t pin, rt_uint32_t enable);
  • 参数

    [IN]pin:GPIO引脚编号,IoTE板子支持的GPIO有五个,请查看设置GPIO工作模式中的表格描述。

    [IN]enable:状态,可取以下 2 种值之一:

    #define PIN_IRQ_DISABLE     0x00    // 关闭
    #define PIN_IRQ_ENABLE      0x01    // 开启
    
  • 返回值

    0:成功。

    其他:错误,RT-Thread定义的错误类型。

解绑GPIO中断回调函数

可以使用如下函数解绑GPIO引脚中断回调函数:

rt_err_t rt_pin_detach_irq(rt_int32_t pin);
  • 参数

    [IN]pin:GPIO引脚编号,IoTE板子支持的GPIO有五个,请查看设置GPIO工作模式中的表格描述。

  • 返回值

    0:成功。

    其他:错误,RT-Thread定义的错误类型。

注:引脚解绑了中断回调函数后,中断并没有关闭,还可以调用绑定引脚中断回调函数再次绑定其他回调函数。

GPIO使用示例

使用示例需要配置menuconfig,使能例程与外设,步骤如下:

  1. 使能例程
Application Example Config -> Enable PIN Example
  1. 使能外设驱动
Hardware Drivers Config -> On-chip Peripheral Drivers -> Enable GPIO

以下提供GPIO测试实例,测试步骤如下:

  1. 设置GPIO输出模式。

  2. 输入模式下设置中断触发方式。

  3. 开启中断。

#include <rtthread.h>

#ifdef APP_EXAMPLE_PIN

#ifndef RT_USING_PIN
#error "Please enable rt-thread GPIO device driver"
#endif

#ifndef BSP_USING_GPIO
#error "Please enable on-chip peripheral gpio config"
#endif

#include <rtdevice.h>
#include "uc_pin_app.h"

#define THREAD_STACK_SIZE 512
#define THREAD_PRIORITY 5
#define THREAD_TIMESLICE 5

#define LED1_PIN_NUM 2
#define LED2_PIN_NUM 3
#define IRQ1_PIN_NUM 16
#define IRQ2_PIN_NUM 17

static void led2_on(void *args)
{
    rt_kprintf("key1 pressed, LED2 on.\n");
    rt_pin_write(LED2_PIN_NUM, PIN_HIGH);
}

static void led2_off(void *args)
{
    rt_kprintf("key2 pressed, LED2 off.\n");
    rt_pin_write(LED2_PIN_NUM, PIN_LOW);
}

static int pin_app_init(void)
{
    rt_err_t ret = RT_EOK;
    rt_pin_mode(LED1_PIN_NUM, PIN_MODE_OUTPUT);
    rt_pin_mode(LED2_PIN_NUM, PIN_MODE_OUTPUT);

    rt_pin_write(LED1_PIN_NUM, PIN_LOW);
    rt_pin_write(LED2_PIN_NUM, PIN_LOW);

    rt_pin_mode(IRQ1_PIN_NUM, PIN_MODE_INPUT_PULLUP);
    rt_pin_attach_irq(IRQ1_PIN_NUM, PIN_IRQ_MODE_RISING, led2_on, RT_NULL);
    rt_pin_irq_enable(IRQ1_PIN_NUM, PIN_IRQ_ENABLE);

    rt_pin_mode(IRQ2_PIN_NUM, PIN_MODE_INPUT_PULLUP);
    rt_pin_attach_irq(IRQ2_PIN_NUM, PIN_IRQ_MODE_RISING, led2_off, RT_NULL);
    rt_pin_irq_enable(IRQ2_PIN_NUM, PIN_IRQ_ENABLE);

    return ret;
}

static void pin_thread_entry(void *parameter)
{
    while (1)
    {
        rt_pin_write(LED1_PIN_NUM, PIN_HIGH);
        rt_kprintf("LED1 on.\n");
        rt_thread_mdelay(500);
        rt_pin_write(LED1_PIN_NUM, PIN_LOW);
        rt_kprintf("LED1 off.\n");
        rt_thread_mdelay(500);
    }
}

int pin_app_sample(void)
{
    rt_err_t ret = RT_EOK;
    rt_thread_t thread = RT_NULL;

    rt_kprintf("pin_app_sample\n");

    ret = pin_app_init();
    if (ret != RT_EOK)
    {
        rt_kprintf("pin init error\n");
        return -RT_ERROR;
    }

    /* 创建 serial 线程 */
    thread = rt_thread_create("pin_app",
                              pin_thread_entry,
                              RT_NULL,
                              THREAD_STACK_SIZE,
                              THREAD_PRIORITY,
                              THREAD_TIMESLICE);
    /* 创建成功则启动线程 */
    if (RT_NULL == thread)
    {
        return -RT_ERROR;
    }
    else
    {
        rt_thread_startup(thread);
    }

    return RT_EOK;
}

#endif // APP_EXAMPLE_PIN
Back to top