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编程指南》:

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编程指南》:

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,接线、上电,打开串口调试助手查看打印信息(最多同时五点触摸):

STM32F103驱动GT911的更多相关文章

  1. STM32F103驱动ADS1118

    ADS1118 作为常用温度测量芯片被越来越多的开发者熟知,TI官方给出的是基于 MSP430 的驱动测试程序,由于 STM32 的普及,闲暇中移植了 MSP430 的 ADS1118 驱动程序到 S ...

  2. 全志A33驱动GT911触摸屏

    0x00 环境说明: 所使用的开发板为锐尔威视的插针版A33_Vstar 触摸屏驱动IC为GT911 接线参照开发板的TP线路 0x01 修改系统配置文件: 笔者所使用的A33开发板的系统配置文件路径 ...

  3. 电赛总结(四)——波形发生芯片总结之AD9834

    一.特性参数 1.2.3V~5.5V供电 2.输出频率高达37.5MHz 3.正弦波.三角波输出 4.提供相位调制和频率调制功能 5.除非另有说明,VDD = 2.3 V至5.5 V,AGND = D ...

  4. FLASH 存储学习-串行SPI NOR FLASH

    1.1 SST25VF080B简介1.1.1 主要特性 关键点:容量.速度(时钟速度.读写速度).功耗. l 容量:8MBit: l 最高SPI时钟频率:50MHz: l 低功耗模式下电流消耗:5uA ...

  5. FLASH 存储学习-串行SPI nor

    1.1 SST25VF080B简介 1.1.1 主要特性 关键点:容量.速度(时钟速度.读写速度).功耗. 容量:8MBit: 最高SPI时钟频率:50MHz: 低功耗模式下电流消耗:5uA,正常读模 ...

  6. STM32-串行SPI nor

    源:FLASH 存储学习-串行SPI nor 1.1 SST25VF080B简介1.1.1 主要特性 关键点:容量.速度(时钟速度.读写速度).功耗. l 容量:8MBit: l 最高SPI时钟频率: ...

  7. 从FPGA搞定OV7670 VGA显示 移植到 STM32F10x TFT显示 总结及疑问(高手请进)

    OV7670不愧是最便宜的摄像头了最大显示像素:640*480(在VGA显示器上显示效果还不赖,用usb模块采集显示依然显著) 第一步:VGA显示 视频图像(实时)FPGA+SDRAM+OV7670= ...

  8. STM32F103 USB虚拟串口 驱动例程移植

    1)驱动下载及安装.目前ST公司支持WIN7版本号为:VCP_V1.3.1_Setup.exe (在官网上搜索stsw-stm32102即是了):先安装驱动后再插入USB不然安装不成功. 2)固件下载 ...

  9. 如何为编程爱好者设计一款好玩的智能硬件(八)——LCD1602点阵字符型液晶显示模块驱动封装(中)

    六.温湿度传感器DHT11驱动封装(下):如何为编程爱好者设计一款好玩的智能硬件(六)——初尝试·把温湿度给收集了(下)! 七.点阵字符型液晶显示模块LCD1602驱动封装(上):如何为编程爱好者设计 ...

随机推荐

  1. 遍历文件路径python版,java版

    python: # 获取所有txt路径列表 file_list = [] def gci(filepath): files=os.listdir(filepath) for fi in files: ...

  2. UOJ#110. 【APIO2015】Bali Sculptures 贪心 动态规划

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ110.html 题解 我们发现n=2000 的子任务保证A=1! 分两种情况讨论: $n\leq 100$ ...

  3. js隐藏元素、jquery隐藏、css隐藏

    $("#yh").css("display","none");//隐藏元素 $("#yh").css("dis ...

  4. 阿里云服务器端配置TensorFlow & jupyter

    在阿里云上搭建爬取某信的公众号文章的程序时,发现需要验证码验证,技穷之后考虑做一个验证码识别程序,所以开始在服务器上搭建机器学习平台,背景,服务器上已经有其他应用在跑着了,所以不想停服,初始环境:ce ...

  5. mobile_音悦台

    音悦台 less 可以 width = 1080/67.5rem; /**** 变量定义 ****/ @px: 67.5rem; /**** Start ****/ #wrap { width: 10 ...

  6. prometheus + grafana + node_exporter + alertmanager 的安装部署与邮件报警 (一)

    大家一定要先看详细的理论教程,再开始搭建,这样报错后才容易找到突破口 参考文档 https://www.cnblogs.com/afterdawn/p/9020129.html https://www ...

  7. [LeetCode] Split BST 分割二叉搜索树

    Given a Binary Search Tree (BST) with root node root, and a target value V, split the tree into two ...

  8. apache启动不了应对方法

    原因一:80端口占用 例如IIS,另外就是迅雷.我的apache服务器就是被迅雷害得无法启用! 原因二:软件冲突 装了某些软件会使apache无法启动如Dr.com 你打开网络连接->TcpIp ...

  9. 添加spring-boot-devtools热部署报错

    使用的eclipse部署的spring boot,百度了下,大部分的问题都是说IDE工具使用热部署无法成功的解决方案,看了很懵逼 <!-- 热部署模块 --> <dependency ...

  10. 在U8菜单中增加自定义项

    --.NET实现的脚本 If Exists (Select 1 From UFSystem..UA_Menu where cMenu_id = 'SAM06') delete from UFSyste ...