嵌入式系统与单片机|技术阅读
登录|注册

您现在的位置是:嵌入式系统与单片机 > 技术阅读 > TouchGFX界面开发 | 添加触摸屏驱动

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

关注+星标 不错过任何一次推送!

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


1. STM32CubeMX配置

文中的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:%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;
}


3. TouchGFX Designer中添加点击事件

在TouchGFX Designer中,创建一个按钮,实现点击后背景变色的功能⏩ 添加一个图标按钮,同时添加一个box作为背景


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


⏩ 点击Generate Code生成TouchGFX代码


4. 下载测试

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

往期推荐

● 

● 

● 

● 

● 

● 

● 

● 

扫二维码|关注我们

微信号|andyxi_linux

专注于嵌入式开发技术

分享、在看与点赞

只要你点,我们就是胖友