Integrating STM32 with LVGL v9 Touchscreen

In the previous article “Porting LVGL v9 to STM32”, we completed the porting of LVGL on STM32. In the article “STM32 Driver for XPT2046 Touchscreen”, we implemented the driver for the XPT2046 touchscreen chip.Next, we will combine LVGL with the touchscreen to enable interaction through buttons and other controls on the screen.1. Modify the Touch Driver to Convert to Screen CoordinatesFirst, modify the previous <span>xpt2046</span> driver file to convert the raw data returned by the touch chip into screen pixel coordinates.In <span>User/Src/touch_xpt2046.c</span>, modify the <span>Touch_Get_Pos()</span> function and add a coordinate mapping function <span>map_axis()</span>:

// Convert the coordinate range of in to the coordinate range of out
static uint16_t map_axis(uint16_t coord, uint16_t in_min, uint16_t in_max, uint16_t out_min, uint16_t out_max) {
    return (coord - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

void Touch_Get_Pos(uint16_t* x, uint16_t* y) {
    uint16_t x_sum = 0, y_sum = 0;
    // Average value from multiple samples
    for (int i = 0; i < SAMPLE_TIMES; i++) {
        x_sum += Touch_Read_Data(0x90);
        y_sum += Touch_Read_Data(0xD0);
    }
    x_sum = x_sum / SAMPLE_TIMES;
    y_sum = y_sum / SAMPLE_TIMES;
    // The x coordinate range is 0~LCD_WIDTH-1, y coordinate range is 0~LCD_HEIGHT-1, using max value + 1 to indicate touch termination
    if (x_sum == 4095 || y_sum == 0) {
        *x = LCD_WIDTH;
        *y = LCD_HEIGHT;
    } else {
        // Set the valid range of xpt2046 return values to 100~4000, for more accuracy, a screen calibration function can be implemented to determine the range
        *x = map_axis(x_sum, 100, 4000, 0, LCD_WIDTH - 1);
        *y = map_axis(y_sum, 100, 4000, 0, LCD_HEIGHT - 1);
    }
}

2. Register Input Device in LVGL

Next, in <span>main.c</span>, write the touch reading function <span>touch_xpt2046_read()</span> to allow LVGL to obtain coordinate data from the driver:

static void touch_xpt2046_read(lv_indev_t * indev, lv_indev_data_t * data) {
    (void)data;
    (void)indev;
    static uint16_t x = 0;
    static uint16_t y = 0;
    if (!touch_screen_pressed) {
        data->state = LV_INDEV_STATE_REL;
    } else {
        Touch_Get_Pos(&x, &y);
        if (x == 320 || y == 240) {
            touch_screen_pressed = false;
            data->state = LV_INDEV_STATE_REL;
        } else {
            data->state = LV_INDEV_STATE_PR;
            data->point.x = x;
            data->point.y = 240 - 1 - y; // The coordinate system of xpt2046 is opposite to that of lvgl on the y-axis. Here we make a conversion.
        }
    }
}

Then implement a function to create the input device object:

static void create_input_device() {
    lv_indev_t * indev = lv_indev_create();
    lv_indev_set_type(indev, LV_INDEV_TYPE_POINTER);
    lv_indev_set_read_cb(indev, touch_xpt2046_read);
}

Then in the <span>main()</span> function, after successfully creating the <span>lv_disp_t</span>, call <span>create_input_device()</span> so that LVGL can receive input events through the touchscreen.

3. Implement Button Click Event

Next, we will write a callback function for the previous button to implement a simple click count:

static void btn_event_cb(lv_event_t* e) {
    static int count = 0;
    lv_obj_t * target_label = lv_event_get_user_data(e);
    lv_label_set_text_fmt(target_label, "You clicked %d times", ++count);
}
And bind this function to the button's click event:

lv_obj_add_event_cb(button, btn_event_cb, LV_EVENT_CLICKED, label);
Thus, when the user clicks the screen button, the label text will update in real-time.

4. Running Effect

After downloading the program to the development board, you can see that the button in the LVGL interface now supports touch clicks, and each time the button is clicked, the text will update the count, achieving a complete touch interaction function.

Through this content, we have successfully made LVGL + STM32 + ILI9341 + XPT2046 work together. In the future, we can expand more features based on this, such as:

  • Touch calibration function;

  • Multi-page menu switching;

  • Custom controls and animation effects.

Leave a Comment