STM32----GT9157触摸IC驱动

发布者:pcwg最新更新时间:2019-06-29 来源: eefocus关键字:STM32  GT9157  触摸IC驱动 手机看文章 扫描二维码
随时随地手机看文章

一、硬件环境


        野火F429第一代开发板,5寸触摸屏,触摸IC为GT9157,支持5点触控(但IC是支持10点触控的)



二、GT9157初始化


总的流程:1、初始化GPIO --> 2、初始化I2C --> 3、复位GT9157以确定IC从地址 --> 4、写配置寄存器(0x8047~0x8100)


(1)初始化GPIO与I2C


         这个不详述,I2C可用模拟,也可用硬件I2C。STM32F4的硬件I2C稳定性还行,最重要的是,需要设置I2C等待时间


         与等待次数,超时跳出等待防止卡死。野火的I2C读取移植自GT9157的Linux驱动,使用一个i2c_msg结构体控制读写


static int I2C_Transfer( struct i2c_msg *msgs,int num)

{

int im = 0;

int ret = 0;

 

GTP_DEBUG_FUNC();

 

for (im = 0; ret == 0 && im != num; im++)

{

if ((msgs[im].flags&I2C_M_RD)) //根据flag判断是读数据还是写数据

{

ret = I2C_ReadBytes(msgs[im].addr, msgs[im].buf, msgs[im].len); //IIC读取数据

} else

{

ret = I2C_WriteBytes(msgs[im].addr,  msgs[im].buf, msgs[im].len); //IIC写入数据

}

}

 

if(ret)

return ret;

 

return im;    //正常完成的传输结构个数

}

以下是使用这个I2C传输函数的实例应用,先发送地址,后接收数据,总共2个传输过程故 i2c_msg 结构体数组个数为2


/**

  * @brief   从IIC设备中读取数据

  * @param

  * @arg client_addr:设备地址

  * @arg  buf[0~1]: 读取数据寄存器的起始地址

  * @arg buf[2~len-1]: 存储读出来数据的缓冲buffer

  * @arg len:    GTP_ADDR_LENGTH + read bytes count(寄存器地址长度+读取的数据字节数)

  * @retval  i2c_msgs传输结构体的个数,2为成功,其它为失败

  */

static int32_t GTP_I2C_Read(uint8_t client_addr, uint8_t *buf, int32_t len)

{

    struct i2c_msg msgs[2];

    int32_t ret=-1;

    int32_t retries = 0;

 

    GTP_DEBUG_FUNC();

    /*一个读数据的过程可以分为两个传输过程:

     * 1. IIC  写入 要读取的寄存器地址

     * 2. IIC  读取  数据

     * */

 

    msgs[0].flags = !I2C_M_RD; //标志位取反,在I2C_Transfer中会启用发送功能

    msgs[0].addr  = client_addr; //IIC设备地址,GT9157可设为:0xBAXBB或者0x28x29

    msgs[0].len   = GTP_ADDR_LENGTH;         //寄存器地址为2字节(即写入两字节的数据)

    msgs[0].buf   = &buf[0]; //buf[0~1]存储的是要读取的寄存器地址

    

    msgs[1].flags = I2C_M_RD; //读取

    msgs[1].addr  = client_addr; //IIC设备地址

    msgs[1].len   = len - GTP_ADDR_LENGTH; //要读取的数据长度

    msgs[1].buf   = &buf[GTP_ADDR_LENGTH]; //buf[GTP_ADDR_LENGTH]之后的缓冲区存储读出的数据

 

    while(retries < 5)

    {

        ret = I2C_Transfer( msgs, 2); //调用IIC数据传输过程函数,有2个传输过程,返回成功读写次数,0代表读写失败

        if(ret == 2)break;

        retries++;

    }

    if((retries >= 5))

    {

        GTP_ERROR("I2C Read: 0x%04X, %d bytes failed, errcode: %d! Process reset.", (((uint16_t)(buf[0] << 8)) | buf[1]), len-2, ret);

    }

    return ret;

}

 


(2)复位GT9157


控制RESER跟INT引脚就行,不多说,注意引脚电平状态持续时间就可以


(3)写配置寄存器


         把野火的程序稍微改动了以下,更好理解,实际使用的时候建议使用野火的I2C驱动


u8 test[200];

 

 int32_t GTP_Init_Panel(void)

{

    int32_t ret = -1;

 

    int32_t i = 0;

    uint8_t check_sum = 0;  //用于缓存配置元素的和,用于计算校验的补码

    uint8_t cfg_info[] = CTP_CFG_GROUP1;

    uint8_t cfg_info_len =CFG_GROUP_LEN(cfg_info) ;  //配置数组元素的个数

 

    uint8_t cfg_num =0x80FE-0x8047+1 ; //需要配置的寄存器个数

 

    GTP_DEBUG_FUNC();

 

 

    I2C_Touch_Init();  //初始化GPIO与I2C,复位GT9157

 

    //ret = GTP_I2C_Test();

    /****** 1、测试I2C读写功能,读取0x8047这个地址的数据,如果读取成功则I2C通讯正常 *******/

    test[0] = GTP_REG_CONFIG_DATA>>8;   //读写的地址为0x8047

    test[1] = GTP_REG_CONFIG_DATA&0xff;

   for(i=0; i<5; i++)

   {

ret = -1;

ret += I2C_WriteBytes(GTP_ADDRESS,  test, 2); //1、写入读取的寄存器(0x8047)的地址,成功返回0

ret += I2C_ReadBytes(GTP_ADDRESS,test+2, 1); //2、将寄存器(0x8047)的数据读出,成功返回0

if(ret == -1) break; //如果读写成功则返回

   }

 

    if (ret != -1)

    {

        GTP_ERROR("I2C communication ERROR!");

    }

  

    //GTP_Read_Version(); 

    /************************** 2、读取Product ID与Firmware version ************************/

   test[0] = GTP_REG_VERSION>>8;   //读写的地址为0x8047

   test[1] = GTP_REG_VERSION&0xff;

   ret += I2C_WriteBytes(GTP_ADDRESS,  test, 2); //1、写入读取的寄存器地址,成功返回0

   ret += I2C_ReadBytes(GTP_ADDRESS,test+2, 6); //2、将寄存器的数据读出,成功返回0

   if (ret != -1)

   {

       GTP_ERROR("GTP read version failed");

   }

   if (test[5] == 0x00) //Product ID有3位与4位的区别,此屏幕ID为9157 4位

   {

      GTP_INFO("IC Version: %c%c%c_%02x%02x", test[2], test[3], test[4], test[7], test[6]);

   }

    else

    {

        GTP_INFO("IC Version: %c%c%c%c_%02x%02x", test[2], test[3], test[4], test[5], test[7], test[6]);

    }

    //将数组config从第GTP_ADDR_LENGTH个元素开始,后面的GTP_CONFIG_MAX_LENGTH个元素变成 0 

    memset(&config[GTP_ADDR_LENGTH], 0, GTP_CONFIG_MAX_LENGTH); 

    //将数组cfg_info的cfg_info_len个元素复制到config数组的第GTP_ADDR_LENGTH以及后面位置

    memcpy(&config[GTP_ADDR_LENGTH], cfg_info, cfg_info_len);

 

    //计算要写入checksum寄存器的值

    check_sum = 0;

    for (i = GTP_ADDR_LENGTH; i < cfg_num+GTP_ADDR_LENGTH; i++)

    {

        check_sum += config[i];

    }

    config[ cfg_num+GTP_ADDR_LENGTH] = (~check_sum) + 1; //checksum

    config[ cfg_num+GTP_ADDR_LENGTH+1] =  1; //refresh 配置更新标志

 

    //写入配置信息

    for (i = 0; i < 5; i++)

    {

        ret = I2C_WriteBytes(GTP_ADDRESS,  config, cfg_num + GTP_ADDR_LENGTH+2); 

        if (ret == 0)

        {

            break;

        }

    }

    Delay(0xfffff); //延迟等待芯片更新

 

    GTP_Get_Info();

 

    return 0;

}

 


三、读取触摸坐标数据


读取的时候直接读0x814e地址,根据需要读取的触摸点的数量控制连续读取字节数。参考编程手册可知数据的意义:


修改了一下获取触摸屏坐标的函数:


/**

  * @brief   触屏处理函数,轮询或者在触摸中断调用

  * @param 无

  * @retval 无

  */

u8 Touch_Point[35];  //5个触摸点35个数据

 

static void Goodix_TS_Work_Func(void)

{

u16 i;

uint8_t  end_cmd[3] = {GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF, 0};

uint8_t  point_data[2 + 1 + 8 * GTP_MAX_TOUCH + 1]={GTP_READ_COOR_ADDR >> 8, GTP_READ_COOR_ADDR & 0xFF};

uint8_t  touch_num = 0;

uint8_t  finger = 0;

 

uint8_t client_addr=GTP_ADDRESS;

int32_t ret = -1;

GTP_DEBUG_FUNC();

ret = GTP_I2C_Read(client_addr, point_data, 2+1+8*GTP_MAX_TOUCH);//10字节寄存器加2字节地址

if (ret < 0)

{

GTP_ERROR("I2C transfer error. errno:%dn ", ret);

return;

}

finger = point_data[GTP_ADDR_LENGTH];//状态寄存器数据

 

GTP_DEBUG("I2C finger:%X",finger);

 

if((finger & 0x80) == 0)//判断buffer status位

{

goto exit_work_func;//坐标未就绪,数据无效

}

 

touch_num = finger & 0x0f;//坐标点数

 

for(i=0;i {

Touch_Point[0+i*7] = point_data[3+i*8];  //ID

Touch_Point[1+i*7] = point_data[4+i*8];  //x

Touch_Point[2+i*7] = point_data[5+i*8];  //x

Touch_Point[3+i*7] = point_data[6+i*8];  //y

Touch_Point[4+i*7] = point_data[7+i*8];  //y

Touch_Point[5+i*7] = point_data[8+i*8];  //xize

Touch_Point[6+i*7] = point_data[9+i*8];  //xize

}

for(i=touch_num*7;i<5*7;i++)  //清除后续触摸点数据

    Touch_Point[i] = 0;

 

 

      exit_work_func:

{

ret = GTP_I2C_Write(client_addr, end_cmd, 3);

if (ret < 0)

{

GTP_INFO("I2C write end_cmd error!");

}

}

}

 


主函数中每隔100MS输出一次坐标参数到自制上位机:


void GT9xx_GetOnePiont(void)

{

GUI_PID_STATE State;

GTP_DEBUG_FUNC();

Goodix_TS_Work_Func();

if((pre_x==-1) || (pre_y==-1))

{

State.x = -1;

State.y = -1;

State.Pressed = 0;

State.Layer = 1;

GUI_PID_StoreState(&State);

return;

}

State.Pressed = 1;

State.x = pre_x;

State.y =pre_y;

State.Layer = 1;

GUI_PID_StoreState(&State);

}

extern u8 Touch_Point[35];  //5个触摸点35个数据

void SendTouch_Point(void)

{

  u8 i;

  for(i=0;i<35;i++)

{

                USART_SendData(DEBUG_USART, Touch_Point[i]);

while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET);

}

 

  for(i=0;i<4;i++)

{

                USART_SendData(DEBUG_USART, 0xff);

while (USART_GetFlagStatus(DEBUG_USART, USART_FLAG_TXE) == RESET);

}

}

 

 

/**

  * @brief  主函数

  * @param  无

  * @retval 无

  */

int main(void)

{

NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);

 

/* 初始化调试串口,一般为串口1 */

Debug_USART_Config();

 

GTP_Init_Panel(); //触摸屏初始化必须优先于系统滴答定时器初始化

SysTick_Init();

 

         while(1)

{

GT9xx_GetOnePiont();

SendTouch_Point();

Delay_MS(100);

}

}

 


 


四、数据获取与显示


       上位机采用VS2015 C#编写,具体代码如下:


using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

using System.IO.Ports;

 

 

 

namespace WindowsFormsApplication1

{

    public partial class TouchApp : Form

    {

        int MAXDATA;  //计算存储对应触摸点需要的字节数

        int Buffoffset = 0, EndFlag = 0, i,temp;

        byte[] Buff = new byte[4096];      //缓存串口数据

        byte[] DisData = new byte[70];      //缓存串口数据

 

        public TouchApp()  //初始化

        {

            InitializeComponent();

[1] [2]
关键字:STM32  GT9157  触摸IC驱动 引用地址:STM32----GT9157触摸IC驱动

上一篇:基于STM32F103的红外遥控小车
下一篇:STM32----LTDC与DMA2D

推荐阅读最新更新时间:2024-11-12 12:16

STM32一键下载电路导致的单片机不能正常运行
使用的正点原子精英版的电路,直接使用那种4线的stlink给单片机供电+下载程序,发现能够正常下载,但死活不运行程序。 一键下载电路如图~ 当时没有使用USB串口功能,所以没有接入5V供电,导致了RTS和DTR引脚悬空,测量电压均为2.69V,即BOOT0被拉高,单片机的启动模式变成了从ISP下载。 插上5V供电一切正常~
[单片机]
<font color='red'>STM32</font>一键下载电路导致的单片机不能正常运行
STM32按键控制灯
/*---------------------------------------------------------------------------------- 文件名称:控制LED2,LED3闪烁 硬件平台:STM32F103 开发板 作者 :求是 固件库 :V3.5 -----------------------------------------------------------------------------------*/ /* Includes ------------------------------------------------------------------*/ #include st
[单片机]
STM32控制蜂鸣器
main.c具体的代码如下 /*---------------------------------------------------------------------------------- 功能描述:普通延时控制LED2闪烁,间隔250ms,定时器控制蜂鸣器和LED3 硬件平台:STM32F103 开发板 作者 :求是07 固件库 :V3.5 -----------------------------------------------------------------------------------*/ /* Includes ------------------------------------------
[单片机]
<font color='red'>STM32</font>控制蜂鸣器
STM32 关于USART接收中断的BUG和注意事项
今天在使用USART模块,遇到了一些问题并解决了,于是发贴共享。 问题描述: 在使用USART做串口通讯时,我只把接收中断打开,并设置抢占优先级为最低一个级别,而接收中断上一个优先级处理事情比较多,可能占用了2ms时间。当我使用9600波特率往下位机发送数据,速度非常快,就是一直按回车发!问题就出来,不到1分钟时间,通讯没有反应了。USART配置代码如下: void uart_config(void) { USART_InitTypeDef USART_InitStructure; USART_InitStructure.USART_BaudRate = UART_GetBaud(BaudRate); USART_In
[单片机]
关于 STM32 SPI 从机模式的问题
网上有很多关于STM32 作为从机来使用 的 问题 主要还是 从机接收数据错误 1 关于主从机的 时钟悬空配置 可以肯定的说 主机与从机的时钟悬空一定要配成一样的 这点STM 的官方手册说的很明白 2 从机的波特率 只与 主机提供的 CLK 信号有关 3 通信失败 或者 数据接收错误 问题就出在从机对SPI 的起始信号的判断上面 当使用TI 模式 NSS 信号由硬件 从机对数据的捕获 就很容易 若没有NSS 信号呢 因为STM32 SPI普通模式 根本就没有对数据的捕获 做什么工作 真的有点糊弄我们 它 只是 当我们把SPI 打开 他就开始进行捕获 而不管SCK 此时是闲置的还是忙的 这就造成
[单片机]
stm32基础之独立看门狗
stm32基本都内置两种看门狗(另外还有外置的看门狗芯片),窗口看门狗和独立看门狗,两种看门狗的使用方法和应用场景各不相同,今天主要讲讲最常用的独立看门狗(工作这么多年,没见谁用过窗口看门狗,这种估计在时序严格的场合会用上)。 所谓独立(Independent watchdog),就是该看门狗有独立的时钟源供看门狗使用,VIP专属。这样即使程序跑飞,或者主时钟挂掉,照样运行。但是精度嘛,你懂的(VIP用户一般比较飘)。 所谓看门狗,外形虽然不像(一堆电子电路,肯定不像),但行为真的狗,还是一条疯狗。为啥这么说呢? 这只狗一定要在规定以内的时间(这个时间自己设置)喂食,超出一点都不行,否则就咬人(复位整个程序,让你的人生重新
[单片机]
<font color='red'>stm32</font>基础之独立看门狗
STM32开发笔记62: 使用MicroLIB
单片机型号:STM32F407VGT6 microLIB 是缺省 C 库的备选库,它旨在与需要装入到极少量内存中的深层嵌入式应用程序配合使用。LwIP中使用了microLIB,如果不勾选microLIB选项,则程序不能够正常运行,其主要原因在于LwIP使用了microLIB提供的标准输入和输出函数。本文对microLIB做详细介绍。 1、microLIB介绍 Microlib is an alternative library to the default C library. It is intended for use with deeply embedded applications that must fit
[单片机]
<font color='red'>STM32</font>开发笔记62: 使用MicroLIB
意法半导体量产STM32 F0系列入门级MCU
意法半导体(ST)5月15日在北京媒体沟通会上宣布,开始量产基于ARM Cortex-M0处理器内核的入门级STM32 F0系列32位MCU。其适于工业控制器、家庭自动化、打印机和白色家电等应用。   STM32 F0的主要特性包括:①工作频率48MHz时,性能为38DMIPS,独立第三方评测机构的CoreMark评分为68;24MHz时,22DMIPS,CoreMark39。11项外设映射在5通道的DMA,结合总线矩阵,使闪存中执行代码与DMA数据传输同步操作。   ②四个低功耗模式包括5.3μA停止模式,实时时钟运行的2.8μA待机模式,电池供电模式下且实时时钟运行时0.4μA。1.8V/2-3.6V电源电压。功耗效率如图
[模拟电子]
意法半导体量产<font color='red'>STM32</font> F0系列入门级MCU
热门资源推荐
热门放大器推荐
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
  • 学习ARM开发(16)
    ARM有很多东西要学习,那么中断,就肯定是需要学习的东西。自从CPU引入中断以来,才真正地进入多任务系统工作,并且大大提高了工作效率。采 ...
  • 学习ARM开发(17)
    因为嵌入式系统里全部要使用中断的,那么我的S3C44B0怎么样中断流程呢?那我就需要了解整个流程了。要深入了解,最好的方法,就是去写程序 ...
  • 学习ARM开发(18)
    上一次已经了解ARM的中断处理过程,并且可以设置中断函数,那么它这样就可以工作了吗?答案是否定的。因为S3C44B0还有好几个寄存器是控制中 ...
  • 嵌入式系统调试仿真工具
    嵌入式硬件系统设计出来后就要进行调试,不管是硬件调试还是软件调试或者程序固化,都需要用到调试仿真工具。 随着处理器新品种、新 ...
  • 最近困扰在心中的一个小疑问终于解惑了~~
    最近在驱动方面一直在概念上不能很好的理解 有时候结合别人写的一点usb的例子能有点感觉,但是因为arm体系里面没有像单片机那样直接讲解引脚 ...
  • 学习ARM开发(1)
  • 学习ARM开发(2)
  • 学习ARM开发(4)
  • 学习ARM开发(6)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved