当前位置:网站首页>ESP32 LVGL8. 1 - input devices (input devices 18)

ESP32 LVGL8. 1 - input devices (input devices 18)

2022-04-23 18:37:00 Please call me Xiao Peng

Tips : This blog serves as a learning note , If there are mistakes, I hope to correct them

One 、Input devices brief introduction

1.1 summary Overview

   Input devices usually mean :
• Pointer input devices like touchpad or mouse
• The keypad is like an ordinary keyboard or a simple numeric keypad
• Encoder and left / Turn right and choose
• External hardware button , Assigned to a specific point on the screen
Before further reading , Please read the input of the portable device (/ transplant /indev) part ,

1.2 The pointer Pointers

   The pointer input device can have a cursor .( Usually mouse )

lv_indev_t * mouse_indev = lv_indev_drv_register(&indev_drv);
LV_IMG_DECLARE(mouse_cursor_icon); 							/*Declare the image file.*/
lv_obj_t * cursor_obj = lv_img_create(lv_scr_act(), NULL); 	/*Create an image object␣ /*for the cursor */
lv_img_set_src(cursor_obj, &mouse_cursor_icon); /*Set the image source*/
lv_indev_set_cursor(mouse_indev, cursor_obj); 	/*Connect the image ␣ ,→object to the driver*/

   Be careful , Cursor object should have lv_obj_set_click(cursor_obj, false). For the image , Clicking is disabled by default .

1.3 Keys and encoders Keypad and encoder

   You can fully control the user interface without a touch pad or mouse using a keypad or encoder (s). It works like PC Upper TAB Key to select elements in an application or web page .

1.3.1 Group Groups

   You need to add objects that you want to control with a keyboard or encoder to the group . In each group , There is a focused object that receives the action of the pressed key or encoder . for example , If a text area is centralized , You press a letter on the keyboard , The key will be sent and inserted into the text area . Similarly , If a slider is focused , And you press the left or right arrow , The value of the slider will change . You need to associate the input device with the Group . An input device can only send keys to one group , however , A group can also receive data from multiple input devices . To create a group , Please use lv_group_t * g = lv_group_create(); To add an object to a group , Please use lv_group_add_obj(g, obj). Use lv_indev_set_group(indev, g) Associate a group with an input device , among indev yes lv_indev_drv_register() The return value of .

1.3.1.1 Key Keys

   There are some predefined keys that have special meanings :
• LV_KEY_NEXT Next object
• LV_KEY_PREV Focus on the previous object
• LV_KEY_ENTER Trigger LV_EVENT_PRESSED/CLICKED/LONG_PRESSED Other events
• LV_KEY_UP Add value or move up
• LV_KEY_DOWN Reduce value or move down
• LV_KEY_RIGHT Add value or move right
• LV_KEY_LEFT Decrease the value or move to the left
• LV_KEY_ESC Close or exit ( For example, close the drop-down list )
• LV_KEY_DEL Delete ( For example, a character to the right of the text area )
• LV_KEY_BACKSPACE Delete the character on the left ( For example, in the text area )
• LV_KEY_HOME Go to the beginning / Top ( For example, in the text area )
• LV_KEY_END Go to last ( For example, in the text area ))
The most important special key is LV_KEY_NEXT/PREV、LV_KEY_ENTER and LV_KEY_UP/DOWN/LEFT/RIGHT. stay
read_cb Function , You should convert some keys to these special keys , To navigate through the group and interact with the selected objects . Use only LV_KEY_LEFT/RIGHT That's enough , Because most objects can use them to fully control . For encoders , You should only use LV_KEY_LEFT、LV_KEY_RIGHT and LV_KEY_ENTER.

1.3.1.2 Edit and navigation mode Edit and navigate mode

   Because the keypad has many keys , So it's easy to navigate between objects and edit them with the keypad . however , Encoder “ secret key ” Limited number , So it's hard to navigate with the default options . Navigation and editing are created to avoid this problem with the encoder .
   In navigation mode , Encoder LV_KEY_LEFT/RIGHT Converted to LV_KEY_NEXT/PREV. therefore , The next or previous object is selected by the rotary encoder . Press LV_KEY_ENTER Switch to edit mode .
   In edit mode , Usually use LV_KEY_NEXT/PREV To edit objects . According to the type of object , Short press or long press LV_KEY_ENTER Change back to navigation mode . Usually , An object cannot be pressed ( Such as slider ) Leave edit mode after a short click . But for those short clicks that make sense ( Button like ), It takes a long time to press .
   This function is usually used to switch between navigation mode and editing mode lv_group_set_editing(group,false);

1.3.2 style Styling

   If an object clicks focus through the touch pad , Or focus through encoder or keyboard , It will go to LV_STATE_FOCUSED. therefore , The emphasis style will be applied to it .
   If the object enters edit mode , It will enter LV_STATE_FOCUSED | LV_STATE_EDITED state , Therefore, these style attributes will be displayed .
   For a more detailed description , Please read the style section .

Two 、 Input device interface Input device interface

2.1 Enter device type Types of input devices

   notes : Most of the content in the article comes from lv_port_indev_template.c Modified from the template .
   To register an input device , Must be initialized lv_indev_drv_t Variable :: To initialize KeyPad As an example

2.1.1 Touch Pad , Mouse or any pointer Touchpad, mouse or any pointer

    static lv_indev_drv_t indev_drv;
    /*Initialize your keypad or keyboard if you have*/
    keypad_init();                                  // Initialize hardware 
    /*Register a keypad input device*/
    lv_indev_drv_init(&indev_drv);                  // Initialize registration 
    indev_drv.type = LV_INDEV_TYPE_KEYPAD;          // Initialize the registration type 
    indev_drv.read_cb = keypad_read;                // Initialize read callback 
    indev_keypad_or_encoder = lv_indev_drv_register(&indev_drv);    // Initialize callback implementation 

  indev_drv.type It can be one of the following situations .
• LV_INDEV_TYPE_POINTER Touch pad or mouse
• LV_INDEV_TYPE_KEYPAD keyboard
• LV_INDEV_TYPE_ENCODER Encoder and left / Turn right and choose
• LV_INDEV_TYPE_BUTTON The external keys are almost pressing the screen
read_cb Is a function pointer , It will be called periodically to report the current status of the input device .
   Input devices that can click on screen points fall into this category .

indev_drv.type = LV_INDEV_TYPE_POINTER;
indev_drv.read_cb = my_input_read;

void my_input_read(lv_indev_drv_t * drv, lv_indev_data_t*data)
{
    
	if(touchpad_pressed) {
    
		data->point.x = touchpad_x;
		data->point.y = touchpad_y;
		data->state = LV_INDEV_STATE_PRESSED;
	} else {
    
		data->state = LV_INDEV_STATE_RELEASED;
	}
}

   To set the mouse cursor , Please use lv_indev_set_cursor(my_indev, &img_cursor).(my_indev yes lv_indev_drv_register The return value of )

2.1.1 Keyboard or keyboard Keypad or keyboard

   A full keyboard with all letters or a simple keyboard with several navigation buttons belong here .
Using the keyboard / Keypad :
• use LV_INDEV_TYPE_KEYPAD Type register a read_cb function .
• You must create an object group :lv_group_t * g = lv_group_create(), And must use lv_group_add_obj(g, obj) Add objects to it
• The created group must be assigned to the input device :lv_indev_set_group(my_indev, g) (my_indev yes lv_indev_drv_register The return value of )
• Use LV_KEY_…… Navigate between objects in a group . About the available keys , see also lv_core/lv_group.h.

indev_drv.type = LV_INDEV_TYPE_KEYPAD;
indev_drv.read_cb = keyboard_read;
void keyboard_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
    
	data->key = last_key(); /*Get the last pressed or released key*/
	if(key_pressed()) data->state = LV_INDEV_STATE_PRESSED;
		else data->state = LV_INDEV_STATE_RELEASED;
}

2.1.1 Encoder Encoder

   Using the encoder, you can do 4 thing :
1. Press the button
2. Press and hold the button
3. turn left
4. turn right
In short ,Encoder The input device works like this :
• By rotating the encoder , You can focus on the next / The last object .
• When you're in a simple object ( Button like ) When the encoder is pressed up , It will be clicked ..
• If you're in a complex object ( As listing , Message box, etc ) Press the encoder up , The object will enter edit mode , In this way , You can navigate inside objects .
• To leave edit mode , Please press and hold the button .
Use the encoder ( Similar to a keypad ), Objects should be added to the group .

indev_drv.type = LV_INDEV_TYPE_ENCODER;
indev_drv.read_cb = encoder_read;
void encoder_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
    
	data->enc_diff = enc_get_new_moves();if(enc_pressed()) data->state = LV_INDEV_STATE_PRESSED;
	else data->state = LV_INDEV_STATE_RELEASED;
}

   Use buttons and encoder logic Using buttons with Encoder logic In addition to standard encoder behavior , You can also use its logic to navigate ( The focus of ) And using buttons to edit widgets . If you only have a few buttons available , Or you want to use buttons other than the encoder wheel , This is particularly convenient .
You need 3 Button :
• LV_KEY_ENTER Simulate pressing or pressing the encoder button
• LV_KEY_LEFT Analog encoder moves to the left
• LV_KEY_RIGHT Analog encoder moves to the right
• Other keys will be passed to the focused widget
If you press and hold these keys , It will simulate the encoder click and specify the period as indev_drv.long_press_rep_time.

2.1.1 Button Button

   A button is an external button next to the screen “ Hardware ” Button , They are assigned to specific coordinates of the screen . If a button is pressed , It will simulate pressing on the specified coordinates .( Similar to touch pad ) Assign buttons to coordinates and use lv_indev_set_button_points(my_indev,points_array).points_array It should be like this const lv_point_t points_array[] = { {12,30},{60,90}, …}

indev_drv.type = LV_INDEV_TYPE_BUTTON;
indev_drv.read_cb = button_read;
void button_read(lv_indev_drv_t * drv, lv_indev_data_t*data){
    
	static uint32_t last_btn = 0;				/*Store the last pressed button*/
	int btn_pr = my_btn_read(); 				/*Get the ID (0,1,2...) of the pressed button*/
	if(btn_pr >= 0) {
     							/*Is there a button press? (E.g. -1 indicated no button was pressed)*/
		last_btn = btn_pr; 						/*Save the ID of the pressed button*/
		data->state = LV_INDEV_STATE_PRESSED; 	/*Set the pressed state*/
	} else {
    
		data->state = LV_INDEV_STATE_RELEASED; 	/*Set the released state*/
	}
	data->btn = last_btn; 						/*Save the last button*/
}

2.2 Other features Other features

2.2.1 Parameters Parameters

   The default values of the following parameters can be in lv_indev_drv_t:
• scroll_limit The number of pixels to slide before actually scrolling the object .
• scroll_throw Roll throw ( momentum ) Slow down at [%]. The bigger the value is. , The faster you slow down .
• long_press_time Press send LV_EVENT_LONG_PRESSED Time for ( millisecond )
• long_press_rep_timeLV_EVENT_LONG_PRESSED_REPEAT Send interval ( millisecond )
• read_timer Point to lv_rimer The pointer to , Used to read input devices . Its parameters can be through lv_timer_…() Function to change .
lv_conf.h Medium LV_INDEV_DEF_READ_PERIOD Set the default read cycle .

2.2.1 feedback Feedback

   except read_cb, You can also do it in lv_indev_drv_t It is specified in feedback_cb Callback . When the input device sends any type of event , call Feedback_cb.( It's not about type ). It allows users to provide feedback , For example, in LV_EVENT_CLICKED Play sound on .

2.2.1 Associated with the display Associating with a display

   Each input device is associated with a display . By default , The new input device is added to the last created or explicitly selected ( Use lv_disp_set_default()) Showing . Related display storage , And can be in the drive disp Field change .

2.2.1 Buffer reading Buffered reading

   By default ,LVGL Will call... On a regular basis read_cb. Because of this intermittent polling , It is possible that some user gestures are missed .
   To solve this problem , You can write an event driven driver for your input device to buffer the measurement data . stay read_cb in , You can set buffered data , Instead of reading the input device . You can set data-> continue_reading Sign to tell LVGL There's more data to read , It should call again read_cb.

2.1 API

   About grouping API As shown below

lv_group_t * lv_group_create(void)					// Create a new object group 
void lv_group_del(lv_group_t * group)				// Delete group object 
void lv_group_set_default(lv_group_t * group)		// Set the default group . If used in a class ' add_to_def_group = true ' Enable this group , The new object will be added to the group .
lv_group_t * lv_group_get_default(void)				// Get default group 
void lv_group_add_obj(lv_group_t * group, struct _lv_obj_t * obj)	// Add an object to the group 
void lv_group_remove_obj(struct _lv_obj_t * obj)	// Remove an object from the group 
void lv_group_remove_all_objs(lv_group_t * group)	// Remove all objects in the group 
void lv_group_focus_obj(struct _lv_obj_t * obj)		// Focus on an object ( Defocus current )
void lv_group_focus_next(lv_group_t * group)		// Focus on the next object in the group ( Defocus the current object )
void lv_group_focus_prev(lv_group_t * group)		// Focus on the previous object in a group ( Defocus the current object )
void lv_group_focus_freeze(lv_group_t * group, bool en)				// Don't change the focus of the current object 
lv_res_t lv_group_send_data(lv_group_t * group, uint32_t c)			// Send a control character to the focus object of the group 
void lv_group_set_focus_cb(lv_group_t * group, lv_group_focus_cb_t focus_cb)			// Set a function for a group , When a new object is focused , The function will be called 
void lv_group_set_refocus_policy(lv_group_t * group, lv_group_refocus_policy_t policy)	// Set whether the next or previous item in the group is the focus , If the current focus object is deleted .
struct _lv_obj_t * lv_group_get_focused(const lv_group_t * group)	// Get focus object , If not, get NULL
lv_group_focus_cb_t lv_group_get_focus_cb(const lv_group_t * group)	// Get the focus callback function of a group 
void lv_group_set_editing(lv_group_t * group, bool edit)			// Manually set the current mode ( Edit or navigate ).
bool lv_group_get_editing(const lv_group_t * group)					// Get the current mode ( Edit or navigate ).
void lv_group_set_wrap(lv_group_t * group, bool en)					// set focus next/prev Is it allowed to go from first->last or last->first Objects are packaged .
bool lv_group_get_wrap(lv_group_t * group)							// Get focus next/prev Is it allowed to go from first->last or last->first Objects are packaged .
uint32_t lv_group_get_obj_count(lv_group_t * group)					// Get the number of objects in the group 

   About input devices API As shown below

void lv_indev_read_timer_cb(lv_timer_t * timer)						// Call periodically to read the input device 
void lv_indev_enable(lv_indev_t * indev, bool en)					// Input device enable 
lv_indev_t * lv_indev_get_act(void)									// Get the input device currently processed . Can also be used in functions .
lv_indev_type_t lv_indev_get_type(const lv_indev_t * indev)			// Get the type of an input device 
void lv_indev_reset(lv_indev_t * indev, lv_obj_t * obj)				// Reset one or all input devices 
void lv_indev_reset_long_press(lv_indev_t * indev)					// Reset the long press state of the input device 
void lv_indev_set_cursor(lv_indev_t * indev, lv_obj_t * cur_obj)	// Input device for pointer (LV_INPUT_TYPE_POINTER and LV_INPUT_TYPE_BUTTON) Set cursor 
void lv_indev_set_group(lv_indev_t * indev, lv_group_t * group)		// Set the target group for the keyboard input device ( by LV_INDEV_TYPE_KEYPAD)
void lv_indev_set_button_points(lv_indev_t * indev, const lv_point_t points[])	// by LV_INDEV_TYPE_BUTTON Set an array of points .
void lv_indev_get_point(const lv_indev_t * indev, lv_point_t * point)// Get the last point of an input device ( about LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
lv_dir_t lv_indev_get_gesture_dir(const lv_indev_t * indev)			// Get the current gesture directly 
uint32_t lv_indev_get_key(const lv_indev_t * indev)					// Get the last key pressed by an input device (LV_INDEV_TYPE_KEYPAD)
lv_dir_t lv_indev_get_scroll_dir(const lv_indev_t * indev)			// Check the scrolling direction of the current input device ( about LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
lv_obj_t * lv_indev_get_scroll_obj(const lv_indev_t * indev)		// Gets the currently scrolling object (LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
void lv_indev_get_vect(const lv_indev_t * indev, lv_point_t * point)// Get the motion vector of an input device ( about LV_INDEV_TYPE_POINTER and LV_INDEV_TYPE_BUTTON)
void lv_indev_wait_release(lv_indev_t * indev)						// The next s Don't do anything before release 
lv_obj_t * lv_indev_get_obj_act(void)								// Gets a pointer to the currently active object in the currently processed input device .
lv_timer_t * lv_indev_get_read_timer(lv_disp_t * indev)				// Get one indev Read the pointer of the timer and modify its parameters ' lv_timer_… The function of .
lv_obj_t * lv_indev_search_obj(lv_obj_t * obj, lv_point_t * point)	// Search the top , Clickable object points 

void lv_indev_drv_init(struct _lv_indev_drv_t * driver)				// Initialize an input device driver with default values . It is used to determine the known value in the field , Not memory garbage . After it, you can set the field .
lv_indev_t * lv_indev_drv_register(struct _lv_indev_drv_t * driver)	// Register an initialized input device driver .
void lv_indev_drv_update(lv_indev_t * indev, struct _lv_indev_drv_t * new_drv)// Update the driver at run time .
lv_indev_t * lv_indev_get_next(lv_indev_t * indev)					// Get the next input device .
void _lv_indev_read(lv_indev_t * indev, lv_indev_data_t * data)		// Read data from input device .

3、 ... and 、 Example

   If you need to use an external input device, you need to initialize the external device , I'm here for external devices keypad And use encoder Modify the use of encoder mode , I don't use a real encoder here , Instead, the gyroscope is used as the input control , Take the pitch angle and roll angle of the gyroscope as the input variation parameters ( Key ), The rolling angle realizes the left and right rotation of the encoder , The pitch angle realizes the pressing and releasing of the encoder .
   initialization lv_port_indev_Key.c file

#include "lv_port_indev_Key.h"

static const char *TAG = "lv_port_indev";

static void keypad_init(void);
static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static uint32_t keypad_get_key(void);

static void encoder_init(void);
static void encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data);
static void encoder_handler(void);

lv_indev_t * indev_keypad_or_encoder;

static int32_t encoder_diff;
static lv_indev_state_t encoder_state;

void keypad_lv_port_indev_init(void)
{
    
    static lv_indev_drv_t indev_drv;
    /*Initialize your keypad or keyboard if you have*/
    keypad_init();                                  // Initialize hardware 
    /*Register a keypad input device*/
    lv_indev_drv_init(&indev_drv);                  // Initialize registration 
    indev_drv.type = LV_INDEV_TYPE_KEYPAD;          // Initialize the registration type 
    indev_drv.read_cb = keypad_read;                // Initialize read callback 
    indev_keypad_or_encoder = lv_indev_drv_register(&indev_drv);    // Initialize callback implementation 
}

/*------------------ * Keypad * -----------------*/

/*Initialize your keypad*/
static void keypad_init(void)
{
    
    /*Your code comes here*/
    key_init();
}

/*Will be called by the library to read the mouse*/
static void keypad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
    
    static uint32_t last_key = 0;
    /*Get whether the a key is pressed and save the pressed key*/
    uint32_t act_key = keypad_get_key();
    if(act_key != 0) {
    
        data->state = LV_INDEV_STATE_PR;
        /*Translate the keys to LVGL control characters according to your key definitions*/
        switch(act_key) {
    
        case 1:
            act_key = LV_KEY_NEXT;
            break;
        case 2:
            act_key = LV_KEY_PREV;
            break;
        case 3:
            act_key = LV_KEY_LEFT;
            break;
        case 4:
            act_key = LV_KEY_RIGHT;
            break;
        case 5:
            act_key = LV_KEY_ENTER;
            break;
        }

        last_key = act_key;
    } else {
    
        data->state = LV_INDEV_STATE_REL;
    }
    data->key = last_key;
}

/*Get the currently being pressed key. 0 if no key is pressed*/
static uint32_t keypad_get_key(void)
{
    
    uint8_t key_value = 0;              // Press the key to return the value 
#if UserGyroscope 
    short aacx = 0, aacy = 0, aacz = 0; // Original number of acceleration sensors 
    float pitch, roll;
    Get_Accelerometer(&aacx, &aacy, &aacz);         // get data 
    LIS3DH_get_angleXY(aacx,aacy,aacz,&pitch,&roll);// Deal with Euler angle 
    // ESP_LOGI(TAG,"angle: x=%.3f, y=%.3f,\r\n",pitch,roll);
    if (pitch > 66){
    
        key_value = LV_KEY_ENTER;       
        // ESP_LOGI(TAG,"LV_KEY_ENTER\r\n");
    }
    else if(pitch < -66){
    
        key_value = LV_KEY_NEXT;
        // ESP_LOGI(TAG,"LV_KEY_NEXT\r\n");
    }
    else if(roll > 66){
    
        key_value = LV_KEY_LEFT;
        // ESP_LOGI(TAG,"LV_KEY_LEFT\r\n");
    }
    else if(roll < -66){
    
        key_value = LV_KEY_RIGHT;
        // ESP_LOGI(TAG,"LV_KEY_RIGHT\r\n");
    }
#else
    // Key trigger   The way 
    if(gpio_get_level(KEY_LEFT)==1)
        key_value = LV_KEY_LEFT;
    else if(gpio_get_level(KEY_CENTER)==1)
        key_value = LV_KEY_ENTER;
    else if(gpio_get_level(KEY_RIGHT)==1)
        key_value = LV_KEY_RIGHT;
    else if(gpio_get_level(KEY_RIGHT_ADD)==1)
        key_value = LV_KEY_NEXT;
#endif
    return key_value;
}

void encoder_lv_port_indev_init(void)
{
    
    static lv_indev_drv_t indev_drv;
    /*Initialize your encoder if you have*/
    encoder_init();

    /*Register a encoder input device*/
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_ENCODER;
    indev_drv.read_cb = encoder_read;
    indev_keypad_or_encoder = lv_indev_drv_register(&indev_drv);
}

/*------------------ * Encoder * -----------------*/

/*Initialize your keypad*/
static void encoder_init(void)
{
    
    /*Your code comes here*/
    key_init();
}

/*Will be called by the library to read the encoder*/
static void encoder_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data)
{
    
    encoder_handler();              // State detection 
    data->enc_diff = encoder_diff;  // Get key value 
    data->state = encoder_state;    // Get the key status value 

    encoder_diff = 0;               // Increment setting bit 0
}

/*Call this function in an interrupt to process encoder events (turn, press)*/
static void encoder_handler(void)
{
    
#if UserGyroscope 
    /*Your code comes here*/
    short aacx = 0, aacy = 0, aacz = 0; // Original number of acceleration sensors 
    float pitch, roll;
    Get_Accelerometer(&aacx, &aacy, &aacz);         // get data 
    LIS3DH_get_angleXY(aacx,aacy,aacz,&pitch,&roll);// Deal with Euler angle 
	// ESP_LOGI(TAG,"angle: x=%.3f, y=%.3f,\r\n",pitch,roll);

    if (pitch > 66){
    
        encoder_state = LV_INDEV_STATE_PR;      // Press state 
        // ESP_LOGI(TAG,"LV_INDEV_STATE_PR\r\n");
    }
    else {
     
        encoder_state = LV_INDEV_STATE_REL;     // Release status 
        // ESP_LOGI(TAG,"LV_INDEV_STATE_REL\r\n");
    }
    if(roll > 66 && pre_flag){
    
        encoder_diff ++;                        // Increase the direction of rotation 
        pre_flag = 0;
        // ESP_LOGI(TAG,"encoder_diff ++\r\n");
        vTaskDelay(10 / portTICK_PERIOD_MS);    // Delay chattering 
    }
    else if(roll < -66 && pre_flag){
                // Reduce the direction of rotation 
        encoder_diff --;
        pre_flag = 0;
        // ESP_LOGI(TAG,"encoder_diff --\r\n");
        vTaskDelay(10 / portTICK_PERIOD_MS);    // Delay chattering 
    }else{
    
		pre_flag = 1;                           // Press the flag bit 
    }
#else
    // Key trigger   The way 
    if(gpio_get_level(KEY_LEFT)==1){
    
        encoder_diff ++;                        // Increase the direction of rotation 
        pre_flag = 0;
    }else if(gpio_get_level(KEY_RIGHT)==1){
    
        encoder_diff ++;                        // Increase the direction of rotation 
        pre_flag = 0;
    }
    if(gpio_get_level(KEY_CENTER)==1){
    
        encoder_state = LV_INDEV_STATE_PR;      // Press state 
    }
    else{
    
        encoder_state = LV_INDEV_STATE_REL;     // Release status 
    }
#endif
}

void my_lv_port_indev_init(void)
{
    
#if Encoder
    encoder_lv_port_indev_init();               // Initialize encoder 
    ESP_LOGI(TAG,"init_encoder_indev\r\n");
#else
    keypad_lv_port_indev_init();                // Initialization key kaypad
    ESP_LOGI(TAG,"init_keypad_indev\r\n");
#endif
}

   initialization lv_port_indev_Key.h file

#ifndef LV_PORT_INDEV_Key_H
#define LV_PORT_INDEV_Key_H

#include "../components/lvgl/lvgl.h"
#include "my_key.h"
#include "lis3dh.h"

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"

#include <stdio.h>
#include "esp_log.h"

#define Encoder 1 // Define whether to use encoder mode or Keypad Pattern 
#define UserGyroscope 0 // Define whether to use gyroscope mode or ordinary key input mode 

int pre_flag;               // Press the flag bit 

extern lv_indev_t *  indev_keypad_or_encoder;
void my_lv_port_indev_init(void);
#endif /*LV_PORT_INDEV_TEMPL_H*/

   The test program

/************************************************* *  The name of the function  : key_pad_event_cb *  ginseng   Count  : lv_event_t * e  Callback events  *  The functionality  :  The event callback displays  *************************************************/
static void key_pad_event_cb(lv_event_t * e)
{
    
   lv_event_code_t code = lv_event_get_code(e);			    // Get event code 
   lv_obj_t * target = lv_event_get_target(e);			   	// Get the object to which the event is sent 
   lv_obj_t * cur_target = lv_event_get_current_target(e);  // Get the object to which the event was originally sent ( Same as when event bubbling is enabled lv_event_get_target Different )
   lv_obj_t * label = lv_event_get_user_data(e);	        // Get as lv_obj_add_event_cb The pointer passed by the last parameter of 
   lv_obj_t * btn = lv_event_get_param(e);			        // Get as lv_event_send The last parameter of the passed parameter 
   if(code==LV_EVENT_KEY){
    
      uint32_t key=lv_event_get_key(e);                     // Get key events 
      if(key == LV_KEY_ENTER){
    
         printf("\r\n *ENTER_key=%d,code=%d",key,(uint32_t)code);
      }else if(key == LV_KEY_NEXT){
    
         printf("\r\n *NEXT_key=%d,code=%d",key,(uint32_t)code);
      }else if(key == LV_KEY_LEFT){
    
         printf("\r\n *LEFT_key=%d,code=%d",key,(uint32_t)code);
      }else if(key == LV_KEY_RIGHT){
    
         printf("\r\n *RIGHT_key=%d,code=%d",key,(uint32_t)code);
      }
   }
}
/************************************************* *  The name of the function  : Key_pad_test *  ginseng   Count  :  nothing  *  The functionality  :  Event input test  *************************************************/
void Key_pad_test()
{
    
   lv_group_t * group = lv_group_create();            // Create grouped variables 
   lv_indev_set_group(indev_keypad_or_encoder,group); // Set the target group for the keyboard input device 

   static lv_style_t style;                           // Create styles 
   lv_style_init(&style);                             // Initialize style 

   lv_style_set_radius(&style,3);                     // Setting fillet 
   lv_style_set_bg_color(&style,lv_palette_main(LV_PALETTE_RED)); // Set the background color 
   lv_style_set_bg_opa(&style,LV_OPA_COVER);          // Set background transparency 

   lv_style_set_border_color(&style,lv_palette_darken(LV_PALETTE_RED,2));// Set widening 
   lv_style_set_border_opa(&style,LV_OPA_80);         // Set the widening transparency 

   lv_obj_t * btn1 = lv_btn_create(lv_scr_act());     // establish btn object 
   // lv_obj_add_flag(btn1,LV_OBJ_FLAG_HIDDEN); // Add flag bit 
   lv_obj_add_style(btn1,&style,LV_STATE_PRESSED);    // Add style to key object 
   lv_obj_add_event_cb(btn1,key_pad_event_cb,LV_EVENT_KEY,NULL);  // Add key callback function 
   lv_obj_align(btn1,LV_ALIGN_CENTER,-40,0);          // centered 

   lv_obj_t * label1 = lv_label_create(btn1);         // establish label
   lv_label_set_text(label1,"Btn1");                  // Show label Word content 
   
   lv_obj_t * btn2 = lv_btn_create(lv_scr_act());     // establish btn object 
   // lv_obj_add_flag(btn2,LV_OBJ_FLAG_CHECKABLE); // Add flag bit 
   lv_obj_add_style(btn2,&style,LV_STATE_PRESSED);    // Add style to key object 
   lv_obj_add_event_cb(btn2,key_pad_event_cb,LV_EVENT_KEY,NULL);  // Add key callback function 
   lv_obj_align(btn2,LV_ALIGN_CENTER,40,0);           // centered 

   lv_obj_t * label2 = lv_label_create(btn2);         // establish label
   lv_label_set_text(label2,"Btn2");                  // Show label Word content 

   lv_group_add_obj(group,btn1);                      // add group 
   lv_group_add_obj(group,btn2);                      // add group 
}

   It is worth noting that external drivers need to be initialized when using , The initialization position needs to be placed after the initialization of the screen .
 Insert picture description here
The test shows the video :LVGL8 External input key input

版权声明
本文为[Please call me Xiao Peng]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/04/202204210609450406.html