使用STM32CubeMX移植TouchGFX 一文中介绍了如何用TouchGFX点亮屏幕,但是此时屏幕还没有触摸的功能。下面将介绍如何添加触摸屏驱动到TouchGFX中
1. STM32CubeMX配置
在使用STM32CubeMX移植TouchGFX文中的STM32CubeMX配置基础上,再激活一个定时器,用来给IIC通信提供微秒(us)延时。本文通过软件来模拟IIC通信,因此不使用STM32CubeMX来进行IIC配置
2. KEIL中添加触摸芯片驱动
本文中的RGB (800 * 480)屏触摸驱动IC为FT5206芯片,该驱动芯片通过 4 根线与外部连接:CT_RST(PI8), CT_INT(PH7), CT_SDA(PI3), CT_SCL(PH6)。由于通过软件来模拟IIC通信,因此不使用STM32CubeMX来进行配置
2.1 添加微秒延时函数
在自动生成的tim.c文件中添加微秒延时函数,并在tim.h中声明
void delay_us(uint16_t us)
{
uint16_t differ = 0xffff - us -5;
__HAL_TIM_SET_COUNTER(&htim6, differ);
HAL_TIM_Base_Start(&htim6);
while(differ < 0xffff - 5){
differ = __HAL_TIM_GET_COUNTER(&htim6);
}
HAL_TIM_Base_Stop(&htim6);
}
2.2 软件模拟IIC通信
⏩ IIC通信头文件:在工程中添加IIC通信头文件ctiic.h
#ifndef __CT_IIC_H
#define __CT_IIC_H
#include "main.h"
#define IIC_SDA_PORT GPIOI
#define IIC_SDA_PIN GPIO_PIN_3
#define IIC_SCL_PORT GPIOH
#define IIC_SCL_PIN GPIO_PIN_6
#define SET_SDA_PIN_H HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_SET)
#define SET_SDA_PIN_L HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, GPIO_PIN_RESET)
#define SET_SCL_PIN_H HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_SET)
#define SET_SCL_PIN_L HAL_GPIO_WritePin(IIC_SCL_PORT, IIC_SCL_PIN, GPIO_PIN_RESET)
void SET_SDA_DIR_OUT(void);
void SET_SDA_DIR_IN(void);
uint8_t READ_IIC_SDA(void);
void WRITE_IIC_SDA(uint8_t state);
void IIC_Init(void);
void IIC_Start(void);
void IIC_Stop(void);
uint8_t IIC_Wait_Ack(void);
void IIC_Ack(void);
void IIC_NAck(void);
void IIC_Send_Byte(uint8_t txd);
uint8_t IIC_Read_Byte(unsigned char ack);
#endif
⏩ IIC通信源文件:在工程中添加IIC通信源文件ctiic.c
#include "ctiic.h"
#include "tim.h"
void SET_SDA_DIR_OUT(void)
{
GPIO_InitTypeDef GPIO_Initure;
GPIO_Initure.Pin = IIC_SDA_PIN;
GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull = GPIO_PULLUP;
GPIO_Initure.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(IIC_SDA_PORT, &GPIO_Initure);
}
void SET_SDA_DIR_IN(void)
{
GPIO_InitTypeDef GPIO_Initure;
GPIO_Initure.Pin = IIC_SDA_PIN;
GPIO_Initure.Mode = GPIO_MODE_INPUT;
GPIO_Initure.Pull = GPIO_PULLUP;
GPIO_Initure.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(IIC_SDA_PORT, &GPIO_Initure);
}
uint8_t READ_IIC_SDA(void)
{
return HAL_GPIO_ReadPin(IIC_SDA_PORT, IIC_SDA_PIN);
}
void WRITE_IIC_SDA(uint8_t state)
{
HAL_GPIO_WritePin(IIC_SDA_PORT, IIC_SDA_PIN, state);
}
void IIC_Init()
{
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOI_CLK_ENABLE();
__HAL_RCC_GPIOH_CLK_ENABLE();
GPIO_Initure.Pin = IIC_SCL_PIN;
GPIO_Initure.Mode = GPIO_MODE_OUTPUT_PP;
GPIO_Initure.Pull = GPIO_PULLUP;
GPIO_Initure.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(IIC_SCL_PORT, &GPIO_Initure);
GPIO_Initure.Pin = IIC_SDA_PIN;
HAL_GPIO_Init(IIC_SDA_PORT, &GPIO_Initure);
SET_SDA_PIN_H;
SET_SCL_PIN_H;
}
void IIC_Start()
{
SET_SDA_DIR_OUT();
SET_SDA_PIN_H;
SET_SCL_PIN_H;
delay_us(30);
SET_SDA_PIN_L;
delay_us(2);
SET_SCL_PIN_L;
}
void IIC_Stop(void)
{
SET_SDA_DIR_OUT();
SET_SCL_PIN_L;
SET_SDA_PIN_L;
delay_us(30);
SET_SCL_PIN_H;
delay_us(2);
SET_SDA_PIN_H;
}
uint8_t IIC_Wait_Ack(void)
{
uint8_t ucErrTime = 0;
SET_SDA_DIR_IN();
SET_SDA_PIN_H;
SET_SCL_PIN_H;
delay_us(2);
while(READ_IIC_SDA()){
ucErrTime++;
if(ucErrTime > 250){
IIC_Stop();
return 1;
}
delay_us(2);
}
SET_SCL_PIN_L;
return 0;
}
void IIC_Ack(void)
{
SET_SCL_PIN_L;
SET_SDA_DIR_OUT();
SET_SDA_PIN_L;
delay_us(2);
SET_SCL_PIN_H;
delay_us(2);
SET_SCL_PIN_L;
}
void IIC_NAck(void)
{
SET_SCL_PIN_L;
SET_SDA_DIR_OUT();
SET_SDA_PIN_H;
delay_us(2);
SET_SCL_PIN_H;
delay_us(2);
SET_SCL_PIN_L;
}
void IIC_Send_Byte(uint8_t txd)
{
uint8_t t;
SET_SDA_DIR_OUT();
SET_SCL_PIN_L;
for(t=0;t<8;t++){
WRITE_IIC_SDA((txd&0x80)>>7);
txd <<= 1;
delay_us(2);
SET_SCL_PIN_H;
delay_us(2);
SET_SCL_PIN_L;
delay_us(2);
}
}
uint8_t IIC_Read_Byte(unsigned char ack)
{
uint8_t i,receive = 0;
SET_SDA_DIR_IN();
delay_us(30);
for(i=0;i<8;i++ )
{
SET_SCL_PIN_L;
delay_us(2);
SET_SCL_PIN_H;
receive <<= 1;
if(READ_IIC_SDA())
receive++;
delay_us(2);
}
if (!ack)
IIC_NAck();
else
IIC_Ack();
return receive;
}
2.3 FT5206芯片驱动
⏩在工程中添加FT5206芯片驱动头文件ft5206.h
#ifndef __FT5206_H
#define __FT5206_H
#include "ctiic.h"
#define FT_CMD_WR 0X70
#define FT_CMD_RD 0X71
#define FT_DEVIDE_MODE 0x00
#define FT_REG_NUM_FINGER 0x02
#define FT_TP1_REG 0X03
#define FT_TP2_REG 0X09
#define FT_TP3_REG 0X0F
#define FT_TP4_REG 0X15
#define FT_TP5_REG 0X1B
#define FT_ID_G_LIB_VERSION 0xA1
#define FT_ID_G_MODE 0xA4
#define FT_ID_G_THGROUP 0x80
#define FT_ID_G_PERIODACTIVE 0x88
#define TOUCH_MAX_NUM 5
typedef struct
{
uint8_t touch_type;
uint8_t dir; //0表示竖屏,1表示横屏
uint16_t pix_w;
uint16_t pix_h;
uint8_t touch_num;
uint16_t x[TOUCH_MAX_NUM];
uint16_t y[TOUCH_MAX_NUM];
}TouchTypedef;
uint8_t FT5206_WR_Reg(uint16_t reg, uint8_t *buf, uint8_t len);
void FT5206_RD_Reg(uint16_t reg, uint8_t *buf, uint8_t len);
void FT5206_Init(void);
uint8_t FT5206_Scan(TouchTypedef *touch);
#endif
⏩ 在工程中添加FT5206芯片驱动文件ft5206.c
#include "ft5206.h"
#include "stdio.h"
static const uint16_t FT5206_TPX_TBL[5]={FT_TP1_REG, FT_TP2_REG, FT_TP3_REG, FT_TP4_REG, FT_TP5_REG};
uint8_t FT5206_WR_Reg(uint16_t reg, uint8_t *buf, uint8_t len)
{
uint8_t i;
uint8_t ret=0;
IIC_Start();
IIC_Send_Byte(FT_CMD_WR);
IIC_Wait_Ack();
IIC_Send_Byte(reg&0XFF);
IIC_Wait_Ack();
for(i=0; i<len; i++)
{
IIC_Send_Byte(buf[i]);
ret = IIC_Wait_Ack();
if(ret)break;
}
IIC_Stop();
return ret;
}
void FT5206_RD_Reg(uint16_t reg, uint8_t *buf, uint8_t len)
{
uint8_t i;
IIC_Start();
IIC_Send_Byte(FT_CMD_WR);
IIC_Wait_Ack();
IIC_Send_Byte(reg&0XFF);
IIC_Wait_Ack();
IIC_Start();
IIC_Send_Byte(FT_CMD_RD);
IIC_Wait_Ack();
for(i=0; i<len; i++)
{
buf[i]=IIC_Read_Byte(i==(len-1)?0:1);
}
IIC_Stop();
}
void FT5206_Init(void)
{
uint8_t temp[2];
GPIO_InitTypeDef GPIO_Initure;
__HAL_RCC_GPIOH_CLK_ENABLE();
__HAL_RCC_GPIOI_CLK_ENABLE();
//PH7
GPIO_Initure.Pin=GPIO_PIN_7;
GPIO_Initure.Mode=GPIO_MODE_INPUT;
GPIO_Initure.Pull=GPIO_PULLUP;
GPIO_Initure.Speed=GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOH,&GPIO_Initure);
//PI8
GPIO_Initure.Pin=GPIO_PIN_8;
GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP;
HAL_GPIO_Init(GPIOI,&GPIO_Initure);
IIC_Init();
HAL_GPIO_WritePin(GPIOI,GPIO_PIN_8,GPIO_PIN_RESET);
HAL_Delay(20);
HAL_GPIO_WritePin(GPIOI,GPIO_PIN_8,GPIO_PIN_SET);
HAL_Delay(50);
temp[0]=0;
FT5206_WR_Reg(FT_DEVIDE_MODE,temp,1);
FT5206_WR_Reg(FT_ID_G_MODE,temp,1);
temp[0]=22;
FT5206_WR_Reg(FT_ID_G_THGROUP,temp,1);
temp[0]=12;
FT5206_WR_Reg(FT_ID_G_PERIODACTIVE,temp,1);
FT5206_RD_Reg(FT_ID_G_LIB_VERSION,&temp[0],2);
if((temp[0]==0X30&&temp[1]==0X03)||temp[1]==0X01||temp[1]==0X02)
{
printf("CTP ID:%xrn",((uint16_t)temp[0]<<8)+temp[1]);
return ;
}
printf("CTP ID:%xrn",((uint16_t)temp[0]<<8)+temp[1]);
}
uint8_t FT5206_Scan(TouchTypedef *touch)
{
uint8_t buf[4];
uint8_t touch_num;
uint8_t i = 0;
//uint8_t touch_state = 0;
FT5206_RD_Reg(FT_REG_NUM_FINGER,&touch_num,1);
touch->touch_num = touch_num;
if((touch_num&0XF)&&((touch_num&0XF)<6))
{
for(i = 0;i<touch_num;i++){
FT5206_RD_Reg(FT5206_TPX_TBL[i],buf,4);
uint16_t x = 0;
uint16_t y = 0;
if(touch->dir){
y = ((uint16_t)(buf[0]&0X0F)<<8)+buf[1];
x = ((uint16_t)(buf[2]&0X0F)<<8)+buf[3];
}else{
x = touch->pix_h - (((uint16_t)(buf[0]&0X0F)<<8)+buf[1]);
y = ((uint16_t)(buf[2]&0X0F)<<8)+buf[3];
}
touch->x[i] = x;
touch->y[i] = y;
}
}else{
touch->touch_num = 0;
return 0;
}
return touch_num;
}
2.4 将触摸驱动添加到TouchGFX中
将触摸驱动添加到触摸控制文件STM32TouchController.cpp中
#include <STM32TouchController.hpp>
extern "C"{
#include "ft5206.h"
}
TouchTypedef mtouch;
void STM32TouchController::init()
{
FT5206_Init();
mtouch.dir = 1;
mtouch.pix_w = 800;
mtouch.pix_h = 480;
}
bool STM32TouchController::sampleTouch(int32_t& x, int32_t& y)
{
if(FT5206_Scan(&mtouch)){
x = mtouch.x[0];
y = mtouch.y[0];
return true;
}
return false;
}
3. TouchGFX Designer中添加点击事件
在TouchGFX Designer中,创建一个按钮,实现点击后背景变色的功能⏩ 添加一个图标按钮,同时添加一个box作为背景
⏩ 添加交互动作:实现点击图标按钮,背景颜色由黑色变为白色
⏩ 点击Generate Code生成TouchGFX代码
4. 下载测试
回到Keil工程中,编译无误后,下载到开发板中。点击屏幕上的按钮,若屏幕背景色由黑色变为白色,说明点击成功,触摸驱动添加成功