电子网首页 > 开源与设计

【瑞萨RA8D1 LVGL/LWIP评测】LVGL添加输入设备:EC1

2026-02-07 01:10 | 来源:电子世界报

      在上一篇文章 《【瑞萨RA8D1 LVGL/LWIP评测】RA8D1 部署FreeRTOS+LVGL》 中,我们基于瑞萨 CPKCOR-RA8D1 开发板部署了 FreeRTOS + LVGL 的代码。但是该LVGL工程缺少输入设备,本文我们既不搞按键、也不添加触屏,添加一种比较特殊的输入设备:Encoder 编码器。本文似乎是全网首个瑞萨单片机使用GPT 硬件计数模式读取EC11旋转编码器的文章,我们这就开搞!

一、基础环境准备

硬件部分

  1. CPKCOR-RA8D1 核心板

  2. CPKEXP-EKRA8x1 扩展板

  3. EC11 旋转编码器

软件部分

  1. e²Studio 2025-12 (25.12.0)

  2. Renesas FSP 6.3.0

  3. J-Link RTT Viewer V8.92

请基于上篇文章部署好的 FreeRTOS+LVGL 的基础环境进行开发。

二、工作原理

ec11.png

EC11 是一种常见的增量式机械旋转编码器,其工作原理可以概括为以下三个核心点:

1. 结构与信号产生
    EC11 内部有两组金属触点(通常标记为 Phase A 和 Phase B)。
    旋转时:内部的金属拨片会随着转动周期性地接触和断开公共端(COM,通常接地)。
    输出信号:A 相和 B 相会分别产生两个正交(相位差为 90°)的方波脉冲信号。

2. 相位差判断方向
    通过 A、B 两路信号跳变的先后顺序来识别旋转方向:
    顺时针 (CW):当 A 相产生下降沿时,B 相还处于高电平。
    逆时针 (CCW):当 A 相产生下降沿时,B 相已经处于低电平。

show.gif

     现代微控制器的定时器一般支持编码器计数的场景,在“计数模式”下,底层硬件会自动监测这种超前/滞后关系,从而自动增加或减少计数器的值。

3. 机械特性
    定位感(Detents):EC11 通常带有“咔哒”声的定位点。每转动一个定位点,A/B 相会完成一个或多个完整的脉冲周期。
    机械抖动(Bouncing):由于触点是机械接触,信号在跳变瞬间会产生几毫秒的杂波。因此我们在处理波形时要加以过滤,比如开启 Noise Filter。

     在瑞萨 RA8 系列中,EC11 编码器的检测主要有两种实现路径:GPT 硬件计数模式(最推荐,全硬件自动处理)和 ICU 外部中断模式(纯软件逻辑)。本文我们玩得“高端”一点,就用GPT!

三、FSP图形化配置

Pin引脚

     开始前,我们首先翻一翻 RA8D1 芯片手册和扩展板原理图,找找合适的输入捕获引脚,用来连接编码器的A、B相。

encoder_pin.jpg

     P400 和 P401 作为 GPT6 的A、B相,在扩展板中引出,正好满足我们的需求。

RGB.jpg

     我们在 Pin 配置的 GPT6 中启用相应引脚。

encoder_pin2.jpg

Stack配置

     我们通过 Timers -> Timer,General PWM(r_gpt) 选项引入GPT。Stack框图:

stack.JPG

随后修改GPT配置项:

1. Channel 选择 6,代表GPT6

2. Input 的 Count Up Source 选择 GTIOCA Rising Edge While GTIOCB Low

3. Input 的 Count Down Source 选择 GTIOCA Falling Edge While GTIOCB Low

4. Noice Filter 选择 PCLKD/64,启动滤波

properties.JPG

四、代码绑定

1. 在board_init.c 中,加入初始化代码:

R_GPT_Open(g_encoder_timer.p_ctrl, g_encoder_timer.p_cfg);
R_GPT_Start(g_encoder_timer.p_ctrl);

2. 在LVGL的移植文件 rm_lvgl_port.c 中,加入编码器回调方法

static void encoder_read_cb(lv_indev_t * indev, lv_indev_data_t * data) {
    FSP_PARAMETER_NOT_USED(indev);

    static uint32_t last_raw_count = 0;
    timer_status_t status;

    // 瑞萨 FSP 接口获取硬件计数值
    R_GPT_StatusGet(g_encoder_timer.p_ctrl, &status);
    uint32_t current_raw_count = status.counter;

    // 计算增量
    int32_t diff = (int32_t)(current_raw_count - last_raw_count);
    diff = diff > 1000 ? 0 : diff;

    data->enc_diff = (int16_t)diff;

    /* 更新旧值 */
    last_raw_count = current_raw_count;
}

3. 在LVGL的移植文件 rm_lvgl_port.c 的 RM_LVGL_PORT_Open 中,加入编码器注册代码:

g_indev_encoder = lv_indev_create();
lv_indev_set_type(g_indev_encoder, LV_INDEV_TYPE_ENCODER);
lv_indev_set_read_cb(g_indev_encoder, encoder_read_cb);

五、UI设计

     本文我们使用GUI Guider进行UI设计,引入slider控件来测试编码器是否正常工作。我们创建一个222x480分辨率的竖屏,添加一个图片和slider,slider可以控制图片的透明度。

ui.jpg

导出代码,复制到src下新建的ui文件夹中。

最后在LVGL线程中初始化使用的UI,将焦点设置在slider上。

代码如下:

extern lv_indev_t * g_indev_encoder;

void bind_slider(void) {
    /* 1. 创建一个组 (Group) */
    lv_group_t * g = lv_group_create();
    lv_group_set_default(g); // 设为默认组,后续创建的控件会自动加入

    /* 2. 将编码器绑定到组 */
    lv_indev_set_group(g_indev_encoder, g);

    /* 3. 关键:进入编辑模式 */
    // 在编辑模式下,编码器旋转才会改变 Slider 的 Value
    // 如果不在编辑模式,旋转通常用于在不同控件间切换焦点
    lv_group_set_editing(g, true);
}

/* LVGL Thread entry function */
/* pvParameters contains TaskHandle_t */
void lvgl_thread_entry(void *pvParameters)
{
    int i = 0, cnt = 0;
    char label[10];
    FSP_PARAMETER_NOT_USED (pvParameters);

    lv_init();
    board_init();
    bind_slider();
    setup_ui(&guider_ui);
    events_init(&guider_ui);
    lv_timer_handler();

    while (1)
    {
        lv_timer_handler();
        vTaskDelay (5);
    }
}

六、烧录运行

     烧录代码,转动EC11编码器,可以看到 slider 可以随之左右滑动,图像透明度也会随之变化。

v11.gif

     至此,我们就在 RA8D1 的 LVGL 中成功添加了EC11旋转编码器设备。


本文工程源码:

lvgl_encoder_rtos.zip

阅读全文

推荐技术

返回顶部