RT-Thread Pin 设备驱动框架快速对接

为什么需要 Pin 设备驱动框架

  • 跨平台可移植应用
  • 操作简单

试想下面这个场景:
你基于 STM32 MCU 编写了一个包含很多 GPIO 操作的应用程序,GPIO 控制函数使用的是 HAL 库。
后面,由于某种原因,MCU 需要更换,使用的是 NXP 的芯片,不支持 HAL 库,那你怎么办?

通常,你会查找所有 GPIO 操作相关的接口,然后替换成 NXP 提供的 GPIO 驱动函数,如果 GPIO 的编排方式不一样(有的有 GPIOA 这样的分组,有的没有),那就更加的麻烦。这样,你就维护了两个版本的应用程序。

那么,有了 Pin 驱动框架能解决这个问题吗?
当然,Pin 只能解决应用层代码不需要变动的问题,但需要将 GPIO 驱动对接到 Pin 驱动框架上。
另外,RT-Thread Pin 设备驱动框架采用了统一 GPIO 号编排的方式,从 0 开始向上计数,每一个 GPIO 对应一个 pin 号。这样做的好处是,应用程序无需关心该 GPIO 属于哪一个组(GPIOA,还是 GPIOB),也无需关心相关 GPIO 的时钟初始化、中断等。因为,Pin 设备驱动框架都帮你抽象好了。

在这里插入图片描述

怎么对接到 Pin 设备框架

首先了解下文件结构

PIN 设备框架对应文件:

  • pin.h
  • pin.c
    源文件路径: components/drivers/misc/pin.c

对接到 PIN 设备框架的驱动代码需要我们自行实现(如果官方没有现成的 BSP 可以使用),为了保持驱动实现的一致性,这里有一些潜在规则:

  • RT-Thread 通常将对接设备框架的驱动相关文件存放在对应 bsp 的 drivers 目录下
  • 驱动程序文件命名采用 drv_ 前缀加驱动名称的方式

当然,并不是所有的 BSP 对接 rt-thread 设备框架的驱动程序文件都存放在 drivers 目录下,如 STM32 新 BSP 中的驱动实现在 rt-thread/bsp/stm32/libraries/HAL_Drivers 目录下。

由此,本次我们需要实现的 GPIO 驱动如下:

GPIO 驱动对应文件:

  • drv_gpio.h
  • drv_gpio.c

PIN 驱动框架和 GPIO 驱动对接

在这里插入图片描述
从上图可以直观地看到 Pin 设备驱动框架和 GPIO 驱动是如果对接到一起的。
如上图所示:

  • 左侧为 Pin 设备驱动框架封装的 API 接口,向上提供给应用层使用;
  • 右侧为具体芯片平台对接 Pin 设备的驱动程序,与 Pin 设备框架提供的 API 接口一一对应,通过 rt_pin_ops 结构体关联到一起,驱动框架层接口最终会回调驱动层接口;
  • 最后通过 rt_device_pin_register 函数接口,将底层驱动与 Pin 设备框架绑定到一起,注册到 RT-Thread 的设备框架中。

在对接 RT-Thread Pin 设备框架的时候,仅需要实现上图右侧 rt_pin_ops 结构体中的所有 callback 回调函数即可,然后通过 rt_device_pin_register 注册到系统,最后使用 rt_hw_pin_init 调用以进行初始化。
rt_hw_pin_init 在系统启动过程中被 rt_hw_board_init 调用。

注意:
需要注意的是 rt_pin_attach_irq 接口的使用,其函数原型如下:

rt_err_t rt_pin_attach_irq(rt_int32_t pin, rt_uint32_t mode,
                             void (*hdr)(void *args), void  *args)

该函数的功能是,为指定的 pin 脚绑定中断回调函数 hdr,并设置对应的中断模式 mode 。该函数是唯一的从应用层,通过 Pin 设备框架向下注册到 GPIO 驱动层的 API 接口。
用户在实现 rt_pin_attach_irq 对应的 pin_attach_irq 回调函数时,记得将 hdr 回调函数应用到对应 pin 脚的外部中断 Handler 中。

如何使用

RT-Thread 官方的文档中心中 Pin 设备给出了一个基本的测试例程,这里做引用,如下所示:

以下内容引用自 RT-Thread 文档中心,地址:https://www.rt-thread.org/document/site/programming-manual/device/pin/pin/

PIN 设备的具体使用方式可以参考如下示例代码,示例代码的主要步骤如下:

  • 设置蜂鸣器对应引脚为输出模式,并给一个默认的低电平状态
  • 设置按键 0 和 按键1 对应引脚为输入模式,然后绑定中断回调函数并使能中断
  • 按下按键 0 蜂鸣器开始响,按下按键 1 蜂鸣器停止响

代码如下:

/*
 * 程序清单:这是一个 PIN 设备使用例程
 * 例程导出了 pin_beep_sample 命令到控制终端
 * 命令调用格式:pin_beep_sample
 * 程序功能:通过按键控制蜂鸣器对应引脚的电平状态控制蜂鸣器
*/

#include <rtthread.h>
#include <rtdevice.h>

/* 引脚编号,通过查看设备驱动文件drv_gpio.c确定 */
#ifndef BEEP_PIN_NUM
    #define BEEP_PIN_NUM            35  /* PB0 */
#endif
#ifndef KEY0_PIN_NUM
    #define KEY0_PIN_NUM            55  /* PD8 */
#endif
#ifndef KEY1_PIN_NUM
    #define KEY1_PIN_NUM            56  /* PD9 */
#endif

void beep_on(void *args)
{
    rt_kprintf("turn on beep!\n");

    rt_pin_write(BEEP_PIN_NUM, PIN_HIGH);
}

void beep_off(void *args)
{
    rt_kprintf("turn off beep!\n");

    rt_pin_write(BEEP_PIN_NUM, PIN_LOW);
}

static void pin_beep_sample(void)
{
    /* 蜂鸣器引脚为输出模式 */
    rt_pin_mode(BEEP_PIN_NUM, PIN_MODE_OUTPUT);
    /* 默认低电平 */
    rt_pin_write(BEEP_PIN_NUM, PIN_LOW);

    /* 按键0引脚为输入模式 */
    rt_pin_mode(KEY0_PIN_NUM, PIN_MODE_INPUT_PULLUP);
    /* 绑定中断,下降沿模式,回调函数名为beep_on */
    rt_pin_attach_irq(KEY0_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_on, RT_NULL);
    /* 使能中断 */
    rt_pin_irq_enable(KEY0_PIN_NUM, PIN_IRQ_ENABLE);

    /* 按键1引脚为输入模式 */
    rt_pin_mode(KEY1_PIN_NUM, PIN_MODE_INPUT_PULLUP);
    /* 绑定中断,下降沿模式,回调函数名为beep_off */
    rt_pin_attach_irq(KEY1_PIN_NUM, PIN_IRQ_MODE_FALLING, beep_off, RT_NULL);
    /* 使能中断 */
    rt_pin_irq_enable(KEY1_PIN_NUM, PIN_IRQ_ENABLE);
}
/* 导出到 msh 命令列表中 */
MSH_CMD_EXPORT(pin_beep_sample, pin beep sample);
<think>好的,用户现在在问关于在RT-Thread系统中驱动GT911触摸屏的信息或教程,以及示例代码。我需要先回顾一下RT-Thread的文档和相关组件。记得RT-Thread有一个传感器框架,可能触摸屏驱动会集成在这里。另外,用户之前提到的GT9147示例,可能GT911的驱动方式类似,都是通过I2C通信,注册为触摸设备。 首先,检查RT-Thread的官方文档或者GitHub仓库,看看是否有GT911的驱动支持。可能GT911和GT9147都属于Goodix的触摸芯片,驱动代码结构可能相似。需要确认硬件连接,比如I2C接口的引脚配置,中断引脚和复位引脚的使用。 然后,用户可能需要配置board.h中的相关宏定义,比如I2C总线名称、设备地址、中断引脚号等。示例代码可能包括初始化函数、中断处理、读取坐标数据等部分。此外,RT-Thread可能使用rt_touch框架,所以需要注册touch设备,并实现open、close、control等操作。 另外,用户提到的引用中有关littlevgl2rtt项目,说明可能需要与LittlevGL图形库集成,所以驱动成功后,触摸数据会被传递到GUI部分。需要注意配置正确的分辨率和触摸点数量。 用户可能遇到的问题包括I2C通信失败、中断无法触发、坐标数据不正确等,需要建议他们检查硬件连接、配置参数,以及使用i2c工具进行测试。同时,参考GT9147的示例代码进行适配,因为两者驱动方式可能相似,只需修改部分寄存器地址或初始化序列。 最后,生成相关问题,帮助用户进一步解决可能遇到的调试问题、配置步骤或与其他组件的集成。</think>在RT-Thread系统中驱动GT911触摸屏的开发可分为以下关键步骤,基于其传感器框架和触摸设备驱动模型: ### 一、硬件配置要点 1. 确认开发板的I2C接口定义,GT911通常需要连接: - SCL/SDA(I2C时钟/数据线) - INT(中断信号引脚) - RST(复位控制引脚) 2. 在`board.h`中配置设备地址,GT911默认地址为$0x5D$或$0x14$(根据TS引脚电平) ### 二、驱动移植示例代码 ```c #include <rtdevice.h> #define GT911_ADDR 0x5D #define GT911_INT_PIN GET_PIN(C, 5) #define GT911_RST_PIN GET_PIN(C, 6) static void gt911_irq_handler(void *args) { rt_touch_irq_handler((rt_device_t)args); } static struct rt_touch_ops gt911_ops = { .touch_readpoint = gt911_read_point, .touch_control = gt911_control }; int rt_hw_gt911_init(void) { struct rt_touch_config cfg; cfg.dev_name = "i2c1"; // 指定I2C总线 rt_touch_t touch_dev = rt_calloc(1, sizeof(struct rt_touch_device)); touch_dev->info.type = RT_TOUCH_TYPE_CAPACITANCE; touch_dev->info.vendor = RT_TOUCH_VENDOR_GT911; touch_dev->ops = &gt911_ops; rt_pin_mode(GT911_INT_PIN, PIN_MODE_INPUT_PULLUP); rt_pin_attach_irq(GT911_INT_PIN, PIN_IRQ_MODE_FALLING, gt911_irq_handler, touch_dev); rt_hw_touch_register(touch_dev, "gt911", RT_DEVICE_FLAG_INT_RX, &cfg); return RT_EOK; } INIT_DEVICE_EXPORT(rt_hw_gt911_init); ``` ### 三、关键开发要点 1. **中断处理**:需要实现坐标数据的读取和上报,建议使用`rt_touch_irq_handler`作为中断入口 2. **寄存器配置**:需按照数据手册初始化触摸芯片,包含: ```c static rt_err_t gt911_control(rt_device_t dev, int cmd, void *args) { switch (cmd) { case RT_TOUCH_CTRL_GET_ID: i2c_read_reg(GT911_PRODUCT_ID_REG, id_buf, 4); break; case RT_TOUCH_CTRL_SET_X_RANGE: gt911_set_reg(GT911_X_RANGE_REG, *(rt_uint16_t*)args); break; } return RT_EOK; } ``` 3. **坐标解析**:在`gt911_read_point`函数中需要处理原始数据包,通常包含$5$个触控点的$X/Y$坐标(每个坐标用$2$字节表示) ### 四、调试方法 1. 使用`i2c-tools`工具验证I2C通信 ```shell msh > i2c probe 1 # 扫描i2c1总线 msh > i2c read 1 0x5D 0x8140 2 # 读取产品ID ``` 2. 查看触摸设备注册状态 ```shell msh > list_device touch gt911 # 应显示已注册设备 ``` 3. 使用`touch_test`命令验证数据流 ```shell msh > touch_test gt911 [398,288] [press] # 将显示实时坐标 ``` ### 五、GUI集成 与LittlevGL图形库对接时,需在`lv_port_indev_init`中设置输入设备: ```c rt_device_t touch = rt_device_find("gt911"); lv_indev_drv_t indev_drv; lv_indev_drv_init(&indev_drv); indev_drv.type = LV_INDEV_TYPE_POINTER; indev_drv.read_cb = rt_touch_read_callback; lv_indev_drv_register(&indev_drv); ``` 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值