STM32F1与STM32CubeIDE编程实例-XPT2046电阻触摸屏驱动 XPT2046电阻触摸屏驱动 1、XPT2046介绍 XPT2046 是一款 4 线电阻式触摸屏控制器,包含一个 12 位 125 kHz 采样 SAR 型 A/D 转换器。XPT2046支持1.5V到5.25V的低电压I/O接口。XPT2046通过两次A/D转换就可以确认被按的屏幕位置。其功能框图如下:
XPT2046支持SPI和QSPI通信,支持8位或12位采集样。XPT2046与MCU的典型连接电路如下:
2、XPT2046配置 开发环境搭建、系统时钟配置、调试配置及串口配置,请参考:
本次配置如下:
SPI配置如下:
XPT2046的CS引脚及IRQ引脚配置如下:
3、XPT2046驱动实现 1)XPT2046驱动基本定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 /\* \* xpt2046\_touch.h \* \* Created on: Jul 4, 2022 \* Author: jenson \*/ #ifndef XPT2046\_XPT2046\_TOUCH\_H\_ #define XPT2046\_XPT2046\_TOUCH\_H\_ #include "main.h" #include <stdbool.h> #include <stm32f1xx\_hal.h> #define TOUCH\_ORIENTATION\_PORTRAIT (0U) #define TOUCH\_ORIENTATION\_LANDSCAPE (1U) #define TOUCH\_ORIENTATION\_PORTRAIT\_MIRROR (2U) #define TOUCH\_ORIENTATION\_LANDSCAPE\_MIRROR (3U) #define ORIENTATION (TOUCH\_ORIENTATION\_PORTRAIT) // change depending on screen orientation #if (ORIENTATION == 0) #define XPT2046\_SCALE\_X 240 #define XPT2046\_SCALE\_Y 320 #elif (ORIENTATION == 1) #define XPT2046\_SCALE\_X 320 #define XPT2046\_SCALE\_Y 240 #elif (ORIENTATION == 2) #define XPT2046\_SCALE\_X 240 #define XPT2046\_SCALE\_Y 320 #elif (ORIENTATION == 3) #define XPT2046\_SCALE\_X 320 #define XPT2046\_SCALE\_Y 240 #endif // 需要根据触摸板的硬件参数确定 #define XPT2046\_MIN\_RAW\_X 3400 #define XPT2046\_MAX\_RAW\_X 29000 #define XPT2046\_MIN\_RAW\_Y 3300 #define XPT2046\_MAX\_RAW\_Y 30000 #ifdef \_\_cplusplus extern "C" { #endif typedef struct { uint8\_t id; SPI_HandleTypeDef\* spi; GPIO_TypeDef\* cs_port; uint16\_t cs_pin; GPIO_TypeDef\* irq_port; uint16\_t irq_pin; uint16\_t raw_x; // 原始X坐标 uint16\_t raw_y; // 原始Y坐标 uint16\_t x; // 转换后X坐标 uint16\_t y; // 转换后Y坐标 }xpt2046\_t; void xpt2046\_init(xpt2046\_t\* xpt2046); bool xpt2046\_pressed(xpt2046\_t\* xpt2046); bool xpt2046\_read\_xy(xpt2046\_t\* xpt2046); #ifdef \_\_cplusplus } #endif /\* XPT2046\_XPT2046\_TOUCH\_H\_ \*/ #endif
请注意:XPT2046触摸板的最小输出和最大输出不同触摸板可能不同,请参考触摸板的硬件参数。
2)XPT2046驱动定义实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 /\* \* XPT2046\_touch.c \* \* Created on: Jul 4, 2022 \* Author: jenson \*/ #include <stdio.h> #include <stdlib.h> #include "xpt2046\_touch.h" #if (ORIENTATION == 0) #define READ\_X 0xD0 #define READ\_Y 0x90 #elif (ORIENTATION == 1) #define READ\_Y 0xD0 #define READ\_X 0x90 #elif (ORIENTATION == 2) #define READ\_X 0xD0 #define READ\_Y 0x90 #elif (ORIENTATION == 3) #define READ\_Y 0xD0 #define READ\_X 0x90 #endif void \_\_xpt2046\_spi\_select(xpt2046\_t \*xpt2046) { HAL\_GPIO\_WritePin(xpt2046->cs_port, xpt2046->cs_pin, GPIO_PIN_RESET); } void \_\_xpt2046\_spi\_deselect(xpt2046\_t \*xpt2046) { HAL\_GPIO\_WritePin(xpt2046->cs_port, xpt2046->cs_pin, GPIO_PIN_SET); } void xpt2046\_init(xpt2046\_t \*xpt2046) { } bool xpt2046\_pressed(xpt2046\_t \*xpt2046) { return HAL\_GPIO\_ReadPin(xpt2046->irq_port, xpt2046->irq_pin) == GPIO_PIN_RESET; } bool xpt2046\_read\_xy(xpt2046\_t \*xpt2046) { static const uint8\_t cmd_read_x[] = { READ_X }; static const uint8\_t cmd_read_y[] = { READ_Y }; static const uint8\_t zeroes_tx[] = { 0x00, 0x00 }; \_\_xpt2046\_spi\_select(xpt2046); uint32\_t avg_x = 0; uint32\_t avg_y = 0; uint8\_t nsamples = 0; // 采样16次 for (uint8\_t i = 0; i < 16; i++) { if (!xpt2046\_pressed(xpt2046)) break; nsamples++; uint8\_t y_raw[2]; uint8\_t x_raw[2]; HAL\_SPI\_Transmit(xpt2046->spi, (uint8\_t\*) cmd_read_y, sizeof(cmd_read_y), HAL_MAX_DELAY); HAL\_SPI\_TransmitReceive(xpt2046->spi, (uint8\_t\*) zeroes_tx, y_raw, sizeof(y_raw), HAL_MAX_DELAY); HAL\_SPI\_Transmit(xpt2046->spi, (uint8\_t\*) cmd_read_x, sizeof(cmd_read_x), HAL_MAX_DELAY); HAL\_SPI\_TransmitReceive(xpt2046->spi, (uint8\_t\*) zeroes_tx, x_raw, sizeof(x_raw), HAL_MAX_DELAY); avg_x += (((uint16\_t) x_raw[0]) << 8) | ((uint16\_t) x_raw[1]); avg_y += (((uint16\_t) y_raw[0]) << 8) | ((uint16\_t) y_raw[1]); } \_\_xpt2046\_spi\_deselect(xpt2046); if (nsamples < 16) return false; uint32\_t raw_x = (avg_x / 16); uint32\_t raw_y = (avg_y / 16); // printf("raw\_x = %6d, raw\_y = %6d\r\n", (int) raw\_x, (int) raw\_y); xpt2046->raw_x = raw_x; xpt2046->raw_y = raw_y; if (raw_x < XPT2046_MIN_RAW_X) raw_x = XPT2046_MIN_RAW_X; if (raw_x > XPT2046_MAX_RAW_X) raw_x = XPT2046_MAX_RAW_X; if (raw_y < XPT2046_MIN_RAW_Y) raw_y = XPT2046_MIN_RAW_Y; if (raw_y > XPT2046_MAX_RAW_Y) raw_y = XPT2046_MAX_RAW_Y; // 转换坐标 #if (ORIENTATION == 0) xpt2046->x = (raw_x - XPT2046_MIN_RAW_X) \* XPT2046_SCALE_X / (XPT2046_MAX_RAW_X - XPT2046_MIN_RAW_X); xpt2046->y = (raw_y - XPT2046_MIN_RAW_Y) \* XPT2046_SCALE_Y / (XPT2046_MAX_RAW_Y - XPT2046_MIN_RAW_Y); #elif (ORIENTATION == 1) xpt2046->x = (raw_x - XPT2046_MIN_RAW_X) \* XPT2046_SCALE_X / (XPT2046_MAX_RAW_X - XPT2046_MIN_RAW_X); xpt2046->y = (raw_y - XPT2046_MIN_RAW_Y) \* XPT2046_SCALE_Y / (XPT2046_MAX_RAW_Y - XPT2046_MIN_RAW_Y); #elif (ORIENTATION == 2) xpt2046->x = (raw_x - XPT2046_MIN_RAW_X) \* XPT2046_SCALE_X / (XPT2046_MAX_RAW_X - XPT2046_MIN_RAW_X); xpt2046->y = XPT2046_SCALE_Y - (raw_y - XPT2046_MIN_RAW_Y) \* XPT2046_SCALE_Y / (XPT2046_MAX_RAW_Y - XPT2046_MIN_RAW_Y); #elif (ORIENTATION == 3) xpt2046->x = XPT2046_SCALE_X - (raw_x - XPT2046_MIN_RAW_X) \* XPT2046_SCALE_X / (XPT2046_MAX_RAW_X - XPT2046_MIN_RAW_X); xpt2046->y = (raw_y - XPT2046_MIN_RAW_Y) \* XPT2046_SCALE_Y / (XPT2046_MAX_RAW_Y - XPT2046_MIN_RAW_Y); #endif return true; }
3、驱动测试 在main.c文件中添加如下代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 /\* Private includes ----------------------------------------------------------\*/ /\* USER CODE BEGIN Includes \*/ #include "xpt2046/xpt2046\_touch.h" #include <stdio.h> /\* USER CODE END Includes \*/ /\* USER CODE BEGIN PV \*/ xpt2046\_t xpt2046; /\* USER CODE END PV \*/ int main(void) { /\* USER CODE BEGIN 1 \*/ /\* USER CODE END 1 \*/ /\* MCU Configuration--------------------------------------------------------\*/ /\* Reset of all peripherals, Initializes the Flash interface and the Systick. \*/ HAL\_Init(); /\* USER CODE BEGIN Init \*/ /\* USER CODE END Init \*/ /\* Configure the system clock \*/ SystemClock\_Config(); /\* USER CODE BEGIN SysInit \*/ /\* USER CODE END SysInit \*/ /\* Initialize all configured peripherals \*/ MX\_GPIO\_Init(); MX\_USART1\_UART\_Init(); MX\_SPI1\_Init(); /\* USER CODE BEGIN 2 \*/ xpt2046.spi = &hspi1; xpt2046.cs_port = T_CS_GPIO_Port; xpt2046.cs_pin = T_CS_Pin; xpt2046.irq_port = T_PEN_GPIO_Port; xpt2046.irq_pin = T_PEN_Pin; xpt2046\_init(&xpt2046); /\* USER CODE END 2 \*/ /\* Infinite loop \*/ /\* USER CODE BEGIN WHILE \*/ while (1) { /\* USER CODE END WHILE \*/ /\* USER CODE BEGIN 3 \*/ if (xpt2046\_pressed(&xpt2046)) { if (xpt2046\_read\_xy(&xpt2046)) { printf("x = %d,y = %d\r\n", xpt2046.x, xpt2046.y); } } HAL\_Delay(30); } /\* USER CODE END 3 \*/ }
参考
文章来源: https://iotsmart.blog.csdn.net/article/details/125698903
如果觉得我的文章对您有用,请随意打赏。您的支持将鼓励我继续创作!