STM32F407_多点电容触摸(GT911)驱动

前言

做毕设用到了电容触摸屏,移植了几天内才整好。在网上找到的好多例程都是电容屏、电阻屏都融合到一起去了,对于新手来说,不是太好理解,所以我来分享一下我的认识、例程和学习过程中遇到的问题以及要注意的点。

1、简单介绍

GT911、GT928、GT9147都属于GT9系列非单层多点触控芯片,他们支持的触控点数不同(GT928支持10个点、GT911支持5个点)、驱动和感应通道也可能不同。可是他们的寄存器和IIC通讯时序是相同的,也就是说驱动程序是兼容的。
所以如果是使用的GT9147也可以看看这个文档,整理下思路。

2、触摸芯片与主机的硬件连接

接口介绍
VCC电源
GND
SCL与GT911进行IIC通信的时钟线
SDA与GT911进行IIC通信的数据线
INT当发生触摸时,GT911的INT脚会输出上升/下降沿(内部寄存器可以配置),主机就可以通过外部中断处理去读取触点信息。
RST复位引脚,拉低100us以上,即可复位。正常工作时,应该保持拉高

3、内部寄存器

GT911上电初始化情况,是由其内部FLASH中的若干个寄存器来决定的,我们下面对其中比较重要的进行讲解。

3.1、控制寄存器(0X8040)

通过往里面写入不同的8bit数据。可以使其完成不同的任务。
在这里插入图片描述
如图示,一般的操作是在复位时,先往0X8040里面写2,对其进行软复位,然后判断是否需要对其配置寄存器进行更新,若需要更新,则写入新版本的配置参数(这部分配合着后面来看才能看懂),然后在往0X8040里面写0,结束软复位,后面就能正常读取触摸坐标了。
总结一下:

  • 要更新配置:(一般来说,买到的屏幕商家都已经预先写进去了,不需要更新)
    • 1、往0X8040写2(开始软复位)
    • 2、往0X8047~0X8100写入新的配置寄存器参数
    • 3、往0X8040写0(结束软复位)
    • 4、后面正常读触点坐标
  • 不更新配置:
    • 1、往0X8040写2(开始软复位)
    • 2、往0X8040写0(结束软复位)
    • 3、后面正常读触点坐标

3.2、配置寄存器组(0X8047~0X8100)

在这里插入图片描述
在这里插入图片描述

如上图示,这里共有186个寄存器,用于配置GT9147的各个参数,这些参数对于不同的屏幕也都各有不同。一般买回来的里面呢都自带的有(也就是说,原来就是好用的,不需要再自己进行操作了)

如果你要是不小心把原来的覆盖掉了,就只能再重新写一次了(我在调试过程中就是这样,把其它型号的配置参数写进去了,要命的是我还没有正确的了,最后还是从我同学的一块同款屏幕上将这186个寄存器的值都读出来,又重新写入到我的屏幕的GT911中,才弄好了)

在这样的情况下,你就需要对这些寄存器的一些特性,做些更深入的了解了。

  • 0x8047——这个寄存器中,保存的是当前配置参数的版本号,你新写入配置参数的版本号,必须要比它大或者在相等的情况下,其他参数有变化,否则不会生效。
  • 0x80FF——这里需要写入的是从0x8047到0x80FE之间184个数据和的补码,否则那你写入的配置也不会生效。
  • 0x8100——用于控制是否将配置保存在GT911的FLASH中,写0,则不保存配置,写1则保存配置。

3.3、状态寄存器(0x814E)

寄存器bit7bit6bit5 bit4bit3 bit2 bit1 bit0
0x814Ebuffer状态large detectReserved有效触点个数

我们只看此寄存器的最高位和低四位即可。
最高位表示的Buffer状态,若有数据(有触摸),则Buffer为1‘
低四位表示有效出点的个数,0~5,0表示此时没有触摸。5表示此时有5点触摸
(我们上面提到过gt911最多同时支持五个触控点数)

3.4、坐标寄存器(0x8150-0x8177)

在这里插入图片描述
在这里插入图片描述
如上图所示,我们可以将其分为5组,其分别用来表示5个触点坐标
下面以触点1的坐标数据寄存器为例做具体讲解:

寄存器bit7~0寄存器bit7~0
0x8150触点1X坐标低8位0x8151触点1X坐标高8位
0x8152触点1Y坐标低8位0x8153触点1Y坐标高8位
0x8154触点1触摸尺寸低8位0x8155触点1触摸尺寸高8位

一般只用到触点的x,y坐标,所以只需要读取0X8150-0X8153的数据,组合即可得到触点坐标。其它四组分别是:0X8158、0X8160、0X8168和0X8170等开头的的16个寄存器组成,分别针对触点2~5的坐标。同样GT911也支持寄存器地址自增,我们只需要发送寄存器组的首地址,然后连续读取即可,GT9147会自动地址自增,从而提高读取速度。

4、初始化流程

4.1、IIC地址选择

GT911作为从设备,其地址有两种选择:

7bit地址8bit写地址8bit读地址
0x5D0xBA0xBB
0x140x280x29

其配置方法如下:

  • 将地址配置为0x28/0x29

    • 1、将RST引脚设置为上拉推挽输出模式,将INT引脚设置为上拉输入模式
    • 2、将RST拉低,延时大于1ms
    • 3、将RST拉高,延时大于5ms
    • 4、将INT配置为悬浮输入态,RST维持拉高输出
      在这里插入图片描述
  • 将地址配置为0xBA/0xBB

    • 1、将RST和INT引脚配置为输出模式并拉低
    • 2、延时1ms
    • 3、将RST拉高,延时大于5ms
    • 4、将INT配置为悬浮输入态,RST维持拉高输出
      在这里插入图片描述
      注意:因为我使用的是查询扫描模式,所以没有配置INT引脚的外部中断模式,如果需要,这里也需要配置。

4.2、更新GT911寄存器配置

就像上面3.2说的,如果刚买回来的触摸屏幕,里面应该是本身就有适配此屏幕的参数配置的,这一条就可以省略直接进行下面的4.3,去读取触摸点坐标值。
注:这点尤为关键,因为你非常容易写进去错误的寄存器配置导致原来的配置被覆盖掉,你还不知道原来的配置参数是多少。
如果你真的需要更新它。

  • 1、向命令寄存器(0x8040)写入2,开始软复位
  • 2、把配置参数数组(那186个参数)写入寄存器(0x8047-0x8100).
    • 1)、 0x8047——这个寄存器中,保存的是当前配置参数的版本号,你新写入配置参数的版本号,必须要比它大或者在相等的情况下,其他参数有变化,否则不会生效。
    • 2)、0x80FF——这里需要写入的是从0x8047到0x80FE之间184个数据和的补码,否则那你写入的配置也不会生效。
    • 3)、0x8100——用于控制是否将配置保存在GT911的FLASH中,写0,则不保存配置,写1则保存配置。
  • 3、往向命令寄存器(0x8040)写入0,结束软复位

5、触摸点坐标值读取

当有触摸发生时,GT911会有3个提示:

  • 1、INT会输出上升沿或下降沿信号。(由寄存器配置参数决定)
  • 2、状态寄存器0x814E的最高位(buffer状态位)的值变为1,表示数据已准备好。
  • 3、状态寄存器0x814E的低4位的值会变为触摸点个数,提示有多少个点被按下。

注意:读完坐标后,要把0x814E寄存器清为0,表示坐标点已读。否则GT911会一直输出INT信号,不继续检测触摸。

读取方法:

  • 1、使用INT中断,当发生触摸时,会进入外部中断处理程序,在中断服务中,可以去读取0x8114E中的低四位获取触摸点数,然后再去读去相应寄存器,获取触点坐标,读完后将0x814E寄存器清零。
  • 2、轮询读取0x814E寄存器值,若最高位为1,则通过低四位获取触摸点数,然后去读相应触摸点数的坐标值,读完后将0x814E清零。若最高位为0,则退出,等待下次监测。

轮询读取案例:

6、提示

  • 因为GT911的触摸检测频率小于100HZ,所以我们采用轮询读取时,读取频率设的小于100HZ即可。

7、代码部分

7.1、ctiic.h

#ifndef __MYCT_IIC_H
#define __MYCT_IIC_H
	   
#include "stm32f4xx.h"


//IO方向设置
#define CT_SDA_IN()  {GPIOB->MODER&=~(3<<(2*7));GPIOB->MODER|=0<<2*7;}	//PB7输入模式
#define CT_SDA_OUT() {GPIOB->MODER&=~(3<<(2*7));GPIOB->MODER|=1<<2*7;} 	//PB7输出模式
//IO操作函数	 
#define CT_IIC_SCL(x) GPIO_WriteBit(GPIOB,GPIO_Pin_6,(BitAction)(x)) 	//SCL
#define CT_IIC_SDA(x) GPIO_WriteBit(GPIOB,GPIO_Pin_7,(BitAction)(x)) 	//SDA
#define CT_READ_SDA   GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)  //输入SDA 

//IIC所有操作函数
void CT_IIC_Init(void);                	//初始化IIC的IO口				 
void CT_IIC_Start(void);				//发送IIC开始信号
void CT_IIC_Stop(void);	  				//发送IIC停止信号
void CT_IIC_Send_Byte(uint8_t txd);			//IIC发送一个字节
uint8_t CT_IIC_Read_Byte(unsigned char ack);	//IIC读取一个字节
uint8_t CT_IIC_Wait_Ack(void); 				//IIC等待ACK信号
void CT_IIC_Ack(void);					//IIC发送ACK信号
void CT_IIC_NAck(void);					//IIC不发送ACK信号

#endif

7.2、ctiic.c

#include "ctiic.h"
#include "DWT_Delay.h"

//控制I2C速度的延时
void CT_Delay(void)
{
	DWT_DelayUS(2);
}
//电容触摸芯片IIC接口初始化
void CT_IIC_Init(void)
{
	GPIO_InitTypeDef  GPIO_InitStructure;
	RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE); //使能GPIOB,F时钟
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;//PB0设置为推挽输出
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//输出模式
	GPIO_InitStructure.GPIO_OType = GPIO_OType_OD;//开漏输出
	GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
}
//产生IIC起始信号
void CT_IIC_Start(void)
{
  CT_IIC_SDA(1);
	CT_IIC_SCL(1);
	CT_Delay();

  CT_IIC_SDA(0);//START:when CLK is high,DATA change form high to low
	CT_Delay();
	CT_IIC_SCL(0); //钳住I2C总线,准备发送或接收数据
	CT_Delay();
}
//产生IIC停止信号
void CT_IIC_Stop(void)
{
  CT_IIC_SDA(0);//STOP:when CLK is high DATA change form low to high
	CT_Delay();
	CT_IIC_SCL(1);
	CT_Delay();
  CT_IIC_SDA(1);//发送I2C总线结束信号
	CT_Delay();
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
uint8_t CT_IIC_Wait_Ack(void)
{
	uint8_t ucErrTime = 0;
	uint8_t rack = 0;


  CT_IIC_SDA(1);
	CT_Delay();
	CT_IIC_SCL(1);
	CT_Delay();

	while (CT_READ_SDA)
	{
			ucErrTime++;

			if (ucErrTime > 250)
			{
					CT_IIC_Stop();
					rack = 1;
					break;
			}

			CT_Delay();
	}

	CT_IIC_SCL(0); //时钟输出0
	CT_Delay();
	return rack;
}
//产生ACK应答
void CT_IIC_Ack(void)
{
	CT_IIC_SDA(0);
	CT_Delay();
	CT_IIC_SCL(1);
	CT_Delay();
	CT_IIC_SCL(0);
	CT_Delay();
	CT_IIC_SDA(1);
	CT_Delay();
}
//不产生ACK应答
void CT_IIC_NAck(void)
{
	CT_IIC_SDA(1);
	CT_Delay();
	CT_IIC_SCL(1);
	CT_Delay();
	CT_IIC_SCL(0);
	CT_Delay();
}
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答
void CT_IIC_Send_Byte(uint8_t txd)
{
	uint8_t t;

	for (t = 0; t < 8; t++)
	{
			CT_IIC_SDA((txd & 0x80) >> 7);
			CT_Delay();
			CT_IIC_SCL(1);
			CT_Delay();
			CT_IIC_SCL(0);
			txd <<= 1;
	}

	CT_IIC_SDA(1);
}
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK
uint8_t CT_IIC_Read_Byte(unsigned char ack)
{
	uint8_t i, receive = 0;

	for (i = 0; i < 8; i++ )
	{
			receive <<= 1;
			CT_IIC_SCL(1);
			CT_Delay();

			if (CT_READ_SDA)receive++;

			CT_IIC_SCL(0);
			CT_Delay();
	}

	if (!ack)CT_IIC_NAck();//发送nACK
	else CT_IIC_Ack(); //发送ACK

	return receive;
}

7.3、gt911.h

#ifndef __GT911_H
#define __GT911_H	
#include "sys.h"	

#include "ctiic.h"
#include "Serial.h"
#include "DWT_Delay.h" 
#include "string.h" 

#include "lcd_init.h"
#define TP_PRES_DOWN 0x80  //触屏被按下	  
#define TP_CATH_PRES 0x40  //有按键按下了 
#define CT_MAX_TOUCH  5    //电容屏支持的点数,固定为5点

//触摸屏控制器
typedef struct
{
	uint16_t x[CT_MAX_TOUCH]; 		//当前坐标
	uint16_t y[CT_MAX_TOUCH];		//电容屏有最多5组坐标,电阻屏则用x[0],y[0]代表:此次扫描时,触屏的坐标,用
								//x[4],y[4]存储第一次按下时的坐标. 
	uint8_t  sta;					//笔的状态 
								//b7:按下1/松开0; 
	                            //b6:0,没有按键按下;1,有按键按下. 
								//b5:保留
								//b4~b0:电容触摸屏按下的点数(0,表示未按下,1表示按下)
}_m_tp_dev;

extern _m_tp_dev tp_dev;	 	//触屏控制器在touch.c里面定义
//IO操作函数	 
#define GT_RST    		PBout(9)	//GT911复位引脚
#define GT_INT    		PBin(8)		//GT911中断引脚	
   	
//I2C读写命令	
#define GT_CMD_WR 		0X28     	//写命令
#define GT_CMD_RD 		0X29		//读命令
  
//GT911 部分寄存器定义 
#define GT_CTRL_REG 	0X8040   	//GT911控制寄存器
#define GT_CFGS_REG 	0X8047   	//GT911配置起始地址寄存器
#define GT_CHECK_REG 	0X80FF   	//GT911校验和寄存器
#define GT_PID_REG 		0X8140   	//GT911产品ID寄存器

#define GT_GSTID_REG 	0X814E   	//GT911当前检测到的触摸情况
#define GT_TP1_REG 		0X8150  	//第一个触摸点数据地址
#define GT_TP2_REG 		0X8158		//第二个触摸点数据地址
#define GT_TP3_REG 		0X8160		//第三个触摸点数据地址
#define GT_TP4_REG 		0X8168		//第四个触摸点数据地址
#define GT_TP5_REG 		0X8170		//第五个触摸点数据地址  
 
void GT911_Send_Cfg(uint8_t mode);                           /*更新GT911配置参数*/
uint8_t GT911_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len); /*向GT911写入一次数据*/
void GT911_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len);    /*从GT911读出一次数据*/
uint8_t GT911_Init(void);                                    /*初始化GT911触摸屏*/
uint8_t GT911_Scan(uint8_t mode);                            /*扫描触摸屏(采用查询方式)*/
#endif

7.4、GT911.c

#include "gt911.h"

#include "IIC.h"
_m_tp_dev tp_dev;				


/*五个触摸点的数据寄存器起始地址*/
const uint16_t GT911_TPX_TBL[5]={GT_TP1_REG,GT_TP2_REG,GT_TP3_REG,GT_TP4_REG,GT_TP5_REG};

//GT911配置参数表--适用于耀元鸿2.8寸IPS屏幕。不同尺寸屏幕配置参数会有区别
const uint8_t GT911_CFG_TBL[]=
{ 
0x61,0xf0,0x00,0x40,0x01,0x05,0x35,0x00,0x02,0x08,
0x1e,0x08,0x50,0x3c,0x0f,0x05,0x00,0x00,0x00,0x00,
0x50,0x00,0x00,0x18,0x1a,0x1e,0x14,0x87,0x27,0x0a,
0x4b,0x4d,0xd3,0x07,0x00,0x00,0x00,0x02,0x32,0x1c,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x32,0x00,0x00,

0x2a,0x32,0x64,0x94,0xd5,0x02,0x07,0x00,0x00,0x04,
0xa5,0x35,0x00,0x91,0x3d,0x00,0x80,0x46,0x00,0x70,
0x51,0x00,0x63,0x5d,0x00,0x63,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,

0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x14,0x12,0x10,0x0e,0x0c,0x0a,0x08,0x06,
0x04,0x02,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0x00,0x02,0x04,0x06,0x08,0x0a,0x0c,0x24,

0x22,0x21,0x20,0x1f,0x1e,0x1d,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,
};  

/*
* 函数名称: GT911_Send_Cfg
* 功能描述: 更新GT911配置参数
* 传入参数: mode:0,参数不保存到flash
*                1:参数保存到flash
*   返回值: 0,成功;1,失败.
*/
void GT911_Send_Cfg(uint8_t mode)
{
	uint8_t buf[2];
	uint8_t i=0;
	buf[0]=0;
	buf[1]=mode;	//是否写入到GT911 FLASH?  即是否掉电保存
	for(i=0;i<sizeof(GT911_CFG_TBL);i++)buf[0]+=GT911_CFG_TBL[i];//计算校验和
    buf[0]=(~buf[0])+1;
	GT911_WR_Reg(GT_CFGS_REG,(uint8_t*)GT911_CFG_TBL,sizeof(GT911_CFG_TBL));//发送寄存器配置
	GT911_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记
} 


/*
* 函数名称: GT911_WR_Reg
* 功能描述: 向GT911写入一次数据
* 传入参数: reg:起始寄存器地址
*           buf:数据缓缓存区
*           len:写数据长度	
*   返回值: 0,成功;1,失败.
*/
uint8_t GT911_WR_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
{
	uint8_t i;
	uint8_t ret=0;	
	
	CT_IIC_Start();	
 	CT_IIC_Send_Byte(GT_CMD_WR);   	//发送写命令 	 
	CT_IIC_Wait_Ack();
	CT_IIC_Send_Byte(reg>>8);   	//发送高8位地址
	CT_IIC_Wait_Ack(); 	 										  		   
	CT_IIC_Send_Byte(reg&0XFF);   	//发送低8位地址
	CT_IIC_Wait_Ack();  
	for(i=0;i<len;i++)
	{	   
    CT_IIC_Send_Byte(buf[i]);  	//发数据
		ret=CT_IIC_Wait_Ack();
		if(ret)break;  
	}
    CT_IIC_Stop();					//产生一个停止条件	    
	return ret; 
}
 
/*
* 函数名称: GT911_RD_Reg
* 功能描述: 从GT911读出一次数据
* 传入参数: reg:起始寄存器地址
*           buf:数据缓缓存区
*           len:读数据长度	
*   返回值: 无
*/
void GT911_RD_Reg(uint16_t reg,uint8_t *buf,uint8_t len)
{
	uint8_t i; 
 	CT_IIC_Start();	
 	CT_IIC_Send_Byte(GT_CMD_WR);   //发送写命令 	 
	CT_IIC_Wait_Ack();
 	CT_IIC_Send_Byte(reg>>8);   	//发送高8位地址
	CT_IIC_Wait_Ack(); 	 										  		   
 	CT_IIC_Send_Byte(reg&0XFF);   	//发送低8位地址
	CT_IIC_Wait_Ack();  
 	CT_IIC_Start();  	 	   
	CT_IIC_Send_Byte(GT_CMD_RD);   //发送读命令		   
	CT_IIC_Wait_Ack();	   
	for(i=0;i<len;i++)
	{	   
    	buf[i]=CT_IIC_Read_Byte(i==(len-1)?0:1); //发数据	  
	} 
    CT_IIC_Stop();//产生一个停止条件    
} 

/*
* 函数名称: GT911_Init
* 功能描述: 初始化GT911触摸屏
* 传入参数: 无
*   返回值: 0,初始化成功;1,初始化失败
*/
 
uint8_t GT911_Init(void)
{
	
//	uint8_t zancun[190]; /*测试使用*/
//	uint8_t i;
//	uint8_t z;
	
	uint8_t temp[5]; 
	GPIO_InitTypeDef  GPIO_InitStructure;	
	
  RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB, ENABLE);//使能GPIOB,C时钟

  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 ;//PB1设置为上拉输入
  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;//输入模式
  GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//推挽输出
  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;//100MHz
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;//上拉
  GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化
		
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//PC13设置为推挽输出
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//输出模式
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化	

	
	
	CT_IIC_Init();      	//初始化电容屏的I2C总线  
  GT_RST(0);//复位
	DWT_DelayMS(1);
	GT_RST(1);//释放复位	
	DWT_DelayMS(5); 
	

	
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
  GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;
	GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化	
	
	DWT_DelayMS(10);  
	GT911_RD_Reg(GT_PID_REG,temp,4);//读取产品ID
	temp[4]=0;
	printf("CTP ID:%s\r\n",temp);	//打印ID
	if(strcmp((char*)temp,"911")==0)//ID==9147
	{
		temp[0]=0X02;			
		GT911_WR_Reg(GT_CTRL_REG,temp,1);//软复位GT911
		GT911_RD_Reg(GT_CFGS_REG,temp,1);//读取GT_CFGS_REG寄存器
		
		
		/*可用来读取GT911本地0x8047-0x80FE的寄存器参数*/
/*
		GT911_RD_Reg(GT_CFGS_REG,(uint8_t *)zancun,186);		 //读取出配置寄存器值
		for(i=0;i<186;i++)
		{
		    if(i<185){z+=zancun[i];}
			  if(i==185){printf("校验值1:%x\r\n",z);}
				printf("%x,",zancun[i]);                   //打印出配置寄存器值
		}
*/
		
		if(temp[0]<0X62)//默认版本比较低,需要更新flash配置
		{
			printf("Default Ver:%x\r\n",temp[0]);
//			GT911_Send_Cfg(1);//更新并保存配置
		}
		DWT_DelayMS(10);
		temp[0]=0X00;	 
		GT911_WR_Reg(GT_CTRL_REG,temp,1);//结束复位   
		return 0;
	} 
	return 0;
}



/*
* 函数名称: GT911_Scan
* 功能描述: 扫描触摸屏(采用查询方式)
* 传入参数: mode:0,正常扫描.
* 传出参数: 无
*   返回值: 当前触屏状态.0,触屏无触摸;1,触屏有触摸
*/
uint8_t GT911_Scan(uint8_t mode)
{
	uint8_t buf[4]; /*触屏坐标信息存储缓冲区*/
	uint8_t i=0;
	uint8_t res=0;  /*返回触摸状态*/
	uint8_t temp;   
	uint8_t tempsta;  /*保存当前触摸状态*/
 	static uint8_t t=0;//控制查询间隔,从而降低CPU占用率   
	t++;
	
	if((t%10)==0||t<10)//空闲时,每进入10次CTP_Scan函数才检测1次,从而节省CPU使用率
	{
		GT911_RD_Reg(GT_GSTID_REG,&mode,1);	//读取触摸点的状态  
		temp=0;
		GT911_WR_Reg(GT_GSTID_REG,&temp,1);//清标志 			
		if((mode&0XF)&&((mode&0XF)<6)) 
		{
			temp=0XFF<<(mode&0XF);		//将点的个数转换为1的位数,匹配tp_dev.sta定义 
			tempsta=tp_dev.sta;			//保存当前的tp_dev.sta值
			tp_dev.sta=(~temp)|TP_PRES_DOWN|TP_CATH_PRES; 
			tp_dev.x[4]=tp_dev.x[0];	//保存触点0的数据
			tp_dev.y[4]=tp_dev.y[0];
			for(i=0;i<5;i++)
			{
				if(tp_dev.sta&(1<<i))	//触摸有效?
				{
					GT911_RD_Reg(GT911_TPX_TBL[i],buf,4);	//读取XY坐标值  
					tp_dev.y[i]=240-(((uint16_t)buf[1]<<8)+buf[0]);
					tp_dev.x[i]=((uint16_t)buf[3]<<8)+buf[2];
					printf("x[%d]:%d,y[%d]:%d\r\n",i,tp_dev.x[i],i,tp_dev.y[i]);
				}			
			 } 
			res=1;
			if(tp_dev.x[0]>LCD_W||tp_dev.y[0]>LCD_H)//非法数据(坐标超出了)
			{ 
				if((mode&0XF)>1)		//有其他点有数据,则复第二个触点的数据到第一个触点.
				{
					tp_dev.x[0]=tp_dev.x[1];
					tp_dev.y[0]=tp_dev.y[1];
					t=0;				//触发一次,则会最少连续监测10次,从而提高命中率
				}
				else					//非法数据,则忽略此次数据(还原原来的)  
				{
					tp_dev.x[0]=tp_dev.x[4];
					tp_dev.y[0]=tp_dev.y[4];
					mode=0X80;		
					tp_dev.sta=tempsta;	//恢复tp_dev.sta
				}
			 }
			 else t=0;					//触发一次,则会最少连续监测10次,从而提高命中率
		}
	}
	if((mode&0X8F)==0X80)//无触摸点按下
	{ 
		if(tp_dev.sta&TP_PRES_DOWN)	//之前是被按下的
		{
			tp_dev.sta&=~(1<<7);	//标记按键松开
		}
		tp_dev.x[0]=0xffff;
		tp_dev.y[0]=0xffff;
		tp_dev.sta&=0XE0;	//清除点有效标记	
	} 	
	if(t>240)t=10;//重新从10开始计数
	return res;
}
 









 //5个触控点的颜色(电容触摸屏用)												 
const uint16_t POINT_COLOR_TBL[5]={RED,GREEN,BLUE,BROWN,GRED};  

//触摸屏测试程序
void ctp_test(void)
{
	uint8_t i=0;	    
 	uint16_t lastpos[5][2];		//存储每个触摸点的最后一次位置信息
	while(1)
	{
		GT911_Scan(0);
		for(i=0;i<5;i++)    /*遍历五个触摸点*/
		{
			if((tp_dev.sta)&(1<<i))
			{
				if(tp_dev.x[i]<LCD_W&&tp_dev.y[i]<LCD_H)
				{
					if(lastpos[i][0]==0XFFFF)
					{
						lastpos[i][0] = tp_dev.x[i];
						lastpos[i][1] = tp_dev.y[i];
					}
					LCD_DrawLine(lastpos[i][0],lastpos[i][1],tp_dev.x[i],tp_dev.y[i],POINT_COLOR_TBL[i]);//画线
					lastpos[i][0]=tp_dev.x[i];
					lastpos[i][1]=tp_dev.y[i];
					if(tp_dev.x[i]>(LCD_W-24)&&tp_dev.y[i]<20)
					{
						LCD_Fill(0,0,LCD_W,LCD_H,WHITE);//整屏填充白色,清除画的图
					}
				}
			}else lastpos[i][0]=0XFFFF;
		}
		
		DWT_DelayMS(5);
	}	
}
  • 14
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: STM32F407是一款基于ARM Cortex-M4内核的微控制器,而FreeRTOS是一种常用的开源实时操作系统。Tracealyzer是一款用于可视化系统的实时调试和性能分析工具。STM32F407_FreeRTOS_Tracealyzer是指将Tracealyzer工具应用于STM32F407微控制器上运行的FreeRTOS操作系统的调试和性能分析。 使用STM32F407_FreeRTOS_Tracealyzer可以方便地跟踪系统中的任务、中断、时间以及资源使用情况。该工具通过可视化的方式展示系统中各个任务的执行顺序、任务的延迟时间、等待时间以及任务之间的通信与同步关系。通过观察Tracealyzer的结果,可以更好地理解系统的调度策略和任务间的相互影响。 此外,STM32F407_FreeRTOS_Tracealyzer还能够帮助分析系统中的事件和中断响应情况。它可以以图表或时间轴的形式展示系统中各个中断的触发时间和持续时间,从而帮助开发者更好地优化中断处理流程。 除了任务和中断分析外,STM32F407_FreeRTOS_Tracealyzer还提供了内存使用情况、资源使用情况和CPU利用率等性能分析功能。开发者可以通过Tracealyzer工具查看系统中各个任务的内存占用和栈使用情况,进而优化系统的资源分配。通过分析CPU利用率,开发者还可以找出存在的性能瓶颈,并进行相应的优化措施。 综上所述,STM32F407_FreeRTOS_Tracealyzer是一款强大的系统调试和性能分析工具,可用于STM32F407微控制器上运行的FreeRTOS操作系统。它通过可视化界面提供了对任务、中断、时间、资源使用以及CPU利用率等方面的分析,帮助开发者更好地了解和优化系统的运行情况。 ### 回答2: STM32F407是一款由STMicroelectronics开发的高性能32位微控制器,而FreeRTOS是一种流行的开源实时操作系统。Tracealyzer是一种用于调试和性能分析的工具,可以用于在嵌入式应用程序中跟踪任务、中断和事件的执行顺序和时间。 STM32F407与FreeRTOS的结合可以提供强大的实时任务管理和调度功能,通过使用RTOS内核和多任务特性,可以有效地管理多个任务并提供实时响应。任务可以根据其优先级和时间要求来进行调度,从而可以轻松实现复杂的并行处理和多任务应用。 Tracealyzer为开发人员提供了一个详细的视图,以实时监视和分析系统中的任务、中断和事件。工具可以生成时间线图,显示任务的活动周期,识别任务之间的依赖关系和延迟,并通过图形界面提供高级分析功能。这对于调试和优化嵌入式应用程序非常有帮助,特别是在处理实时和多任务问题时。 通过使用STM32F407、FreeRTOS和Tracealyzer,开发人员可以更轻松地开发复杂的实时应用程序。STM32F407的高性能和丰富的硬件资源与FreeRTOS的实时任务管理和调度功能相结合,为应用程序提供了灵活性和可靠性。Tracealyzer工具的使用可以帮助开发人员更好地理解系统的运行情况,并进行调试和性能优化。这种组合为嵌入式应用程序开发带来了更高的效率和质量。 ### 回答3: stm32f407是一款基于ARM的微控制器,而FreeRTOS是一个流行的开源实时操作系统。Tracealyzer是一款用于可视化系统行为、调度器行为和中断分析的软件工具。 stm32f407_freertos_tracealyzer是指将Tracealyzer应用于stm32f407和FreeRTOS的组合。通过使用Tracealyzer,我们可以以图形化的方式分析和调试stm32f407微控制器上基于FreeRTOS的应用程序。 stm32f407的主要任务是将系统中的各个任务按照优先级进行调度,并管理系统资源的分配和释放。而FreeRTOS为stm32f407提供了实时任务调度、信号量、队列、事件和内存管理等功能,以便更方便地编写和管理多任务应用程序。 Tracealyzer 利用实时跟踪技术,能够捕获系统中各个任务的执行情况、任务之间的通信以及中断的发生情况。它将这些数据以直观的方式显示出来,帮助开发人员更好地理解系统的运行状况以及发现潜在的问题。 通过stm32f407_freertos_tracealyzer,我们可以实时监测系统中任务的执行情况,包括任务的创建、运行和挂起等状态。我们还可以查看任务之间的通信,例如通过队列和信号量进行的数据交换。此外,我们还可以收集和分析中断的发生情况,以便更好地优化系统性能。 总之,stm32f407_freertos_tracealyzer是一种强大的工具,可以帮助开发人员深入了解基于stm32f407的FreeRTOS应用程序的运行状况,发现潜在的问题,从而提高系统的可靠性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值