diff --git a/stm32f103_lvgl_8080lcd/Core/Inc/bsp_xpt2046.h b/stm32f103_lvgl_8080lcd/Core/Inc/bsp_xpt2046.h index 1eff3e1..9927004 100644 --- a/stm32f103_lvgl_8080lcd/Core/Inc/bsp_xpt2046.h +++ b/stm32f103_lvgl_8080lcd/Core/Inc/bsp_xpt2046.h @@ -4,6 +4,10 @@ #include "stm32f1xx_hal.h" #define BSP_XPT2046_SPI hspi2 +#define BSP_XPT2046_EEPROM_I2C hi2c2 + +#define BSP_XPT2046_EEPROM_I2C_OFFSET 0 +#define BSP_XPT2046_AVG_SAMPLES 16 //必须是偶数 HAL_StatusTypeDef bsp_xpt2046_get_touch_status(void); void bsp_xpt2046_get_adc(uint16_t *x_adc, uint16_t *y_adc); diff --git a/stm32f103_lvgl_8080lcd/Core/Src/app_main.c b/stm32f103_lvgl_8080lcd/Core/Src/app_main.c index b38c17c..e438ffa 100644 --- a/stm32f103_lvgl_8080lcd/Core/Src/app_main.c +++ b/stm32f103_lvgl_8080lcd/Core/Src/app_main.c @@ -18,7 +18,7 @@ void app_main(void) lv_init(); lv_port_disp_init(); lv_create_tick(); - + uint8_t force = HAL_GPIO_ReadPin(KEY1_GPIO_Port, KEY1_Pin) == GPIO_PIN_RESET; touchscreen_calibration(force); diff --git a/stm32f103_lvgl_8080lcd/Core/Src/bsp_xpt2046.c b/stm32f103_lvgl_8080lcd/Core/Src/bsp_xpt2046.c index 76b155c..a6df190 100644 --- a/stm32f103_lvgl_8080lcd/Core/Src/bsp_xpt2046.c +++ b/stm32f103_lvgl_8080lcd/Core/Src/bsp_xpt2046.c @@ -1,6 +1,7 @@ #include "bsp_xpt2046.h" #include +#include #include "main.h" #include "util_delay_us.h" @@ -15,7 +16,7 @@ static uint16_t bsp_xpt2046_conv(uint8_t cmd) HAL_GPIO_WritePin(T_CS_GPIO_Port, T_CS_Pin, GPIO_PIN_RESET); //选中芯片 HAL_SPI_Transmit(&BSP_XPT2046_SPI, &cmd, 1, 200); //发送指令 - delay_us(4); //等待转换完成 + delay_us(2); //等待转换完成 实际延时超过所需最短延时4us uint8_t received_data[2]; uint8_t transmit_data[2] = { 0x00, 0x00 }; //接收时MOSI必须保持固定电平 否则数据出错 @@ -25,10 +26,30 @@ static uint16_t bsp_xpt2046_conv(uint8_t cmd) return ((uint16_t)received_data[0] << 8 | received_data[1]) >> 4; } +static int qsort_comparator(const void *a, const void *b) +{ + return *(uint16_t *)a - *(uint16_t *)b; +} + void bsp_xpt2046_get_adc(uint16_t *x_adc, uint16_t *y_adc) { - *x_adc = bsp_xpt2046_conv(BSP_XPT2046_CMD_CONV_X); - *y_adc = bsp_xpt2046_conv(BSP_XPT2046_CMD_CONV_Y); + uint16_t x_adcs[BSP_XPT2046_AVG_SAMPLES], y_adcs[BSP_XPT2046_AVG_SAMPLES]; + for (uint8_t i = 0; i < BSP_XPT2046_AVG_SAMPLES; i ++) { + x_adcs[i] = bsp_xpt2046_conv(BSP_XPT2046_CMD_CONV_X); + y_adcs[i] = bsp_xpt2046_conv(BSP_XPT2046_CMD_CONV_Y); + } + + qsort(x_adcs, BSP_XPT2046_AVG_SAMPLES, sizeof(x_adcs[0]), qsort_comparator); + qsort(y_adcs, BSP_XPT2046_AVG_SAMPLES, sizeof(y_adcs[0]), qsort_comparator); //升序排序 + + uint32_t x_adc_sum = 0, y_adc_sum = 0; //求中间n/2个数的平均值 + for (uint8_t i = BSP_XPT2046_AVG_SAMPLES / 4; i < BSP_XPT2046_AVG_SAMPLES - BSP_XPT2046_AVG_SAMPLES / 4; i ++) { + x_adc_sum += x_adcs[i]; + y_adc_sum += y_adcs[i]; + } + + *x_adc = x_adc_sum / (BSP_XPT2046_AVG_SAMPLES / 2); + *y_adc = y_adc_sum / (BSP_XPT2046_AVG_SAMPLES / 2); } HAL_StatusTypeDef bsp_xpt2046_get_touch_status(void) @@ -38,9 +59,8 @@ HAL_StatusTypeDef bsp_xpt2046_get_touch_status(void) HAL_StatusTypeDef bsp_xpt2046_get_coord(uint16_t *x, uint16_t *y) { - if (tp_x_factor == 0 || tp_x_offset == 0 || tp_y_factor == 0 || tp_y_offset == 0 || - tp_lcd_x_pixels == 0 || tp_lcd_y_pixels == 0) { - return HAL_ERROR; + if (tp_x_factor == 0 || tp_y_factor == 0 || tp_lcd_x_pixels == 0) { + return HAL_ERROR; } uint16_t x_adc, y_adc; @@ -60,17 +80,49 @@ HAL_StatusTypeDef bsp_xpt2046_calibrate(const uint16_t x_pos[], const uint16_t y tp_y_factor = (float)(y_pos[1] - y_pos[0]) / (y_val[1] - y_val[0]); tp_y_offset = (float)y_pos[0] - tp_y_factor * y_val[0]; - //将校准值写入EEPROM - printf("tp_x_factor=%.3f, tp_x_offset=%.3f\r\n", tp_x_factor, tp_x_offset); - printf("tp_y_factor=%.3f, tp_y_offset=%.3f\r\n", tp_y_factor, tp_y_offset); + printf("tp_x_factor=%.3f, tp_x_offset=%.3f\n", tp_x_factor, tp_x_offset); + printf("tp_y_factor=%.3f, tp_y_offset=%.3f\n", tp_y_factor, tp_y_offset); - return HAL_OK; + //将校准值写入EEPROM + HAL_StatusTypeDef status; + uint8_t addr = BSP_XPT2046_EEPROM_I2C_OFFSET; + status |= HAL_I2C_Mem_Write(&BSP_XPT2046_EEPROM_I2C, 0x50 << 1, addr, 1, (uint8_t *)&tp_x_factor, sizeof(tp_x_factor), 200); + addr += sizeof(tp_x_factor); + HAL_Delay(2); //EEPROM写入比较慢 + status |= HAL_I2C_Mem_Write(&BSP_XPT2046_EEPROM_I2C, 0x50 << 1, addr, 1, (uint8_t *)&tp_x_offset, sizeof(tp_x_offset), 200); + addr += sizeof(tp_x_offset); + HAL_Delay(2); + status |= HAL_I2C_Mem_Write(&BSP_XPT2046_EEPROM_I2C, 0x50 << 1, addr, 1, (uint8_t *)&tp_y_factor, sizeof(tp_y_factor), 200); + addr += sizeof(tp_y_factor); + HAL_Delay(2); + status |= HAL_I2C_Mem_Write(&BSP_XPT2046_EEPROM_I2C, 0x50 << 1, addr, 1, (uint8_t *)&tp_y_offset, sizeof(tp_y_offset), 200); + + return status; } HAL_StatusTypeDef bsp_xpt2046_load_calib_data(uint16_t lcd_x_pixels, uint16_t lcd_y_pixels) { + if (lcd_x_pixels == 0 || lcd_y_pixels == 0) { + return HAL_ERROR; + } + tp_lcd_x_pixels = lcd_x_pixels; tp_lcd_y_pixels = lcd_y_pixels; - return HAL_OK; + HAL_StatusTypeDef status; + uint8_t addr = BSP_XPT2046_EEPROM_I2C_OFFSET; + status |= HAL_I2C_Mem_Read(&BSP_XPT2046_EEPROM_I2C, 0x50 << 1, addr, 1, (uint8_t *)&tp_x_factor, sizeof(tp_x_factor), 200); + addr += sizeof(tp_x_factor); + status |= HAL_I2C_Mem_Read(&BSP_XPT2046_EEPROM_I2C, 0x50 << 1, addr, 1, (uint8_t *)&tp_x_offset, sizeof(tp_x_offset), 200); + addr += sizeof(tp_x_offset); + status |= HAL_I2C_Mem_Read(&BSP_XPT2046_EEPROM_I2C, 0x50 << 1, addr, 1, (uint8_t *)&tp_y_factor, sizeof(tp_y_factor), 200); + addr += sizeof(tp_y_factor); + status |= HAL_I2C_Mem_Read(&BSP_XPT2046_EEPROM_I2C, 0x50 << 1, addr, 1, (uint8_t *)&tp_y_offset, sizeof(tp_y_offset), 200); + + if (tp_x_factor == 0 || tp_y_factor == 0 || *(uint32_t *)&tp_x_factor == 0xFFFFFFFF || *(uint32_t *)&tp_y_factor == 0xFFFFFFFF || + tp_x_offset == 0 || tp_y_offset == 0 || *(uint32_t *)&tp_x_offset == 0xFFFFFFFF || *(uint32_t *)&tp_y_offset == 0xFFFFFFFF) { + return HAL_ERROR; + } else { + return HAL_OK; + } } diff --git a/stm32f103_lvgl_8080lcd/Core/Src/lv_port_indev.c b/stm32f103_lvgl_8080lcd/Core/Src/lv_port_indev.c index 0170b7d..20355d4 100644 --- a/stm32f103_lvgl_8080lcd/Core/Src/lv_port_indev.c +++ b/stm32f103_lvgl_8080lcd/Core/Src/lv_port_indev.c @@ -1,6 +1,5 @@ #include "lv_port_indev.h" -#include "main.h" #include "bsp_xpt2046.h" lv_indev_t *indev_touchpad; @@ -9,13 +8,18 @@ static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) { static lv_coord_t last_x = 0; static lv_coord_t last_y = 0; - - - if(HAL_GPIO_ReadPin(T_PEN_GPIO_Port, T_PEN_Pin) == GPIO_PIN_RESET) { + + if(bsp_xpt2046_get_touch_status() == HAL_OK) { uint16_t x_coord, y_coord; - bsp_xpt2046_get_coord(&x_coord, &y_coord); - last_x = x_coord; last_y = y_coord; - data->state = LV_INDEV_STATE_PR; + HAL_StatusTypeDef status = bsp_xpt2046_get_coord(&x_coord, &y_coord); + + if (status == HAL_OK) { + last_x = x_coord; last_y = y_coord; + data->state = LV_INDEV_STATE_PR; + } else { + data->state = LV_INDEV_STATE_REL; + LV_LOG_ERROR("Touchscreen is not properly calibrated!"); + } } else { data->state = LV_INDEV_STATE_REL; } @@ -26,10 +30,10 @@ static void touchpad_read(lv_indev_drv_t * indev_drv, lv_indev_data_t * data) void lv_port_indev_init(void) { - static lv_indev_drv_t indev_drv; + static lv_indev_drv_t indev_drv; - lv_indev_drv_init(&indev_drv); - indev_drv.type = LV_INDEV_TYPE_POINTER; - indev_drv.read_cb = touchpad_read; - indev_touchpad = lv_indev_drv_register(&indev_drv); + lv_indev_drv_init(&indev_drv); + indev_drv.type = LV_INDEV_TYPE_POINTER; + indev_drv.read_cb = touchpad_read; + indev_touchpad = lv_indev_drv_register(&indev_drv); } diff --git a/stm32f103_lvgl_8080lcd/Core/Src/touchscreen_calibration.c b/stm32f103_lvgl_8080lcd/Core/Src/touchscreen_calibration.c index 4fa5fd9..94d2772 100644 --- a/stm32f103_lvgl_8080lcd/Core/Src/touchscreen_calibration.c +++ b/stm32f103_lvgl_8080lcd/Core/Src/touchscreen_calibration.c @@ -2,6 +2,7 @@ #include #include "main.h" +#include "lvgl.h" #include "bsp_lcd_ili9341.h" #include "bsp_xpt2046.h" @@ -20,25 +21,72 @@ void draw_cross(uint16_t x_center, uint16_t y_center) void touchscreen_calibration(uint8_t force) { - uint16_t x_pos[2] = { 20, BSP_LCD_X_PIXELS - 20 }, y_pos[2] = { 20, BSP_LCD_Y_PIXELS - 20 }; - uint16_t x_val[2], y_val[2]; + HAL_StatusTypeDef status = bsp_xpt2046_load_calib_data(BSP_LCD_X_PIXELS, BSP_LCD_Y_PIXELS); + if (status == HAL_OK && force == 0) { + printf("load touchscreen calibration data from eeprom success\n"); + return; + } else { + printf("load touchscreen calibration data from eeprom failed, re-calibrating\n"); + } - draw_cross(x_pos[0], y_pos[0]); - while (bsp_xpt2046_get_touch_status() == HAL_ERROR); - HAL_Delay(50); + uint16_t x_pos[2], y_pos[2], x_val[2], y_val[2]; + + lv_obj_t *cross = lv_obj_create(lv_scr_act()); + lv_obj_set_size(cross, 59, 59); //创建一个59x59大小的容器 + lv_obj_clear_flag(cross, LV_OBJ_FLAG_SCROLLABLE); //防止出现滚动条 + lv_obj_set_style_bg_opa(cross, LV_OPA_TRANSP, 0); + lv_obj_set_style_border_opa(cross, LV_OPA_TRANSP, 0); //设置容器完全透明 + + lv_style_t style_line; + lv_style_init(&style_line); //创建线条样式 + lv_style_set_line_width(&style_line, 3); + lv_style_set_line_color(&style_line, lv_palette_main(LV_PALETTE_RED)); //红色 3像素宽 + + const static lv_point_t cross_ver_line_points[2] = { { 0, 0 }, { 0, 30 } }; + lv_obj_t *cross_ver_line = lv_line_create(cross); //十字中的竖线 + lv_line_set_points(cross_ver_line, cross_ver_line_points, 2); + lv_obj_add_style(cross_ver_line, &style_line, 0); + lv_obj_center(cross_ver_line); //居中对齐 + + const static lv_point_t cross_hor_line_points[2] = { { 0, 0 }, { 30, 0 } }; + lv_obj_t *cross_hor_line = lv_line_create(cross); //十字中的横线 + lv_line_set_points(cross_hor_line, cross_hor_line_points, 2); + lv_obj_add_style(cross_hor_line, &style_line, 0); + lv_obj_center(cross_hor_line); + + lv_obj_align(cross, LV_ALIGN_TOP_LEFT, 0, 0); //十字首先置于左上角 + lv_area_t cross_obj_area; + lv_obj_update_layout(cross); //需要先重新计算布局才能获取容器尺寸 + lv_obj_get_content_coords(cross, &cross_obj_area); //获取容器尺寸 + + x_pos[0] = (cross_obj_area.x1 + cross_obj_area.x2) / 2; + y_pos[0] = (cross_obj_area.y1 + cross_obj_area.y2) / 2; //计算得到十字中点坐标 + + while (bsp_xpt2046_get_touch_status() != HAL_OK) { + lv_task_handler(); + } bsp_xpt2046_get_adc(&x_val[0], &y_val[0]); - printf("x: 0x%03X, y: 0x%03X\r\n", x_val[0], y_val[0]); - HAL_Delay(50); while (bsp_xpt2046_get_touch_status() == HAL_OK); - draw_cross(x_pos[1], y_pos[1]); - while (bsp_xpt2046_get_touch_status() == HAL_ERROR); - HAL_Delay(50); + lv_obj_align(cross, LV_ALIGN_BOTTOM_RIGHT, 0, 0); //然后将置于右下角 + lv_obj_update_layout(cross); //需要先重新计算布局才能获取容器尺寸 + lv_obj_get_content_coords(cross, &cross_obj_area); //获取容器尺寸 + + x_pos[1] = (cross_obj_area.x1 + cross_obj_area.x2) / 2; + y_pos[1] = (cross_obj_area.y1 + cross_obj_area.y2) / 2; //计算得到十字中点坐标 + + while (bsp_xpt2046_get_touch_status() != HAL_OK) { + lv_task_handler(); + } bsp_xpt2046_get_adc(&x_val[1], &y_val[1]); - printf("x: 0x%03X, y: 0x%03X\r\n", x_val[1], y_val[1]); - HAL_Delay(50); while (bsp_xpt2046_get_touch_status() == HAL_OK); - bsp_xpt2046_calibrate(x_pos, y_pos, x_val, y_val); - bsp_xpt2046_load_calib_data(BSP_LCD_X_PIXELS, BSP_LCD_Y_PIXELS); + status = bsp_xpt2046_calibrate(x_pos, y_pos, x_val, y_val); + if (status != HAL_OK) { + printf("error while saving calibration data to eeprom, code=%d\n", status); + } else { + printf("successfully saved calibration data to eeprom\n"); + } + + lv_obj_del(cross); } diff --git a/stm32f103_lvgl_8080lcd/MDK-ARM/stm32f103_lvgl_8080lcd.uvoptx b/stm32f103_lvgl_8080lcd/MDK-ARM/stm32f103_lvgl_8080lcd.uvoptx index 9787e3d..6ccc621 100644 --- a/stm32f103_lvgl_8080lcd/MDK-ARM/stm32f103_lvgl_8080lcd.uvoptx +++ b/stm32f103_lvgl_8080lcd/MDK-ARM/stm32f103_lvgl_8080lcd.uvoptx @@ -153,7 +153,102 @@ UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000 -FN1 -FF0STM32F10x_512 -FS08000000 -FL080000 -FP0($$Device:STM32F103ZE$Flash\STM32F10x_512.FLM)) - + + + 0 + 0 + 106 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + ..\Core\Src\bsp_xpt2046.c + + +
+ + 1 + 0 + 99 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + ..\Core\Src\bsp_xpt2046.c + + +
+ + 2 + 0 + 44 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + ..\Core\Src\bsp_xpt2046.c + + +
+ + 3 + 0 + 117 + 1 +
0
+ 0 + 0 + 0 + 0 + 0 + 0 + startup_stm32f103xe.s + + +
+
+ + + 0 + 1 + tp_x_factor + + + 1 + 1 + tp_x_offset + + + 2 + 1 + tp_y_factor + + + 3 + 1 + tp_y_offset + + + + + 1 + 0 + tp_calib_data + 0 + + 0 @@ -196,16 +291,6 @@ - - - System Viewer\DMA1 - 35905 - - - System Viewer\FSMC - 35904 - - 1 1 diff --git a/stm32f103_lvgl_8080lcd/MDK-ARM/stm32f103_lvgl_8080lcd.uvprojx b/stm32f103_lvgl_8080lcd/MDK-ARM/stm32f103_lvgl_8080lcd.uvprojx index dd4469a..896f5ed 100644 --- a/stm32f103_lvgl_8080lcd/MDK-ARM/stm32f103_lvgl_8080lcd.uvprojx +++ b/stm32f103_lvgl_8080lcd/MDK-ARM/stm32f103_lvgl_8080lcd.uvprojx @@ -313,7 +313,7 @@ 1 - 5 + 2 0 0 1