基于STM32、HAL库的TSC2046IPWR触摸屏控制器驱动程序设计
一、简介:
TSC2046IPWR是一款4线电阻式触摸屏控制器,具有以下特点:
-
12位分辨率ADC
-
支持SPI和I2C接口
-
低功耗设计
-
内置温度测量功能
-
内置触摸压力测量功能
-
工作电压:2.2V-5.25V
二、硬件接口:
TSC2046引脚 | STM32L4引脚 | 功能说明 |
---|---|---|
VCC | 3.3V | 电源 |
GND | GND | 地 |
DIN | PA7 | SPI MOSI |
DOUT | PA6 | SPI MISO |
CS | PA4 | 片选 |
DCLK | PA5 | SPI时钟 |
BUSY | PA3 | 忙信号(可选) |
PENIRQ | PA2 | 触摸中断(可选) |
三、头文件:
#ifndef __TSC2046_H
#define __TSC2046_H
#include "stm32l4xx_hal.h"
#define TSC2046_CMD_X 0xD0
#define TSC2046_CMD_Y 0x90
#define TSC2046_CMD_Z1 0xB0
#define TSC2046_CMD_Z2 0xC0
#define TSC2046_CMD_TEMP0 0x80
#define TSC2046_CMD_TEMP1 0xF0
#define TSC2046_SPI_TIMEOUT 100
typedef struct {
SPI_HandleTypeDef *hspi;
GPIO_TypeDef *cs_port;
uint16_t cs_pin;
GPIO_TypeDef *irq_port;
uint16_t irq_pin;
} TSC2046_HandleTypeDef;
void TSC2046_Init(TSC2046_HandleTypeDef *htsc, SPI_HandleTypeDef *hspi,
GPIO_TypeDef *cs_port, uint16_t cs_pin,
GPIO_TypeDef *irq_port, uint16_t irq_pin);
uint8_t TSC2046_Touched(TSC2046_HandleTypeDef *htsc);
uint16_t TSC2046_ReadX(TSC2046_HandleTypeDef *htsc);
uint16_t TSC2046_ReadY(TSC2046_HandleTypeDef *htsc);
uint16_t TSC2046_ReadZ1(TSC2046_HandleTypeDef *htsc);
uint16_t TSC2046_ReadZ2(TSC2046_HandleTypeDef *htsc);
uint16_t TSC2046_ReadADC(TSC2046_HandleTypeDef *htsc, uint8_t cmd);
uint16_t TSC2046_ReadTemperature(TSC2046_HandleTypeDef *htsc, uint8_t temp_cmd);
#endif /* __TSC2046_H */
四、源文件:
#include "tsc2046.h"
#include "stm32l4xx_hal.h"
void TSC2046_Init(TSC2046_HandleTypeDef *htsc, SPI_HandleTypeDef *hspi,
GPIO_TypeDef *cs_port, uint16_t cs_pin,
GPIO_TypeDef *irq_port, uint16_t irq_pin)
{
htsc->hspi = hspi;
htsc->cs_port = cs_port;
htsc->cs_pin = cs_pin;
htsc->irq_port = irq_port;
htsc->irq_pin = irq_pin;
// 初始化CS引脚为高电平(不选中)
HAL_GPIO_WritePin(htsc->cs_port, htsc->cs_pin, GPIO_PIN_SET);
}
uint8_t TSC2046_Touched(TSC2046_HandleTypeDef *htsc)
{
// 检查PENIRQ引脚,低电平表示触摸
return (HAL_GPIO_ReadPin(htsc->irq_port, htsc->irq_pin) == GPIO_PIN_RESET);
}
uint16_t TSC2046_ReadADC(TSC2046_HandleTypeDef *htsc, uint8_t cmd)
{
uint8_t tx_data[3] = {0};
uint8_t rx_data[3] = {0};
uint16_t result = 0;
tx_data[0] = cmd;
HAL_GPIO_WritePin(htsc->cs_port, htsc->cs_pin, GPIO_PIN_RESET);
HAL_SPI_TransmitReceive(htsc->hspi, tx_data, rx_data, 3, TSC2046_SPI_TIMEOUT);
HAL_GPIO_WritePin(htsc->cs_port, htsc->cs_pin, GPIO_PIN_SET);
// 数据在第二个和第三个字节的高12位
result = ((rx_data[1] << 8) | rx_data[2]) >> 3;
return result;
}
uint16_t TSC2046_ReadX(TSC2046_HandleTypeDef *htsc)
{
return TSC2046_ReadADC(htsc, TSC2046_CMD_X);
}
uint16_t TSC2046_ReadY(TSC2046_HandleTypeDef *htsc)
{
return TSC2046_ReadADC(htsc, TSC2046_CMD_Y);
}
uint16_t TSC2046_ReadZ1(TSC2046_HandleTypeDef *htsc)
{
return TSC2046_ReadADC(htsc, TSC2046_CMD_Z1);
}
uint16_t TSC2046_ReadZ2(TSC2046_HandleTypeDef *htsc)
{
return TSC2046_ReadADC(htsc, TSC2046_CMD_Z2);
}
uint16_t TSC2046_ReadTemperature(TSC2046_HandleTypeDef *htsc, uint8_t temp_cmd)
{
return TSC2046_ReadADC(htsc, temp_cmd);
}
五、应用:
#include "main.h"
#include "tsc2046.h"
SPI_HandleTypeDef hspi1;
TSC2046_HandleTypeDef htsc;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_SPI1_Init();
// 初始化TSC2046
TSC2046_Init(&htsc, &hspi1, GPIOA, GPIO_PIN_4, GPIOA, GPIO_PIN_2);
while (1)
{
if (TSC2046_Touched(&htsc))
{
uint16_t x = TSC2046_ReadX(&htsc);
uint16_t y = TSC2046_ReadY(&htsc);
uint16_t z1 = TSC2046_ReadZ1(&htsc);
uint16_t z2 = TSC2046_ReadZ2(&htsc);
// 计算触摸压力
uint16_t pressure = z1 - z2 + 4095;
// 在这里可以添加触摸坐标处理逻辑
// ...
HAL_Delay(100); // 简单的防抖处理
}
}
}
// SPI1初始化函数
void MX_SPI1_Init(void)
{
hspi1.Instance = SPI1;
hspi1.Init.Mode = SPI_MODE_MASTER;
hspi1.Init.Direction = SPI_DIRECTION_2LINES;
hspi1.Init.DataSize = SPI_DATASIZE_8BIT;
hspi1.Init.CLKPolarity = SPI_POLARITY_LOW;
hspi1.Init.CLKPhase = SPI_PHASE_1EDGE;
hspi1.Init.NSS = SPI_NSS_SOFT;
hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_32;
hspi1.Init.FirstBit = SPI_FIRSTBIT_MSB;
hspi1.Init.TIMode = SPI_TIMODE_DISABLE;
hspi1.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
hspi1.Init.CRCPolynomial = 7;
if (HAL_SPI_Init(&hspi1) != HAL_OK)
{
Error_Handler();
}
}
// GPIO初始化函数
void MX_GPIO_Init(void)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
__HAL_RCC_GPIOA_CLK_ENABLE();
// SPI1引脚配置
GPIO_InitStruct.Pin = GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// CS引脚配置
GPIO_InitStruct.Pin = GPIO_PIN_4;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_NOPULL;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
// PENIRQ引脚配置
GPIO_InitStruct.Pin = GPIO_PIN_2;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}