目录
概述
1 触摸屏功能实现
1.1 扫描监测方式
1.2 中断监测方式
2 ST7796-LCD
2.1 引脚定义
2.1.1 ST7796-LCD
2.1.2 MCU IO与LCD PIN对应关系
2.1.3 MCU IO与Touch PIN对应关系
2.2 FT6336的寄存器
2.2.1 FT6336寄存器列表
2.2.2 寄存器功能介绍
3 STM32Cube控制配置FT6336驱动
3.1 引脚配置
3.2 STM32Cube生成软件架构
4 程序实现
4.1 FT6336驱动程序
4.2 触摸屏功能
5 源代码
5.1 FT6336驱动程序
5.2 触摸屏功能程序
概述
本文主要介绍使用FT6336的INT引脚的中断功能优化触摸屏功能的性能。将FT6336的INT与MCU的IO连接起来,且使能该IO的外部输入中断功能。笔者详细介绍了代码的实现过程,并重写了触摸屏的功能。
1 触摸屏功能实现
1.1 扫描监测方式
笔者使用的LCD上的触摸屏功能是基于FT6336芯片实现,该芯片与MCU之间I2C接口通信。MCU可通过实时读取FT6336的寄存器的值得到,当前的坐标点位。
采用如下架构设计程序:MCU需要实时读取FT6336采集到的点坐标,即使屏幕没有被触摸,读取数据的操作,依然被执行。
存在的问题:
1)MCU需要周期性的读取FT6336寄存器的值,即使没有触碰操作,该过程依然持续
2)在没有触碰屏幕的情况下也读取FT6336寄存器的值,而该值是没有任何意义的,这极大浪费MCU的时间
1.2 中断监测方式
FT6336控制芯片提供了一个INT中断引脚,当屏幕有触动发生时,INT引脚会发出一个低电平信号。MCU可以通过外部中断的方式监测该信号的状态。当中断发生时,说明屏幕被触动,此时,MCU需要读取FT6336寄存器中的点坐标值。
2 ST7796-LCD
2.1 引脚定义
2.1.1 ST7796-LCD
LCD的PIN引脚功能介绍
序号 | 模块引脚 | 引脚说明 |
1 | VCC | 屏电源正 |
2 | GND | 屏电源地 |
3 | LCD_CS | 液晶屏片选控制信号,低电平有效 |
4 | LCD_RST | 液晶屏复位控制信号,低电平复位 |
5 | LCD_RS | 液晶屏命令/数据选择控制信号 高电平:数据,低电平:命令 |
6 | SDI(MOSI) | SPI总线写数据信号(SD卡和液晶屏共用) |
7 | SCK | SPI总线时钟信号(SD卡和液晶屏共用) |
8 | LED | 液晶屏背光控制信号(如需要控制,请接引脚,如不需要控制,可以不接) |
9 | SDO(MISO) | SPI总线读数据信号(SD卡和液晶屏共用) |
10 | CTP_SCL | 电容触摸屏IIC总线时钟信号(无触摸屏的模块不需连接) |
11 | CTP_RST | 电容触摸屏复位控制信号,低电平复位(无触摸屏的模块不需连接) |
12 | CTP_SDA | 电容触摸屏IIC总线数据信号(无触摸屏的模块不需连接) |
13 | CTP_INT | 电容触摸屏IIC总线触摸中断信号,产生触摸时,输入低电平到主控(无触摸屏的模块不需连接) |
14 | SD_CS | SD卡片选控制信号,低电平有效(不使用SD卡功能,可不接) |
实体LCD Port对应关系如下图所示
2.1.2 MCU IO与LCD PIN对应关系
STM32 PIN引脚 | LCD PIN引脚 |
---|---|
PB5-MOSI | MOSI |
PB4-MISO | MISO |
PB3-SCK | SCK |
PB6 | CS |
PB9 | RST |
PB8 | RS |
2.1.3 MCU IO与Touch PIN对应关系
STM32 PIN引脚 | touch PIN引脚 |
---|---|
PH4 | I2C-SCK |
PH5 | I2C-SDA |
PH10 | INIT |
PH9 | RST |
2.2 FT6336的寄存器
2.2.1 FT6336寄存器列表
2.2.2 寄存器功能介绍
1)设备模式配置
2)姿势ID寄存器
3)TD状态寄存器
4) Pn_XH寄存器
5) Pn_XL寄存器
6) Pn_YH寄存器
7) Pn_YL寄存器
8) Pn_WEIGHT寄存器
9) Pn_MISC寄存器
3 STM32Cube控制配置FT6336驱动
3.1 引脚配置
1) i2c 引脚配置
其用于实现I2C驱动,实时读取FT6336寄存器的中
2) 中断和复位引脚配置
3) 中断函数使能
3.2 STM32Cube生成软件架构
1) 创建ft6336.c文件,编写ft6336的驱动程序
2) 创建usr_touch.c文件,实现触摸屏功能程序
4 程序实现
4.1 FT6336驱动程序
代码47~54: 复位FT6336
代码55~65: 写寄存器函数
代码67~77: 读寄存器函数
代码84行: 初始化IO
代码85行: 复位芯片
代码87行:读取芯片的ID
代码88行:比较ID
4.2 触摸点监测功能
代码95~100行: 外部中断的回调函数,检测中断是否发生
代码102~105行:清除触摸屏按下的标志
代码107~110行:清除触摸屏按下的标志
4.2 触摸屏功能
代码25~29行: 调用芯片初始化函数
代码39行:读取当前触摸屏状态
代码47行:读取触摸点
代码110: 清除当前触摸状态
5 源代码
5.1 FT6336驱动程序
创建FT6336.c,编写如下文件:
/* USER CODE BEGIN Header */
/**
******************************************************************************
* File Name : ft6336.c
* Description : I2C drive based on STM32F4
* STM32 HAL library ver: STM32Cube_FW_F4_V1.27.1
*
******************************************************************************
* @attention
*
* Copyright (c) 2024~2029 mingfei.tang
* All rights reserved.
*
*************************************************************************
*/
/* USER CODE END Header */
#include "ft6336.h"
static int isPressed = 0;
static void touch_delay_us(uint32_t us)
{
uint32_t i=0;
while(us--){
for(i=0;i<1000;i++);
}
}
static void ft6336_TouchIO_Init( void )
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
RCC_TOUCH_CLK_ENABLE();
/*Configure GPIO pin Output Level */
HAL_GPIO_WritePin(GPIO_PORT_TOUCH, FT_RST_PIN,GPIO_PIN_RESET);
/*Configure GPIO pin : RST */
GPIO_InitStruct.Pin = FT_RST_PIN;
GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_InitStruct.Pull = GPIO_PULLUP;
HAL_GPIO_Init(GPIO_PORT_TOUCH, &GPIO_InitStruct);
}
static void ft6336_rest( void )
{
FT_RST_L;
touch_delay_us( 10 );
FT_RST_H;
touch_delay_us( 50000 );
}
uint8_t ft6336_WeReg( uint16_t regAdd, uint8_t *pData, uint16_t Size )
{
HAL_StatusTypeDef status;
status = HAL_I2C_Mem_Write( &hi2c2, FT6336_ADDR, regAdd,
I2C_MEMADD_SIZE_8BIT, pData, Size, 1000);
if( status == HAL_OK)
return FT6336_OK;
else
return FT6336_ERROR;
}
uint8_t ft6336_RdReg( uint16_t regAdd, uint8_t *pData, uint16_t Size )
{
HAL_StatusTypeDef status;
status = HAL_I2C_Mem_Read( &hi2c2, FT6336_ADDR, regAdd,
I2C_MEMADD_SIZE_8BIT, pData, Size, 1000);
if( status == HAL_OK)
return FT6336_OK;
else
return FT6336_ERROR;
}
int ft6336_Init( void )
{
uint8_t id;
ft6336_TouchIO_Init();
ft6336_rest();
// read chip id
ft6336_RdReg(FT_ID_G_FOCALTECH_ID,&id, 1);
if(id != PANNEL_ID)
{
return FT_FALSE;
}
return FT_TRUE;
}
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
if( GPIO_Pin == ft6336_irq_Pin){
isPressed = 1;
}
}
void ft6336_clearPressed( void )
{
isPressed = 0;
}
int ft6336_getPressed( void )
{
return isPressed;
}
/* End of this file */
5.2 触摸屏功能程序
创建usr_touch.c,编写如下文件:
/**
******************************************************************************
* (c) Copyright 2024, tangmingfei2013@126.com
* All Rights Reserved
* @file usr_touch.c
* @author mingfei tang
* @version V1.0.0
* @date 2018/03/25
* @description:
This source code and any compilation or derivative thereof is the proprietary
information of mingfei.tang and is confidential in nature.
Under no circumstances is this software to be combined with any
Open Source Software in any way or placed under an Open Source License
of any type without the express written permission of mingfei.tang
******************************************************************************
**/
/* Includes ------------------------------------------------------------------*/
#include "usr_touch.h"
#include "lcd_drv.h"
extern _lcd_dev lcddev;
const uint16_t touch_press_reg[2]={FT_TP1_REG,FT_TP2_REG};
static int touch_isOK;
void usr_touchInit( void )
{
touch_isOK = ft6336_Init();
}
uint8_t usr_ScanTouchProcess( stru_pos *pPos)
{
uint8_t buf[4];
uint8_t i = 0;
uint8_t set = FT_FALSE;;
uint8_t pointNub = 0;
static uint8_t cnt = 0;
int isPressed;
isPressed = ft6336_getPressed();
if( touch_isOK == FT_FALSE || !isPressed )
return set;
cnt++;
if((cnt%10)==0 || cnt<10)
{
// read number of touch points
ft6336_RdReg(FT_REG_NUM_FINGER,&pointNub,1);
pointNub= pointNub&0x0f;
if( pointNub && (pointNub < 3) )
{
cnt=0;
// read the point value
pPos->status_bit.tpDown = 1;
pPos->status_bit.tpPress = 1;
pPos->status_bit.ptNum = pointNub;
for( i=0; i < CTP_MAX_TOUCH; i++)
{
ft6336_RdReg( touch_press_reg[i], buf, 4 );
if( pPos->status_bit.ptNum )
{
switch(lcddev.dir)
{
case 0:
pPos->xpox[i]=((uint16_t)(buf[0]&0X0F)<<8)+buf[1];
pPos->ypox[i]=((uint16_t)(buf[2]&0X0F)<<8)+buf[3];
break;
case 1:
pPos->ypox[i]=lcddev.height-(((uint16_t)(buf[0]&0X0F)<<8)+buf[1]);
pPos->xpox[i]=((uint16_t)(buf[2]&0X0F)<<8)+buf[3];
break;
case 2:
pPos->xpox[i]=lcddev.width-(((uint16_t)(buf[0]&0X0F)<<8)+buf[1]);
pPos->ypox[i]=lcddev.height-(((uint16_t)(buf[2]&0X0F)<<8)+buf[3]);
break;
case 3:
pPos->ypox[i] = ((uint16_t)(buf[0]&0X0F)<<8)+buf[1];
pPos->xpox[i] = lcddev.width-(((uint16_t)(buf[2]&0X0F)<<8)+buf[3]);
break;
}
printf("x[%d]:%d,y[%d]:%d\r\n",i,pPos->xpox[i],i,pPos->ypox[i]);
}
}
set = FT_TRUE;
if( pPos->xpox[0]==0 && pPos->ypox[0]==0)
{
pPos->status = 0;
}
}
}
if( pPos->status_bit.ptNum == 0)
{
if( pPos->status_bit.tpDown )
{
pPos->status_bit.tpDown = 0;
}
else
{
pPos->xpox[0] = 0xffff;
pPos->ypox[0] = 0xffff;
pPos->status = 0;
}
}
// clear pressed status
ft6336_clearPressed();
if( cnt>240 )
cnt=10;
return set;
}
/* End of this file */