使用STM32CubeMX移植TouchGFX 一文中介绍了如何用TouchGFX点亮屏幕,但是此时屏幕还没有触摸的功能。下面将介绍如何添加触摸屏驱动到TouchGFX中

一、STM32CubeMX配置

使用STM32CubeMX移植TouchGFX 文中的STM32CubeMX配置基础上,再激活一个定时器,用来给IIC通信提供微秒(us)延时。本文通过软件来模拟IIC通信,因此不使用STM32CubeMX来进行IIC配置

TouchGFX界面开发 | 添加触摸屏驱动_c++

二、MKD-ARM 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:%x\r\n",((uint16_t)temp[0]<<8)+temp[1]);
        return ;
    }
		printf("CTP ID:%x\r\n",((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;
}

三、TouchGFX Designer中添加点击事件

在TouchGFX Designer中,创建一个按钮,实现点击后背景变色的功能

  • 添加一个图标按钮,同时添加一个box作为背景

TouchGFX界面开发 | 添加触摸屏驱动_touchGFX_02

  • 添加交互动作:实现点击图标按钮,背景颜色由黑色变为白色

TouchGFX界面开发 | 添加触摸屏驱动_单片机_03

  • 点击Generate Code生成TouchGFX代码

四、下载测试

回到Keil工程中,编译无误后,下载到开发板中。点击屏幕上的按钮,若屏幕背景色由黑色变为白色,说明点击成功,触摸驱动添加成功

TouchGFX界面开发 | 添加触摸屏驱动_c++_04


阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6