From bf249faed0840ee1c6ed20c4ac42ee352e17ec47 Mon Sep 17 00:00:00 2001 From: wanghaolong Date: Fri, 3 Jul 2026 11:22:17 +0800 Subject: [PATCH] resistance touch lcd --- .gitignore | 84 ++++++++++++++++++++ CMakeLists.txt | 6 ++ main/CMakeLists.txt | 3 + main/main.c | 34 +++++++++ main/resistive_touch.c | 170 +++++++++++++++++++++++++++++++++++++++++ main/resistive_touch.h | 28 +++++++ partitions.csv | 4 + sdkconfig.defaults | 7 ++ 8 files changed, 336 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 main/CMakeLists.txt create mode 100644 main/main.c create mode 100644 main/resistive_touch.c create mode 100644 main/resistive_touch.h create mode 100644 partitions.csv create mode 100644 sdkconfig.defaults diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..263b553 --- /dev/null +++ b/.gitignore @@ -0,0 +1,84 @@ +# macOS +.DS_Store +.AppleDouble +.LSOverride + +# Directory metadata +.directory + +# Temporary files +*~ +*.swp +*.swo +*.bak +*.tmp + +# Log files +*.log + +# Build artifacts and directories +**/build/ +build/ +build_guardian/ +document/ +tools/ +*.o +*.a +*.out +*.exe # For any host-side utilities compiled on Windows + +# ESP-IDF specific build outputs +*.bin +*.elf +*.map +flasher_args.json # Generated in build directory +sdkconfig.old +sdkconfig + +# ESP-IDF dependencies +# For older versions or manual component management +/components/.idf/ +**/components/.idf/ +# For modern ESP-IDF component manager +managed_components/ +# If ESP-IDF tools are installed/referenced locally to the project +.espressif/ + +# CMake generated files +CMakeCache.txt +CMakeFiles/ +cmake_install.cmake +install_manifest.txt +CTestTestfile.cmake + +# Python environment files +*.pyc +*.pyo +*.pyd +__pycache__/ +*.egg-info/ +dist/ + +# Virtual environment folders +venv/ +.venv/ +env/ + +# Language Servers +.clangd/ +.ccls-cache/ +compile_commands.json + +# Windows specific +Thumbs.db +ehthumbs.db +Desktop.ini + +# User-specific configuration files +*.user +*.workspace # General workspace files, can be from various tools +*.suo # Visual Studio Solution User Options +*.sln.docstates # Visual Studio + + +.vscode/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..72a62fc --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(touch) diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt new file mode 100644 index 0000000..f0043ec --- /dev/null +++ b/main/CMakeLists.txt @@ -0,0 +1,3 @@ +idf_component_register(SRCS "resistive_touch.c" "main.c" + INCLUDE_DIRS "." + PRIV_REQUIRES esp_driver_gpio esp_driver_spi freertos) diff --git a/main/main.c b/main/main.c new file mode 100644 index 0000000..97956cf --- /dev/null +++ b/main/main.c @@ -0,0 +1,34 @@ +#include "esp_log.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" + +#include "resistive_touch.h" + +static const char *TAG = "touch"; + +void app_main(void) +{ + bool was_pressed = false; + + resistive_touch_init(); + ESP_LOGI(TAG, "resistive touch terminal output started"); + + while (1) { + resistive_touch_point_t point; + + if (resistive_touch_read(&point)) { + if (!was_pressed) { + ESP_LOGI(TAG, "TOUCH DOWN"); + } + + ESP_LOGI(TAG, "TOUCH POINT x=%u y=%u raw_x=%u raw_y=%u", + point.x, point.y, point.raw_x, point.raw_y); + was_pressed = true; + } else if (was_pressed && !resistive_touch_is_pressed()) { + ESP_LOGI(TAG, "TOUCH UP"); + was_pressed = false; + } + + vTaskDelay(pdMS_TO_TICKS(50)); + } +} diff --git a/main/resistive_touch.c b/main/resistive_touch.c new file mode 100644 index 0000000..2ea1b2e --- /dev/null +++ b/main/resistive_touch.c @@ -0,0 +1,170 @@ +#include "resistive_touch.h" + +#include + +#include "esp_err.h" +#include "driver/gpio.h" +#include "driver/spi_master.h" + +#define TOUCH_SPI_HOST SPI2_HOST + +#define TOUCH_CMD_READ_X 0x90 +#define TOUCH_CMD_READ_Y 0xD0 +#define TOUCH_READ_TIMES 5 +#define TOUCH_LOST_VALUES 1 +#define TOUCH_ERR_RANGE 50 + +/* + * Default calibration from the vendor resistive-touch example for 320x240 + * landscape mode. If your panel is offset, adjust these four constants. + */ +#define TOUCH_X_FACTOR 0.089750f +#define TOUCH_X_OFFSET (-14.0f) +#define TOUCH_Y_FACTOR (-0.064668f) +#define TOUCH_Y_OFFSET 251.0f + +static spi_device_handle_t touch_spi; + +static void touch_spi_bus_init(void) +{ + spi_bus_config_t bus_config = { + .mosi_io_num = TOUCH_PIN_MOSI, + .miso_io_num = TOUCH_PIN_MISO, + .sclk_io_num = TOUCH_PIN_SCLK, + .quadwp_io_num = -1, + .quadhd_io_num = -1, + .max_transfer_sz = 3, + }; + + esp_err_t err = spi_bus_initialize(TOUCH_SPI_HOST, &bus_config, SPI_DMA_CH_AUTO); + if (err != ESP_OK && err != ESP_ERR_INVALID_STATE) { + ESP_ERROR_CHECK(err); + } +} + +static uint16_t clamp_u16(float value, uint16_t max) +{ + if (value <= 0.0f) { + return 0; + } + if (value >= (float)max) { + return max; + } + return (uint16_t)lroundf(value); +} + +static uint16_t touch_read_adc(uint8_t command) +{ + uint8_t tx[3] = {command, 0x00, 0x00}; + uint8_t rx[3] = {0}; + spi_transaction_t transaction = { + .length = 24, + .tx_buffer = tx, + .rx_buffer = rx, + }; + + spi_device_polling_transmit(touch_spi, &transaction); + return (uint16_t)((((uint16_t)rx[1] << 8) | rx[2]) >> 3) & 0x0fff; +} + +static uint16_t touch_read_filtered_axis(uint8_t command) +{ + uint16_t values[TOUCH_READ_TIMES]; + + for (int i = 0; i < TOUCH_READ_TIMES; i++) { + values[i] = touch_read_adc(command); + } + + for (int i = 0; i < TOUCH_READ_TIMES - 1; i++) { + for (int j = i + 1; j < TOUCH_READ_TIMES; j++) { + if (values[i] > values[j]) { + uint16_t tmp = values[i]; + values[i] = values[j]; + values[j] = tmp; + } + } + } + + uint32_t sum = 0; + for (int i = TOUCH_LOST_VALUES; i < TOUCH_READ_TIMES - TOUCH_LOST_VALUES; i++) { + sum += values[i]; + } + + return (uint16_t)(sum / (TOUCH_READ_TIMES - 2 * TOUCH_LOST_VALUES)); +} + +static bool touch_read_filtered_raw(uint16_t *x, uint16_t *y) +{ + uint16_t x1 = touch_read_filtered_axis(TOUCH_CMD_READ_X); + uint16_t y1 = touch_read_filtered_axis(TOUCH_CMD_READ_Y); + uint16_t x2 = touch_read_filtered_axis(TOUCH_CMD_READ_X); + uint16_t y2 = touch_read_filtered_axis(TOUCH_CMD_READ_Y); + + if ((abs((int)x1 - (int)x2) >= TOUCH_ERR_RANGE) || + (abs((int)y1 - (int)y2) >= TOUCH_ERR_RANGE)) { + return false; + } + + *x = (uint16_t)((x1 + x2) / 2); + *y = (uint16_t)((y1 + y2) / 2); + return true; +} + +bool resistive_touch_is_pressed(void) +{ + return gpio_get_level(TOUCH_PIN_IRQ) == 0; +} + +bool resistive_touch_read_raw(uint16_t *x, uint16_t *y) +{ + if (!x || !y || !resistive_touch_is_pressed()) { + return false; + } + + return touch_read_filtered_raw(x, y); +} + +bool resistive_touch_read(resistive_touch_point_t *point) +{ + uint16_t raw_x; + uint16_t raw_y; + + if (!point) { + return false; + } + + point->pressed = false; + if (!resistive_touch_read_raw(&raw_x, &raw_y)) { + return false; + } + + point->raw_x = raw_x; + point->raw_y = raw_y; + point->x = clamp_u16(TOUCH_X_FACTOR * raw_x + TOUCH_X_OFFSET, TOUCH_WIDTH - 1); + point->y = clamp_u16(TOUCH_Y_FACTOR * raw_y + TOUCH_Y_OFFSET, TOUCH_HEIGHT - 1); + point->pressed = true; + return true; +} + +void resistive_touch_init(void) +{ + gpio_config_t gpio_config_data = { + .pin_bit_mask = 1ULL << TOUCH_PIN_IRQ, + .mode = GPIO_MODE_INPUT, + .pull_up_en = GPIO_PULLUP_ENABLE, + .pull_down_en = GPIO_PULLDOWN_DISABLE, + .intr_type = GPIO_INTR_DISABLE, + }; + gpio_config(&gpio_config_data); + + touch_spi_bus_init(); + + spi_device_interface_config_t device_config = { + .clock_speed_hz = 2000000, + .mode = 0, + .spics_io_num = TOUCH_PIN_CS, + .queue_size = 1, + }; + + ESP_ERROR_CHECK(spi_bus_add_device(TOUCH_SPI_HOST, &device_config, &touch_spi)); +} diff --git a/main/resistive_touch.h b/main/resistive_touch.h new file mode 100644 index 0000000..83f7c8e --- /dev/null +++ b/main/resistive_touch.h @@ -0,0 +1,28 @@ +#ifndef RESISTIVE_TOUCH_H +#define RESISTIVE_TOUCH_H + +#include +#include + +#define TOUCH_WIDTH 320 +#define TOUCH_HEIGHT 240 +#define TOUCH_PIN_MOSI 11 +#define TOUCH_PIN_SCLK 12 +#define TOUCH_PIN_CS 7 +#define TOUCH_PIN_IRQ 2 +#define TOUCH_PIN_MISO 13 + +typedef struct { + uint16_t x; + uint16_t y; + uint16_t raw_x; + uint16_t raw_y; + bool pressed; +} resistive_touch_point_t; + +void resistive_touch_init(void); +bool resistive_touch_read(resistive_touch_point_t *point); +bool resistive_touch_read_raw(uint16_t *x, uint16_t *y); +bool resistive_touch_is_pressed(void); + +#endif diff --git a/partitions.csv b/partitions.csv new file mode 100644 index 0000000..f622d1e --- /dev/null +++ b/partitions.csv @@ -0,0 +1,4 @@ +# Name, Type, SubType, Offset, Size, Flags +nvs, data, nvs, 0x9000, 0x6000, +phy_init, data, phy, 0xF000, 0x1000, +factory, app, factory, 0x10000, 0xE00000, diff --git a/sdkconfig.defaults b/sdkconfig.defaults new file mode 100644 index 0000000..a9a7fe0 --- /dev/null +++ b/sdkconfig.defaults @@ -0,0 +1,7 @@ +CONFIG_IDF_TARGET="esp32s3" +CONFIG_ESPTOOLPY_FLASHSIZE_16MB=y +CONFIG_ESPTOOLPY_FLASHSIZE="16MB" +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_FILENAME="partitions.csv" +CONFIG_ESP_MAIN_TASK_STACK_SIZE=4096