【LVGL】给SquareLineStudio导出的Arduino工程添加物理按键

〇、前言

书接上回(用SquareLine Studio轻松实现ESP8266运行LVGL图形化界面-CSDN博客),用SquareLineStudio导出界面,并通过Arduino下载到esp8266后运行如下:

可是这里的屏幕不是触摸屏,该如何使用屏幕上的button组件呢?

下面使用的代码,是上篇文章中导出的界面代码,这里需要给界面添加可操作性,增加物理按键。

一、物理按键定义

1.1 物理按键引脚连接

这里使用 D0 (GPIO16)和 D1(GPIO5)引脚分别作为【聚焦切换】和【确定】物理按键控制屏幕的2个按钮。
使用下拉电阻方式连接引脚,如图:

1.2 功能定义

如图,给两个物理按键定义功能:

这里举个例子,按下【D0】物理按键,假如选框在【add】按钮组件上,那么再按一下【D1】按键,就会实现value值的增加。再按下【D0】选框在【sub】按钮组件上,那么再按一下【D1】按键,就会实现value值的减少。

注意这里为什么2个物理按键不分别对应【add】按钮和【sub】按钮?
1、如果用这种方式,那么可以用2个物理按键控制更多的按钮组件。
2、lvgl运行后默认聚焦在第一个添加进组的按钮上,如果没有聚焦切换功能按钮,另一个按钮则无法使用。

二、修改代码部分

主要涉及修改的文件就2个,分别是 .\SquareLine_Project\ui\ui.ino.\SquareLine_Project\libraries\ui\src\ui.c文件,下面是修改部分和注释:

2.1 删除部分(可跳过)

因为这里用的屏幕是非触摸屏, SquareLineStudio导出的代码默认是带有触摸部分的,这里不需要,可以删除该部分。下面列出的部分是需要删除的代码(实际这部分不删,也不影响运行)

  • ui.ino
cpp 复制代码
/*Read the touchpad*/
void my_touchpad_read (lv_indev_t * indev_driver, lv_indev_data_t * data)        //整个my_touchpad_read函数需要删除掉
{
    uint16_t touchX = 0, touchY = 0;

    bool touched = false;//tft.getTouch( &touchX, &touchY, 600 );

    if (!touched)
    {
        data->state = LV_INDEV_STATE_REL;
    }
    else
    {
        data->state = LV_INDEV_STATE_PR;

        /*Set the coordinates*/
        data->point.x = touchX;
        data->point.y = touchY;

        Serial.print( "Data x " );
        Serial.println( touchX );

        Serial.print( "Data y " );
        Serial.println( touchY );
    }
}

void setup(){
    ... ...     // 其他部分代码省略
    static lv_indev_t* indev;                // setup函数中的创建设备的部分, 从这里开始往下4行都删除
    indev = lv_indev_create();
    lv_indev_set_type( indev, LV_INDEV_TYPE_POINTER );
    lv_indev_set_read_cb( indev, my_touchpad_read );    
    ... ...
}

2.2 增加代码

  • ui.ino
    ui.ino部分主要是增加输入设备组的创建函数和读取按键状态值回调函数,下面是需要增加的代码:
cpp 复制代码
... ...
lv_group_t *gp;    // 新增全局变量gp,用于创建组
... ...
void my_keypad_read(lv_indev_t *indev_driver, lv_indev_data_t *data)    // 新增函数my_keypad_read:回调函数用于读取按键状态和按键值
{
    if(digitalRead(D0) == HIGH) {    // 读取D0是否被按下(实际高低由实际按键接线为准)
        data->state = LV_INDEV_STATE_PR;    // 定义按键状态是【press/按下】
        data->key = LV_KEY_NEXT;            // 设置值为LV_KEY_NEXT,D0定义为【聚焦切换】功能按键
    }else if(digitalRead(D1) == HIGH){      // 读取D1是否被按下
        data->state = LV_INDEV_STATE_PR;    // 定义按键状态是【press/按下】
        data->key = LV_KEY_ENTER;           // 设置值为LV_KEY_ENTER,D0定义为【确定】功能按键
    }
    else {
        data->state = LV_INDEV_STATE_REL;    // 定义按键状态是【release/松开】
    }
}

void set_button(void){                                // 新增set_button函数:创建输入设备组函数
  static lv_indev_t* indev;
  indev = lv_indev_create();                        // 创建一个输入设备
(indev)
  lv_indev_set_type(indev, LV_INDEV_TYPE_KEYPAD);    // 该输入设备类型定义为键盘(KEYPAD)
  lv_indev_set_read_cb(indev, my_keypad_read);       // 键盘绑定回调函数my_keypad_read,回调函数读取键盘状态和按键值
  gp = lv_group_create();                            // 创建按键组
  lv_group_set_default(gp);                          // 设为默认组(实际开发可能多个设备组,这里就一个组)
  lv_group_add_obj(gp, ui_Button1);                  // 将按键组件1和按键组件2分别加入按键组
  lv_group_add_obj(gp, ui_Button2);
  lv_indev_set_group(indev, gp);                    // 将输入设备和按键组绑定。
}

void setup(){
    pinMode(D0, INPUT);  // 定义为【聚焦切换】按键
    pinMode(D1, INPUT);  // 定义为【确定】按键
    Serial.begin( 115200 );
    ... ...  // 中间省略部分
    ui_init();
    set_button(); // 一定在ui_init()函数后面调用set_button()函数创建输入设备组,因为按键组件在ui_init()中才被初始化。

    Serial.println( "Setup done" );
}

  • ui.c
    主要是修改按键的事件,根据按键的值实现对应的功能,下面是需要增改的函数
cpp 复制代码
... ...
void set_focus_obj(void){    //新增函数set_focus_obj,用于切换不同的聚焦组件
  lv_obj_t * arr[] = {ui_Button1, ui_Button2};    // 需要循环聚焦的按钮组件列表
  static unsigned char index = 0;
  lv_group_focus_obj(arr[++index % 2]);        // 设置当前需要聚焦的按钮组件
}

void ui_event_Button1(lv_event_t * e)            // 修改函数ui_event_Button1:需要修改的按钮1事件函数
{
    lv_event_code_t event_code = lv_event_get_code(e);    // 获取当前发生的事件
    if(event_code == LV_EVENT_KEY) {            // 判断是否有按键事件
      if(lv_event_get_key(e) == LV_KEY_NEXT){   // 判断是否【聚焦切换】按键按下
        set_focus_obj();                        // 调用切换聚焦组件函数
      }else if(lv_event_get_key(e) == LV_KEY_ENTER)    // 判断是否有【确定】键按下
          _ui_slider_increment(ui_Slider1, -1, LV_ANIM_ON);    // 使slider值加-1,即减1
    }

}

void ui_event_Button2(lv_event_t * e)            // 修改函数ui_event_Button2:需要修改的按钮2事件函数
{
    lv_event_code_t event_code = lv_event_get_code(e);     // 获取当前发生的事件
    if(event_code == LV_EVENT_KEY) {             // 判断是否有按键事件
      if(lv_event_get_key(e) == LV_KEY_NEXT){    // 判断是否【聚焦切换】按键按下
        set_focus_obj();                           // 调用切换聚焦组件函数
      }else if(lv_event_get_key(e) == LV_KEY_ENTER){    // 判断是否有【确定】键按下
        _ui_slider_increment(ui_Slider1, 1, LV_ANIM_ON);  // 使slider值加1,
      }
    }
}

... ...

三、查看效果

用SquareLine导出esp8266单片机的arduino工程,对其lvgl添加物理按键代码,运行结果呈现

相关推荐
广药门徒3 小时前
电脑芯片其实更偏向MPU不是CPU,GPU CPU NPU MPU MCU的区别
单片机·嵌入式硬件
灬若宸4 小时前
14、外部中断
stm32·单片机·嵌入式硬件·系统架构
逼子格6 小时前
【Protues仿真】基于AT89C52单片机的舵机和直流电机控制
单片机·嵌入式硬件·硬件工程·硬件工程师·电机驱动·l298n·直流电机控制
GodKK老神灭7 小时前
STM32 AFIO模块
stm32·单片机·嵌入式硬件
滴啦嘟啦哒9 小时前
【项目复盘】【四轴飞行器设计】驱动开发部分
单片机·面试准备
狂奔的sherry9 小时前
一会儿能ping通一会ping不通解决方案
运维·网络·单片机·嵌入式硬件
qq_401700419 小时前
单片机驱动继电器接口
单片机·嵌入式硬件
anghost1501 天前
基于 STM32 的多传感器健康监测系统设计
stm32·单片机·嵌入式硬件
玉~你还好吗1 天前
【嵌入式电机控制#34】FOC:意法电控驱动层源码解析——HALL传感器中断(不在两大中断内,但重要)
单片机·嵌入式系统·电机控制
STC_USB_CAN_80511 天前
所有普通I/O口都支持中断的51单片机@Ai8051U, AiCube 图形化配置
单片机·嵌入式硬件·51单片机