STM32F103驱动GT911

STM32F103驱动GT9110x00引脚连接://SCL——-PB10//SDA——-PB11//INT——–PB1//RST——–PB2IIC的SCL与SDA需要接上拉电阻!0x01模拟IIC:在模拟IIC的头文件中:定义所需的IO操作宏://IO操作函数#defineIIC_SCLPBout(10)//…

大家好,又见面了,我是你们的朋友全栈君。

0x00 引脚连接:

// SCL——-PB10
// SDA——-PB11
// INT——–PB1
// RST——–PB2

IIC的SCL与SDA需要接上拉电阻!

0x01 模拟IIC:

在模拟IIC的头文件中:

定义所需的IO操作宏:

//IO操作函数    
#define IIC_SCL    PBout(10) //SCL
#define IIC_SDA    PBout(11) //SDA    
#define READ_SDA   PBin(11)  //输入SDA

宏定义模拟IIC的引脚:

#define    GT911_PIN_SCL    GPIO_Pin_10
#define    GT911_PIN_SDA    GPIO_Pin_11

在模拟IIC的C源文件中实现相关函数:

void SDA_IN(void)
{

     GPIO_InitTypeDef GPIO_InitStructure;
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    
     GPIO_InitStructure.GPIO_Pin = GT911_PIN_SDA;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING ;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOB, &GPIO_InitStructure);       
}

void SDA_OUT(void)
{

     GPIO_InitTypeDef GPIO_InitStructure;
     RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOB, ENABLE);
    
     GPIO_InitStructure.GPIO_Pin = GT911_PIN_SDA;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
}

//初始化IIC
void IIC_Init(void)
{                        
     GPIO_InitTypeDef GPIO_InitStructure;
     RCC_APB2PeriphClockCmd(    RCC_APB2Periph_GPIOB, ENABLE );   
       
     GPIO_InitStructure.GPIO_Pin = GT911_PIN_SCL|GT911_PIN_SDA;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ; 
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
     GPIO_SetBits(GPIOB,GT911_PIN_SCL|GT911_PIN_SDA);
}
//产生IIC起始信号
void IIC_Start(void)
{

     SDA_OUT();   
     IIC_SDA=1;           
     IIC_SCL=1;
     delay_us(4);
      IIC_SDA=0;//START:when CLK is high,DATA change form high to low
     delay_us(4);
     IIC_SCL=0;//钳住I2C总线,准备发送或接收数据
}     
//产生IIC停止信号
void IIC_Stop(void)
{

     SDA_OUT();
     IIC_SCL=0;
     IIC_SDA=0;//STOP:when CLK is high DATA change form low to high
      delay_us(4);
     IIC_SCL=1;
     IIC_SDA=1;//发送I2C总线结束信号
     delay_us(4);                                  
}
//等待应答信号到来
//返回值:1,接收应答失败
//        0,接收应答成功
u8 IIC_Wait_Ack(void)
{

     u8 ucErrTime=0;
     SDA_IN();      //SDA设置为输入 
     IIC_SDA=1;delay_us(1);      
     IIC_SCL=1;delay_us(1);    
     while(READ_SDA)
     {

         ucErrTime++;
         if(ucErrTime>250)
         {

             IIC_Stop();
             return 1;
         }
     }
     IIC_SCL=0;//时钟输出0       
     return 0; 
}
//产生ACK应答
void IIC_Ack(void)
{

     IIC_SCL=0;
     SDA_OUT();
     IIC_SDA=0;
     delay_us(2);
     IIC_SCL=1;
     delay_us(2);
     IIC_SCL=0;
}
//不产生ACK应答           
void IIC_NAck(void)
{

     IIC_SCL=0;
     SDA_OUT();
     IIC_SDA=1;
     delay_us(2);
     IIC_SCL=1;
     delay_us(2);
     IIC_SCL=0;
}                                         
//IIC发送一个字节
//返回从机有无应答
//1,有应答
//0,无应答             
void IIC_Send_Byte(u8 txd)
{                       
     u8 t;  
     SDA_OUT();        
     IIC_SCL=0;//拉低时钟开始数据传输
     for(t=0;t<8;t++)
     {             
         //IIC_SDA=(txd&0x80)>>7;
         if((txd&0x80)>>7)
             IIC_SDA=1;
         else
             IIC_SDA=0;
         txd<<=1;      
         delay_us(2);   //对TEA5767这三个延时都是必须的
         IIC_SCL=1;
         delay_us(2);
         IIC_SCL=0;   
         delay_us(2);
     }    
}        
//读1个字节,ack=1时,发送ACK,ack=0,发送nACK  
u8 IIC_Read_Byte(unsigned char ack)
{

     unsigned char i,receive=0;
     SDA_IN();//SDA设置为输入
     for(i=0;i<8;i++ )
     {

         IIC_SCL=0;
         delay_us(2);
         IIC_SCL=1;
         receive<<=1;
         if(READ_SDA)receive++;  
         delay_us(1);
     }                    
     if (!ack)
         IIC_NAck();//发送nACK
     else
         IIC_Ack(); //发送ACK  
     return receive;
}

0x02 初始化GT911:

查阅《GT911编程指南》:

GT911上电时序

IIC通信地址选择 0x28/0x29,在头文件中加入相关声明和定义:

//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    GT911_PIN_INT    GPIO_Pin_1
#define    GT911_PIN_RST    GPIO_Pin_2

typedef struct _POINT{

     u16 x;
     u16 y;
}POINT, *PPOINT;

typedef struct _GT911_POINT_DATA{

     u8 cnt;
     POINT points[5];
}GT911_POINT_DATA, *PGT911_POINT_DATA;

extern GT911_POINT_DATA     gt911_data;

在C源文件中添加GT911初始化所需要的准备函数:

void GT911_INT_Init(void)
{

     GPIO_InitTypeDef GPIO_InitStructure;
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
     GPIO_InitStructure.GPIO_Pin = GT911_PIN_INT;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
     GPIO_ResetBits(GPIOB, GT911_PIN_INT);
}

void GT911_INT(u8 cmd)
{

     if(cmd)    GPIO_SetBits(GPIOB, GT911_PIN_INT);
     else    GPIO_ResetBits(GPIOB, GT911_PIN_INT);
}

void GT911_INT_Change(void)
{

     GPIO_InitTypeDef GPIO_InitStructure;
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
     GPIO_InitStructure.GPIO_Pin = GT911_PIN_INT;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
     GPIO_ResetBits(GPIOB, GT911_PIN_INT);   
}

void GT911_RST_Init(void)
{

     GPIO_InitTypeDef GPIO_InitStructure;
     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
     GPIO_InitStructure.GPIO_Pin = GT911_PIN_RST;
     GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
     GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
     GPIO_Init(GPIOB, &GPIO_InitStructure);
     GPIO_ResetBits(GPIOB, GT911_PIN_RST);
}

void GT911_RST(u8 cmd)
{

     if(cmd)    GPIO_SetBits(GPIOB, GT911_PIN_RST);
     else    GPIO_ResetBits(GPIOB, GT911_PIN_RST);
}

按照时序GT911上电初始化大致流程如下(IIC通信地址选择 0x28/0x29):

GT911_RST_Init();
GT911_INT_Init();
IIC_Init();

GT911_RST(0);
GT911_INT(1);
delay_us(200);
GT911_RST(1);
delay_ms(6);
GT911_INT(0);
delay_ms(55);
GT911_INT_Change();
delay_ms(50);

在C源文件中添加读写GT911寄存器以及修改配置的相关函数:

//reg:起始寄存器地址
//buf:数据缓缓存区
//len:写数据长度
//返回值:0,成功;1,失败.
u8 GT911_WR_Reg(u16 reg,u8 *buf,u8 len)
{

     u8 i;
     u8 ret=0;
     IIC_Start();   
      IIC_Send_Byte(GT_CMD_WR);       //发送写命令     
     IIC_Wait_Ack();
     IIC_Send_Byte(reg>>8);       //发送高8位地址
     IIC_Wait_Ack();                                                          
     IIC_Send_Byte(reg&0XFF);       //发送低8位地址
     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;
}

//reg:起始寄存器地址
//buf:数据缓缓存区
//len:读数据长度             
void GT911_RD_Reg(u16 reg,u8 *buf,u8 len)
{

     u8 i;
      IIC_Start();   
      IIC_Send_Byte(GT_CMD_WR);   //发送写命令     
     IIC_Wait_Ack();
      IIC_Send_Byte(reg>>8);       //发送高8位地址
     IIC_Wait_Ack();                                                          
      IIC_Send_Byte(reg&0XFF);       //发送低8位地址
     IIC_Wait_Ack(); 
      IIC_Start();             
     IIC_Send_Byte(GT_CMD_RD);   //发送读命令          
     IIC_Wait_Ack();      
     for(i=0;i<len;i++)
     {      
         buf[i]=IIC_Read_Byte(i==(len-1)?0:1); //发数据     
     }
     IIC_Stop();//产生一个停止条件   
}

//发送配置参数
//mode:0,参数不保存到flash
//     1,参数保存到flash
u8 GT911_Send_Cfg(u8 mode)
{

     u8 buf[2];
     u8 i=0;
     buf[0]=0;
     buf[1]=mode;    //是否写入到GT911 FLASH?  即是否掉电保存
     for(i=0;i<sizeof(GT911_Cfg);i++)buf[0]+=GT911_Cfg[i];//计算校验和
     buf[0]=(~buf[0])+1;
     GT911_WR_Reg(GT_CFGS_REG,(u8*)GT911_Cfg,sizeof(GT911_Cfg));//发送寄存器配置
     GT911_WR_Reg(GT_CHECK_REG,buf,2);//写入校验和,和配置更新标记
     return 0;
}

其中GT911_Cfg为寄存器配置数据,一般由厂商直接提供

完整的GT911初始化代码如下:

void GT911_Init(void)
{   
     GT911_RST_Init();
     GT911_INT_Init();
     IIC_Init();
    
     GT911_RST(0);
     GT911_INT(1);
     delay_us(200);
     GT911_RST(1);
     delay_ms(6);
     GT911_INT(0);
     delay_ms(55);
     GT911_INT_Change();
     delay_ms(50);
    
     u8 tmp[4]={0};
     //读取PID
     GT911_RD_Reg(GT_PID_REG, tmp, 4);
    
     //修改配置
     tmp[0] = 0x02;
     GT911_WR_Reg(GT_CTRL_REG, tmp, 1);
     GT911_RD_Reg(GT_CFGS_REG, tmp, 1);
     if(tmp[0] < 0x60){

         printf(“Default Ver:0x%X\r\n”,tmp[0]);
         GT911_Send_Cfg(1);
     }
     delay_ms(10);
     tmp[0] = 0x00;
     GT911_WR_Reg(GT_CTRL_REG, tmp, 1);
    
     EXTIX_Init();
}

0x03 中断接收GT911坐标数据:

GT911所连引脚外部中断初始化(PB1):

void EXTIX_Init(void)
{

      EXTI_InitTypeDef EXTI_InitStructure;
      NVIC_InitTypeDef NVIC_InitStructure;

      RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE);

      GPIO_EXTILineConfig(GPIO_PortSourceGPIOB,GPIO_PinSource1);

      EXTI_InitStructure.EXTI_Line=EXTI_Line1;   
       EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;   
       EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
       EXTI_InitStructure.EXTI_LineCmd = ENABLE;
       EXTI_Init(&EXTI_InitStructure);    

    NVIC_InitStructure.NVIC_IRQChannel = EXTI1_IRQn;           
       NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x02;
       NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;           
       NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;                   
       NVIC_Init(&NVIC_InitStructure);
}

中断服务函数:

查阅《GT911编程指南》:

GT911坐标数据读取

void EXTI1_IRQHandler(void)
{

     u8 tmp;
     GT911_RD_Reg(0x8140, data, 0x40);
     tmp = data[0x0E];
     if((tmp&0x80) && ((tmp&0x0f)>0)){

         GetPointData(tmp&0x0f, data);
         ShowPointData();
     }
     tmp = 0;
     GT911_WR_Reg(0x814E, &tmp, 1);
    
     delay_ms(10);
     EXTI_ClearITPendingBit(EXTI_Line1);
}

data为全局数据(0x8140-0x8180一共0x40个数据),直接一次性读出所有的数据

其中获取和打印坐标的相关函数:

在GT911的头文件中:extern GT911_POINT_DATA     gt911_data;

void GetPointData(u8 cnt, u8 data[])
{

     gt911_data.cnt = 0;
     switch(cnt){

         case 5:
             gt911_data.points[4].x = data[0x31]<<8 | data[0x30];
             gt911_data.points[4].y = data[0x33]<<8 | data[0x32];       
         case 4:
             gt911_data.points[3].x = data[0x29]<<8 | data[0x28];
             gt911_data.points[3].y = data[0x2B]<<8 | data[0x2A];       
         case 3:
             gt911_data.points[2].x = data[0x21]<<8 | data[0x20];
             gt911_data.points[2].y = data[0x23]<<8 | data[0x22];
         case 2:
             gt911_data.points[1].x = data[0x19]<<8 | data[0x18];
             gt911_data.points[1].y = data[0x1B]<<8 | data[0x1A];
         case 1:
             gt911_data.points[0].x = data[0x11]<<8 | data[0x10];
             gt911_data.points[0].y = data[0x13]<<8 | data[0x12];           
             break;
         default:
             break;
     }

    gt911_data.cnt = cnt;
}

void ShowPointData(void)
{

     u8 cnt = gt911_data.cnt;
     for(u8 i=0; i<cnt; i++){

         printf(“Point%d(%d,%d)\t”, i+1, gt911_data.points[i].x, gt911_data.points[i].y);
     }
     printf(“\r\n”);
     memset(&gt911_data, 0, sizeof(gt911_data));
}

0x04 验证结果:

烧录程序至MCU,接线、上电,打开串口调试助手查看打印信息(最多同时五点触摸):

串口打印坐标

转载于:https://www.cnblogs.com/DarkBright/p/10730346.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/147622.html原文链接:https://javaforall.net

(0)
上一篇 2022年6月30日 上午6:00
下一篇 2022年6月30日 上午6:00


相关推荐

  • Android – match_parent 和 fill_parent差异

    Android – match_parent 和 fill_parent差异

    2022年1月2日
    59
  • JMeter入门教程详解

    JMeter入门教程详解简介本文由 xmeter 君写给想了解性能测试和 JMeter 的小白 适合对这两者了解很少的同学们 如果已经有使用经验的请绕道 别浪费时间 我们将介绍 JMeter 的使用场景 如何安装 运行 JMeter 以及开始一个最最简单的测试 你还徘徊在 JMeter 的门口吗 别犹豫了 跟着本文做完 你就可以开启你的 JMeter 之旅了 JMeter 是开源软件 Apache 基金会下的一个性能测试工具 用来测试部署在服务器端的应用程序的性能 近来 JMeter 因为其使用简单 现在也被社区作为接口测试工具 啥 什么是性能测

    2026年3月20日
    2
  • [安全攻防进阶篇] 一.什么是逆向分析、逆向分析应用及经典扫雷游戏逆向

    [安全攻防进阶篇] 一.什么是逆向分析、逆向分析应用及经典扫雷游戏逆向安全攻防进阶篇将更加深入的去研究恶意样本分析、逆向分析、内网渗透、网络攻防实战等。第一篇文章先带领大家学习什么是逆向分析,然后详细讲解逆向分析的典型应用,接着通过OllyDbg工具逆向分析经典的游戏扫雷,再通过CheatEngine工具复制内存地址获取,实现一个自动扫雷程序。基础性文章,西电UI您有所帮助~

    2022年6月19日
    34
  • spark与hadoop的关联和区别,以及spark为什么那么快

    spark与hadoop的关联和区别,以及spark为什么那么快spark与hadoop的关联和区别,以及spark为什么那么快

    2022年4月23日
    58
  • c语言三目运算符例子_单目运算符与双目运算符

    c语言三目运算符例子_单目运算符与双目运算符1.运算方向从左往右,从右往左结合,只有一个表达式被计算百度百科:三目运算符,又称条件运算符,是计算机语言(c,c++,java等)的重要组成部分。它是唯一有3个操作数的运算符,所以有时又称为三元运算符。一般来说,三目运算符的结合性是右结合的。对于条件表达式b?x:y,先计算条件b,然后进行判断。如果b的值为true,计算x的值,运算结果为x的值;否则,计算y的值,运算结果为y的值…

    2026年4月17日
    4
  • 大端模式和小端模式详解

    大端模式和小端模式详解怎么去理解大端和小端 大端模式和小端是实际的字节顺序和存储的地址顺序对应关系的两种模式 总结如下 大端模式 低地址对应高字节小端模式 低地址对应低字节不管是大端还是小端模式 我们在读取和存储数据的时候一定都是从内存的低地址依次向高地址读取或写入 打个比方 我们定义一个数组 chararray 5 0 1 2 3 4 学习过 C 语言应该都知道 array 是这个数组存

    2026年3月18日
    2

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号