CST328触摸驱动(ESP32平台)

该文章已生成可运行项目,

文章内容简介:

        笔者学习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,这里判断触摸屏是否被按压我经过了两层判断,一是判断本次触摸的坐标与上次是否一致,二是判断当前压力值与上次是否一致,若都一致则认为是无有效信息,无手指触摸。

 

 

 

 

本文章已经生成可运行项目
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Distance_90

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值