ESP32开发---驱动触摸屏

这篇具有很好参考价值的文章主要介绍了ESP32开发---驱动触摸屏。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

采用I2C驱动触摸屏。

I2C多用于主控制器和从器件间的主从通信,在小数据量场合使用,传输距离短,任意时刻只能有一个主机等特性。

它有两条线,一条是SCL(串行时钟总线),另外一条是SDA(串行数据线),这两条数据需要接上拉电阻,总线空闲的时候SCL和SDA处于高电平。

ESP32开发---驱动触摸屏

 图来自正点原子linux驱动开发教程

I2C主要有起始位、停止位、数据传输、应答信号等。

I2C写时序

I2C的写时序相较于读时序是比较简单的,大概分以下几个步骤。

  1. 开始信号
  2. 发送 I2C设备地址,其中高七位是设备地址,最后一位是读写地址。
  3. 从机发送应答信号
  4. 重新发送开始信号
  5. 发送要写入数据的寄存器地址
  6. 从机发送应答信号
  7. 发送要写入寄存器的数据
  8. 从机发送应答信号
  9. 停止信号

ESP32开发---驱动触摸屏 图来自正点原子linux驱动开发教程

I2C读时序

读时序相对于写时序来说复杂了一点,结束时多了一个非应答信号,以及写入寄存器地址之后要重新发从机的地址

总体的分为四步,跟写时序差不多。

  1. 发送设备地址
  2. 发送要读取的寄存器地址
  3. 重新发送设备地址
  4. 读取数据

ESP32开发---驱动触摸屏

  图来自正点原子linux驱动开发教程

OK,了解了基本的之后,回到驱动触摸屏上来。

我们驱动一个触摸屏需要使用到TP,这里使用的是FT6236。

查询芯片手册,可以发现FT6236有四根线。

ESP32开发---驱动触摸屏

两根是I2C需要的线,还有两根分别是INT(输入),RSTN(输出)。

到这里,就很简洁明了了。

我们需要用到GPIOI2C,以及TP的驱动。

首先,将RSTINT利用GPIO进行初始化,并进行相应的一些设置。、

GPIO

GPIO的使用已经很熟悉了,这里就不多说了。

简单的来说就是定义硬件图所使用的IO口,然后利用寄存器进行相应的初始化,实现我们的功能。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/queue.h"
#include "driver/gpio.h"

#include "ds_gpio.h"
#include "ds_system_data_da.h"

//定义IO口,查硬件图
#define GPIO_OUTPUT_IO_0       5
#define GPIO_OUTPUT_PIN_SEL    ((1ULL<<GPIO_OUTPUT_IO_0))
#define GPIO_INTPUT_IO_0       4
#define GPIO_INTPUT_PIN_SEL    ((1ULL<<GPIO_INTPUT_IO_0))
#define ESP_INTR_FLAG_DEFAULT 0

static xQueueHandle gpio_evt_queue = NULL;

static void IRAM_ATTR gpio_isr_handler(void *arg){
    uint32_t gpio_num = (uint32_t)arg;//强转
    xQueueSendFromISR(gpio_evt_queue,&gpio_num,NULL);
}

//触摸屏GPIO口初始化
void ds_touch_gpio_init(void){
    gpio_config_t io_conf;
    //rst不需要中断,关闭中断
    io_conf.intr_type = GPIO_PIN_INTR_DISABLE;
    //设置模式为输出
    io_conf.mode = GPIO_MODE_OUTPUT;
    //设置引脚5
    io_conf.pin_bit_mask = GPIO_OUTPUT_PIN_SEL;
    //设置上拉和下拉
    io_conf.pull_down_en = 0;
    io_conf.pull_up_en = 0;
    //配置GPIO
    gpio_config(&io_conf);

    //无论上升沿还是下降沿都触发
    io_conf.intr_type = GPIO_INTR_ANYEDGE;
    //模式为输入,根据手册判定的
    io_conf.mode = GPIO_MODE_INPUT;
    //设置为引脚4
    io_conf.pin_bit_mask = GPIO_INTPUT_PIN_SEL;
    //设置为上拉,默认低电平有效
    io_conf.pull_up_en = 1;
    //配置GPIO
    gpio_config(&io_conf);

    //创建处理gpio事件的消息队列
    gpio_evt_queue = xQueueCreate(10,sizeof(uint32_t));

    //安装gpio中断服务
    gpio_install_isr_service(ESP_INTR_FLAG_DEFAULT);
    gpio_isr_handler_add(GPIO_INTPUT_IO_0,gpio_isr_handler,(void*)GPIO_INTPUT_IO_0);

}
//复位
void ds_gpio_set_touch_rst(uint32_t level){

    gpio_set_level(GPIO_OUTPUT_IO_0,level);
}

GPIO比较简单。

I2C程序编写

I2C的程序编写尽量要参考一下ESP32官方给出的手册,包括读写时序的编写,避免出错。

相关API可以在官方文档里看。

ESP32开发---驱动触摸屏

这是官方例程里带寄存器读的例子,可以看到是先设置寄存器的地址,然后再重新写入从机地址的,接下来就可以模仿这个开始写。

首先设置读取地址。

//设置读取地址
static esp_err_t i2c_master_set_addr(uint8_t u8Cmd){

    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd,(ESP_SLAVE_ADDR<<1)|WRITE_BIT,ACK_CHECK_EN);//设置从机地址
    i2c_master_write_byte(cmd,u8Cmd,ACK_CHECK_EN);//设置读取寄存器地址
    i2c_master_stop(cmd);
    esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) {
        printf("i2c_master_set_addr error\n");
    }
    return ret;

}

然后进行读时序。

//读取数据

esp_err_t i2c_master_read_slave(uint8_t u8Cmd, uint8_t *data_rd, size_t size){
if(size == 0){
    return ESP_OK;
}
i2c_master_set_addr(u8Cmd);//设置要读取的寄存器地址
vTaskDelay(30 / portTICK_RATE_MS);//延时24ms
//然后再次写入从机地址,并加上独标志位
i2c_cmd_handle_t cmd = i2c_cmd_link_create();
i2c_master_start(cmd);
i2c_master_write_byte(cmd,(ESP_SLAVE_ADDR<<1)|READ_BIT,ACK_CHECK_EN);
for(int index = 0;index<(size-1);index++){

    i2c_master_read_byte(cmd,data_rd+index,ACK_VAL);
}
i2c_master_read_byte(cmd,data_rd+size-1,NACK_VAL);//发送非应答信号
i2c_master_stop(cmd);
esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) {
        printf("i2c_master_read_slave error\n");
    }
    return ret;

}

写时序就比较简单了。

//写入数据,不需要发非应答信号
esp_err_t i2c_master_write_slave(uint8_t u8Cmd, uint8_t *data_wr, size_t size){
 
    i2c_cmd_handle_t cmd = i2c_cmd_link_create();
    i2c_master_start(cmd);
    i2c_master_write_byte(cmd, (ESP_SLAVE_ADDR << 1) | WRITE_BIT, ACK_CHECK_EN);
    i2c_master_write_byte(cmd, u8Cmd, ACK_CHECK_EN);
    i2c_master_write(cmd, data_wr, size, ACK_CHECK_EN);
    i2c_master_stop(cmd);

    esp_err_t ret = i2c_master_cmd_begin(I2C_MASTER_NUM, cmd, 1000 / portTICK_RATE_MS);
    i2c_cmd_link_delete(cmd);
    if (ret != ESP_OK) {
        printf("i2c_master_write_slave error\n");
    }
    return ret;


}

在进行这些之前,还需要初始化一下我们的I2C。

这就涉及到一些宏定义,可以采用KConfig进行定义,可以直接写值,但是这里还是建议用Kconfig进行定义。

初始化的代码直接参考例程,几乎不怎么需要修改,只需要把SCL和SDA的引脚重新定义一下,适合我们的开发板就行。

//初始化
esp_err_t i2c_master_init(void)
{
    int i2c_master_port = I2C_MASTER_NUM;
    i2c_config_t conf;
    conf.mode = I2C_MODE_MASTER;
    conf.sda_io_num = I2C_MASTER_SDA_IO;
    conf.sda_pullup_en = GPIO_PULLUP_ENABLE;
    conf.scl_io_num = I2C_MASTER_SCL_IO;
    conf.scl_pullup_en = GPIO_PULLUP_ENABLE; 
    conf.master.clk_speed = I2C_MASTER_FREQ_HZ;
    i2c_param_config(i2c_master_port, &conf);
    return i2c_driver_install(i2c_master_port, conf.mode, I2C_MASTER_RX_BUF_DISABLE, I2C_MASTER_TX_BUF_DISABLE, 0);
}

好了,I2C就已经可以了。

然后开始写最重要的一步,TP的驱动,这个是需要我们自己查芯片手册,然后一步步编写的。

TP驱动

观察芯片手册。

ESP32开发---驱动触摸屏

 圈出来的这里,就是我们用I2C写入或者读取的寄存器了。

在头文件里进行定义。

//由FT6236芯片手册查询得到各部分寄存器地址
#define FI_DEVIDE_MODE      0x00       //FT6236模式控制寄存器
#define FI_REG_NUM_FINGER   0x02       //触摸状态寄存器

#define FI_TP1_REG          0x03       //第一个触摸点数据地址
#define FI_TP2_REG          0x09       //第一个触摸点数据地址
#define FI_TP3_REG          0x0F       //第一个触摸点数据地址
#define FI_TP4_REG          0x15       //第一个触摸点数据地址
#define FI_TP5_REG          0x1B       //第一个触摸点数据地址

#define FI_ID_G_LIB_VERSION   0xA1       //版本
#define FI_ID_G_MODE          0xA4       //FT6236中断模式控制寄存器
#define FI_ID_G_THGROUP       0x80       //触摸有效值设置寄存器
#define FI_ID_G_PERIODACTIVE  0x88       //激活状态周期设置寄存器
#define Chip_Vendor_ID        0xA3       //芯片ID(0x36)
#define ID_G_FT6236ID         0xA8       //0x11

然后定义触摸点的结构体。

//触摸点相关数据结构定义
typedef struct
{
    //bit7:按下1/松开0
    //bit6: 没有按键按下0/有按键按下1
    //bit5:保留
    //bit4-bit0:触摸点按下有效标志,有效为1,对应五个触摸点
    uint8_t touch_sta; //触摸点的情况
    uint8_t touch_count; //触摸点数
    uint16_t x[5];
    uint16_t y[5];
    bool updata;
}TouchPoint_T;

定义一下触摸屏被按下或松开的标记。

#define TP_PRESS_DOWN    0x80  //触摸屏被按下,0x10000000,第七位为1
#define TP_COORD_UD      0x40  //触摸屏坐标更新,第六位为1

其他的就看自己的用途定义了,基本就是这些了。

然后就可以开始编写驱动了,主要参考ESP里的相关例程,以及FT6236的一些源码。

#include <string.h>
#include <stdio.h>

#include "ds_tp.h"
#include "ds_i2c.h"
#include "ds_gpio.h"
#include "ds_system_data_da.h"

//触摸芯片最大5组触摸点,FT6236最大支持双触
const uint16_t FT6236_TPX_TBL[5]=
{
    FI_TP1_REG,
    FI_TP2_REG,
    FI_TP3_REG,
    FI_TP4_REG,
    FI_TP5_REG
};

TouchPoint_T gTPS;

//扫描触摸屏寄存器状态、数据
static void scan_ft6236(void)
{
    uint8_t i=0;
    uint8_t sta = 0;//触摸点状态
    uint8_t buf[4] = {0};//这里是获取四个字节,分别是xH、xL、yH、yL
    uint8_t gestid = 0;//手势
    i2c_master_read_slave(0x02,&sta,1);//读取寄存器状态,读取的是个数!
    gTPS.touch_count = sta;
    i2c_master_read_slave(0x01,&gestid,1);//读取触摸点的状态

    if(sta&0x0f)//判断有无触摸点按下
    {

        gTPS.touch_sta = ~(0xFF << (sta & 0x0F));//将有效触摸点的个数转换为对应的标记
        for (i = 0; i < 2; i++)//最多同时两个触摸点
        {
            if (gTPS.touch_sta & (1 << i))
            {
                i2c_master_read_slave(FT6236_TPX_TBL[i], buf, 4); // 读取触摸点坐标
                gTPS.x[i] = (uint16_t)(((buf[0]&0x0F)<<8)+buf[1]);//清空XH的高四位,并左移8位与XL组成坐标
                gTPS.y[i] = (uint16_t)(((buf[2]&0x0F)<<8)+buf[3]);
            }
        }
        gTPS.touch_sta |= TP_PRESS_DOWN; //按下标记,置1

    }
    else //如果判断无触摸点按下,那么检查一下之前的标记
    {
        if(gTPS.touch_sta & TP_PRESS_DOWN)//如果之前被按下了
        {
            gTPS.touch_sta &= ~0x80; //清楚按下标记
        }
        else//
        {
            gTPS.x[0]=0;
            gTPS.y[0]=0;
            gTPS.touch_sta &= 0xe0;//将后五位清0,这一块还是有点疑虑
        }

    }
    
}

//转换为实际位置
static void count_position_ft6236(TP_POSITION_T *position){

    switch (gTPS.touch_count)
    {
      case 1:
           if ((gTPS.x[0] != 0) && (gTPS.y[0] != 0) 
            && (gTPS.x[0] < 200) && (gTPS.y[0] < 200))
           {
                position->x = gTPS.x[0];
                position->y = gTPS.y[0];
                printf("触摸点的个数=%d\r\n", gTPS.touch_count);
                printf("x0:%d,y0:%d\r\n", gTPS.x[0], gTPS.y[0]);
                return;
            }
            break;
        case 2:
             if ((gTPS.x[0] != 0) && (gTPS.y[0] != 0) 
            && (gTPS.x[0] < 200) && (gTPS.y[0] < 200) 
            && (gTPS.x[0] < 200) && (gTPS.y[0] < 200) 
            && (gTPS.x[1] < 200) && (gTPS.y[1] < 200))
           {
                printf("触摸点个数::%d\r\n", gTPS.touch_count); // FT6336U最多支持两点触控
                printf("x0:%d,y0:%d\r\n", gTPS.x[0], gTPS.y[0]);
                printf("x1:%d,y1:%d\r\n", gTPS.x[1], gTPS.y[1]);
            }
            break;

        default:
            break;
    }
    for (int i = 0; i < 2; i++)
    {
        gTPS.x[i] = 0;
        gTPS.y[i] = 0;
    }
    position->status = 0;
    position->x = gTPS.x[0];
    position->y = gTPS.y[0];
}


void get_ft6236_touch_sta(TP_POSITION_T *position){
    scan_ft6236();
    count_position_ft6236(position);
}



void init_ft6236(void){

    uint8_t w_data,r_data = 0;
    memset(&gTPS,0,sizeof(TouchPoint_T));//清0

    //GPIO初始化,INT中断和复位引脚
    ds_touch_gpio_init();
    //复位初始化,拉低
    ds_gpio_set_touch_rst(GPIO_RST_LOW);
    vTaskDelay(50 / portTICK_PERIOD_MS);
    ds_gpio_set_touch_rst(GPIO_RST_HIGH);
    vTaskDelay(100 / portTICK_PERIOD_MS);
    //I2C初始化
    i2c_master_init();
    vTaskDelay(100 / portTICK_PERIOD_MS);

    w_data = 0;
    //设置正常操作模式
    i2c_master_write_slave(FI_DEVIDE_MODE,&w_data,1);
    w_data = 22;
    //设置触摸有效值22,越小越灵敏
 	i2c_master_write_slave(FI_ID_G_THGROUP,&w_data,1);	    
    i2c_master_read_slave(FI_ID_G_THGROUP,&r_data,1);
    printf("init THGROUP = %d \n",r_data);
    //设置激活周期 不能小于12 最大14
 	i2c_master_write_slave(FI_ID_G_PERIODACTIVE,&w_data,1); 
	i2c_master_read_slave(FI_ID_G_PERIODACTIVE,&r_data,1);
    printf("init PERIODACTIVE = %d \n",r_data);
	w_data = 0;
	//中断产生方式 持续电平
	i2c_master_write_slave(FI_ID_G_MODE,&w_data,1);
	i2c_master_read_slave(FI_ID_G_MODE,&r_data,1);
    printf("init G_MODE = %d \n",r_data);
}

结合芯片手册去看,更能够理解,包括细节性的东西我都在代码里注释了,也是给自己留一个记录。

实验

OK,这些都写好了之后,在主函数里面进行调用。

ESP32开发---驱动触摸屏

 编译一下,成功之后上开发板进行测试!

ESP32开发---驱动触摸屏

可以看到,实验是成功了!

触摸屏初级的使用就已经到这里完成了。

虽然写的不多,但是花的时间是真的多啊。


以上参考正点原子linux驱动开发教程、FT6x36芯片手册,野火STM32库文件开发教程等...文章来源地址https://www.toymoban.com/news/detail-474760.html

到了这里,关于ESP32开发---驱动触摸屏的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 全志V3S嵌入式驱动开发(触摸屏驱动)

    【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】         所谓的触摸屏,其实就是在普通的lcd屏幕之上,再加一层屏而已。这个屏是透明的,这样客户就可以看到下面lcd屏幕的内容,另外一方面,通过触摸信号,还可以实现人和机器的自然

    2024年02月08日
    浏览(17)
  • Linux 触摸屏 (IIC驱动详解)

    本文使用触摸屏iic驱动,驱动编写中要使用 总线,设备,驱动 分层的思想,IIC总线,触摸屏驱动,触摸屏设备,   一般 SOC 的 I2C 总线驱动都是由半导体厂商编写的,比如 I.MX6U 的 I2C 适配器驱动 NXP 已经编写好了,这个不需要用户去编写。因此 I2C 总线驱动对我们这些 SOC 使

    2023年04月11日
    浏览(23)
  • STM32F103C8T6+2.4寸SPI TFT触摸屏代码+标准库 项目开发

    目录 模块清单: 模块介绍: 1:STM32F103C8T6 2:2.4寸SPI TFT触摸屏 项目结果展示 2.4寸 TFT SPI显示触摸屏 2.4寸 SPI TFT 显示触摸屏代码下载链接: https://download.csdn.net/download/weixin_49492286/88458377 清单 STM32F103C8T6 2.4寸SPI TFT触摸屏         STM32F103C8T6是意法半导体(STMicroelectronics)推

    2024年02月07日
    浏览(27)
  • mipi接口 1280(RGB)*720 LCD屏开发驱动笔记帖 1、MTK8788[android 9.0]GT9XX TP触摸屏驱动流程分析

    ps:创业开发产品,自学笔记,不一定适合教材性的阅读,零碎整理,自我总结用 材料:4.1寸lcd屏两块,屏自带触控,屏幕资料具备,rk3399和MK8788开发版上分别开发。 1】rk3399       ​​​​​​​ 开发板:友善的rk3399v2开发版, 资料链接 : 处理器:RK3399 内核: 编译工具

    2023年04月08日
    浏览(66)
  • 嵌入式培训机构四个月实训课程笔记(完整版)-Linux ARM驱动编程第三天-ARM Linux ADC和触摸屏开发 (物联技术666)

    链接:https://pan.baidu.com/s/1V0E9IHSoLbpiWJsncmFgdA?pwd=1688 提取码:1688   教学内容: 1 、 ADC S3C2440 的 A/D 转换器包含一个 8 通道的模拟输入转换器,可以将模拟输入信号转换成 10 位数字编码。 在 A/D 转换时钟频率为 2.5MHz 时,其最大转换率为 500KSPS ( 5 个时钟周期完成一次转换) 输

    2024年02月20日
    浏览(21)
  • 【Liux下6818开发板(ARM)】触摸屏

    (꒪ꇴ꒪ ),hello我是 祐言 博客主页:C语言基础,Linux基础,软件配置领域博主🌍 快上🚘,一起学习! 送给读者的一句鸡汤🤔: 集中起来的意志可以击穿顽石! 作者水平很有限,如果发现错误,可在评论区指正,感谢🙏         在正式学习触摸屏之前,我们先来了解一下事件

    2024年02月14日
    浏览(19)
  • 【ChatGpt】ChatGpt解答了 “我一下午都没解决的“ Linux触摸屏驱动的问题

    现实问题: 有一个基于Linux4.19内核开发了,在海思SS528芯片运行的系统,用鼠标可以正常使用。 现在要求使用一块公司开发的 多点触控屏 连接这个系统,能正常使用。 分析问题: 要在LInux系统使用触控屏,可能需要移植 tslib 的库,这个有以前做过,可以自己解决。 移植后

    2024年02月07日
    浏览(17)
  • 【SA8295P 源码分析】66 - Android 侧内核层 TouchScreen Panel(TP)触摸屏驱动源码分析

    【源码分析】 因为一些原因,本文需要移除, 对于已经购买的兄弟,不用担心,不是跑路, 我会继续持续提供技术支持, 有什么模块想学习的,或者有什么问题有疑问的, 请私聊我,我们 +VX 沟通技术问题,一起学习,一起进步 接下来,我一一私聊已经购买的兄弟添加V

    2024年02月11日
    浏览(27)
  • 【触摸屏功能测试】昆仑通态MCGS——测试通过HJ212_TCPIP驱动4G功能发送212报文

    型号 :TPC7022Ni 测试内容: 实现4G触摸屏,通过自带的4G卡向平台发送HJ212报文 本驱动构件用于MCGS软件,通过污染物在线监控(监测)系统数据传输标准协议向下位机数采仪发送各类指令; 驱动类型 以太网子设备,须挂接在“通用TCPIP父设备”下才能工作 通讯协议 污染物在线监控

    2024年02月07日
    浏览(54)
  • 中文编程工具开发语言开发的实际案例:触摸屏点餐软件应用场景实例

    中文编程工具开发语言开发的实际案例:触摸屏点餐软件应用场景实例 软件特色: 1、功能实用,操作简单,不会电脑也会操作,软件免安装,已内置数据库。软件在关闭的时候,可以设置会员数据备份到U盘,数据本机备份一份,U盘备份一份,双重备份数据安全。 2、软件既

    2024年02月08日
    浏览(17)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包