文章内容简介:
笔者学习ESP32开发时自己使用的CST328触摸芯片驱动。
CST328的特点是能够支持五点触摸,本驱动也对五点的数据进行了采集,至于如何使用就看各位大佬了。
基于ESPIDF框架,做应用开发确实相对容易很多,硬件底层无需过多关心,IDF都帮你做好了,因此这里也不对芯片使用到的IIC做过多介绍。直接进入重点,将CST328芯片相关代码。
1、先看.h文件
#ifndef __CST328_H
#define __CST328_H
#define CST328_RST_PIN GPIO_NUM_2
#define CST328_IRQ_PIN GPIO_NUM_4
#include "IIC.h"
#include <stdio.h>
/*
模块调试宏定义
*/
#define CST328_DEBUG 1
typedef struct
{
unsigned int base_addr;
char ID; // 手指ID
char Press_status; // 触摸状态
int X_POS; // X坐标
int Y_POS; // Y坐标
int Pressure; // 压力值
} finger_t;
typedef struct
{
char key_num; // 与芯片手册有关,用于读取某数量
char TP_RX_NUM; // 触摸屏RX通道数
char TP_TX_NUM; // 触摸屏TX通道数
int X_RESO; // X方向分辨率
int Y_RESO; // Y方向分辨率
int CRC; // CRC校验
int boot_time;
int chip_type;
int prj_id;
char firmware_major;
char firmware_minor;
int firware_build;
char checksum[4];
finger_t finger[5]; // 与五点触摸相关,这里使用数组做统计
} CST328_t; // CST328触摸屏结构体
extern CST328_t CST328_Instance; // CST328触摸屏实例,供外部调用,初始声明在CST328.c中
// 与ESP32通信的IIC总线相关函数
void CST328_Write(unsigned int reg_addr, unsigned char data);
void CST328_Read(unsigned int reg_addr, unsigned char *data, int length);
// CST328初始化函数
void CST328_Init(CST328_t *CST328);
// CST328触摸屏操作函数
// 获取触摸屏信息
void CST328_Get_Info(CST328_t *CST328);
// 判断触摸屏是否被触摸
char CST328_Is_Touched(CST328_t *CST328);
// 获取触摸屏触摸信息,该函数会更新CST328实例中的finger信息
void CST328_Get_Touch(CST328_t *CST328);
#endif
二、再上.c文件
#include "CST328.h"
#include "driver/gpio.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2c_master.h"
#include "esp_log.h"
CST328_t CST328_Instance;
void CST328_Init(CST328_t *CST328)
{
gpio_config_t gpio_init_struct;
gpio_init_struct.intr_type = GPIO_INTR_DISABLE; /* 失能引脚中断 */
gpio_init_struct.mode = GPIO_MODE_OUTPUT; /* 配置输出模式 */
gpio_init_struct.pin_bit_mask = 1ull << CST328_RST_PIN; /* 配置引脚位掩码 */
gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; /* 失能下拉 */
gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE; /* 使能下拉 */
gpio_config(&gpio_init_struct); /* 引脚配置 */
gpio_init_struct.intr_type = GPIO_INTR_DISABLE; /* 失能引脚中断 */
gpio_init_struct.mode = GPIO_MODE_INPUT; /* 配置输出模式 */
gpio_init_struct.pin_bit_mask = 1ull << CST328_IRQ_PIN; /* 配置引脚位掩码 */
gpio_init_struct.pull_down_en = GPIO_PULLDOWN_DISABLE; /* 失能下拉 */
gpio_init_struct.pull_up_en = GPIO_PULLUP_ENABLE; /* 使能下拉 */
gpio_config(&gpio_init_struct); /* 引脚配置 */
gpio_set_level(CST328_RST_PIN, 0);
vTaskDelay(1);
gpio_set_level(CST328_RST_PIN, 1);
CST328->finger[0].base_addr = 0xD000;
CST328->finger[1].base_addr = 0xD007;
CST328->finger[2].base_addr = 0xD00C;
CST328->finger[3].base_addr = 0xD011;
CST328->finger[4].base_addr = 0xD016;
}
void CST328_Write(unsigned int reg_addr, unsigned char data)
{
unsigned char temp[3];
temp[0] = reg_addr >> 8;
temp[1] = reg_addr & 0xFF;
temp[2] = data;
i2c_master_transmit(CST328_dev_handle, temp, 3, -1);
}
void CST328_Read(unsigned int reg_addr, unsigned char *data, int length)
{
unsigned char temp[2];
temp[0] = reg_addr >> 8;
temp[1] = reg_addr & 0xff;
i2c_master_transmit_receive(CST328_dev_handle, temp, 2, data, length, 50);
}
void CST328_Get_Info(CST328_t *CST328)
{
unsigned char temp[4];
CST328_Write(0xD101, 0x00);
CST328_Read(0xD1F4, temp, 4);
#if CST328_DEBUG == 1
ESP_LOGI("CST328", "%d,%d,%d,%d\n", temp[3], temp[2], temp[1], temp[0]);
#endif
CST328->key_num = temp[0];
CST328->TP_RX_NUM = temp[0];
CST328->TP_TX_NUM = temp[0];
CST328_Read(0xD1F8, temp, 4);
#if CST328_DEBUG == 1
ESP_LOGI("CST328", "%d,%d\n", temp[3] << 8 | temp[2], temp[1] << 8 | temp[0]);
#endif
CST328->X_RESO = temp[1] << 8 | temp[0];
CST328->X_RESO = temp[3] << 8 | temp[2];
CST328_Read(0xD1FC, temp, 4);
#if CST328_DEBUG == 1
ESP_LOGI("CST328", "%d,%d,%d,%d\n", temp[3], temp[2], temp[1], temp[0]);
#endif
CST328->CRC = temp[3] << 8 | temp[2];
CST328->boot_time = temp[1] << 8 | temp[0];
}
void CST328_Set_Sleep()
{
CST328_Write(0xD105, 0x00);
}
char CST328_Is_Touched(CST328_t *CST328)
{
unsigned char temp[5];
static char last_pressure = 0, pressure = 0;
static int last_x = 0, last_y = 0, x = 0, y = 0;
/* 进入正常报点模式 */
CST328_Write(0xD109, 0x00);
/* 获取当前有多少触摸点 */
CST328_Read(0xD005, temp, 1);
unsigned char i;
unsigned char touched_number = temp[0] & 0x0f;
CST328_Read(CST328->finger[0].base_addr, temp, 5);
last_x = x;
last_y = y;
x = temp[1] << 4 | temp[3] >> 4;
y = temp[2] << 4 | (temp[3] & 0x0f);
last_pressure = pressure;
pressure = temp[4];
if (last_pressure == pressure)
{
return 0;
}
else if (last_x == x && last_y == y)
{
return 0;
}
else
{
return 1;
}
}
void CST328_Get_Touch(CST328_t *CST328)
{
unsigned char temp[5];
/* 重新初始化算法*/
// CST328_Write(0xD104, 0x00);
/* 进入正常报点模式 */
CST328_Write(0xD109, 0x00);
/* 获取当前有多少触摸点 */
CST328_Read(0xD005, temp, 1);
unsigned char i;
unsigned char touched_number = temp[0] & 0x0f;
#if CST328_DEBUG == 1
ESP_LOGI("CST328", "Touched:%d", touched_number);
#endif
for (i = 0; i < touched_number; i++)
{
/* 根据多少触摸点依次获取数据 */
CST328_Read(CST328->finger[i].base_addr, temp, 5);
CST328->finger[i].ID = temp[0] >> 4;
CST328->finger[i].Press_status = (temp[0] & 0x0f);
CST328->finger[i].X_POS = temp[1] << 4 | temp[3] >> 4;
CST328->finger[i].Y_POS = temp[2] << 4 | (temp[3] & 0x0f);
CST328->finger[i].Pressure = temp[4];
#if CST328_DEBUG == 1
ESP_LOGI("CST328", "finger%d:(%d,%d) Pressure:%d", CST328->finger[i].ID, CST328->finger[i].X_POS, CST328->finger[i].Y_POS, CST328->finger[i].Pressure);
#endif
}
/* 需要根据压力大小判断是否上报,排除重复上报数据 */
}
在测试时我发现如果触摸屏初始化后从来没被触摸过,那么第一次数据是正确的,获取到的手指数量和坐标、压力值都是正确的。但当手指松开后,芯片仍会返回上一次的手指数、坐标和压力值。因此,为了适配LVGL,这里判断触摸屏是否被按压我经过了两层判断,一是判断本次触摸的坐标与上次是否一致,二是判断当前压力值与上次是否一致,若都一致则认为是无有效信息,无手指触摸。
1525

被折叠的 条评论
为什么被折叠?



