分享电容触摸屏FT6236驱动程序

2019-07-21 04:14发布

来论坛索取了很多资料,一直没分享过,今天分享一个测试好了的程序。借鉴了原子哥的FT5206和论坛其他大虾的程序,分享给有需要的人吧。
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
20条回答
wangrlo
2019-07-22 07:01
本帖最后由 wangrlo 于 2016-5-7 14:33 编辑

初始化时SDA是低电平应答信号,但为什么初始化后INT是低电平?多谢。附件是工程,下面是其中的FT6236.c:
//#include "delay.h"
#include "FT6236.h"

//#include "vmlog.h"
#include <string.h>
#include "vmtype.h"
#include "vmsystem.h"
#include "vmcmd.h"
#include "vmlog.h"
#include "vmboard.h"

#include "vmdcl.h"
#include "vmdcl_eint.h"

#include "vmdcl_gpio.h"
#include "stdio.h"


//VM_DCL_HANDLE gpio_handle;  // device handle
VM_DCL_HANDLE lcd_reset_handle;
VM_DCL_HANDLE lcd_cs_handle;
VM_DCL_HANDLE lcd_dc_handle;
VM_DCL_HANDLE lcd_wr_handle;
VM_DCL_HANDLE lcd_sda_handle;
static VM_DCL_HANDLE g_eint_handle = VM_DCL_HANDLE_INVALID;
VMCHAR g_buff[256];


#define RST_L vm_dcl_control(lcd_reset_handle, VM_DCL_GPIO_COMMAND_WRITE_LOW, NULL)
#define RST_H vm_dcl_control(lcd_reset_handle, VM_DCL_GPIO_COMMAND_WRITE_HIGH, NULL)
#define DC_Low vm_dcl_control(lcd_dc_handle, VM_DCL_GPIO_COMMAND_WRITE_LOW, NULL)
#define DC_High vm_dcl_control(lcd_dc_handle, VM_DCL_GPIO_COMMAND_WRITE_HIGH, NULL)
#define SCLK_Low vm_dcl_control(lcd_wr_handle, VM_DCL_GPIO_COMMAND_WRITE_LOW, NULL)
#define SCLK_High vm_dcl_control(lcd_wr_handle, VM_DCL_GPIO_COMMAND_WRITE_HIGH, NULL)
#define SDIN_Low vm_dcl_control(lcd_sda_handle, VM_DCL_GPIO_COMMAND_WRITE_LOW, NULL)
#define SDIN_High vm_dcl_control(lcd_sda_handle, VM_DCL_GPIO_COMMAND_WRITE_HIGH, NULL)
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
//  Delay Time
//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
void delay_us(VMUINT32 millisecs){
   VMUINT32 timeStop;
   VMUINT32 timeStart;
   VMUINT32 Freq = 0;
   volatile VMUINT32 i;
   ///millisecs = millisecs*1000;

    timeStart = vm_time_ust_get_count();
    sprintf(g_buff,"delay_us = %d", timeStart);log_info(10, g_buff);

    while( Freq  < millisecs)
    {
            //for(i=0;i<5000;i++){}
        timeStop = vm_time_ust_get_count();
        Freq = timeStop - timeStart + 1;
    }
}

void Delay(unsigned char n)
{
unsigned char i,j,k;

        for(k=0;k<n;k++)
        {
                for(i=0;i<131;i++)
                {
                        for(j=0;j<15;j++)
                        {
                                delay_us(203);
                        }
                }
        }
}
vm_dcl_gpio_control_level_status_t FT6236_SDA_Read(){
vm_dcl_gpio_control_level_status_t gpio_input_data;  // parameter for VM_DCL_GPIO_COMMAND_READ.

vm_dcl_control(lcd_sda_handle, VM_DCL_GPIO_COMMAND_READ, (void *)&gpio_input_data);   // We call vm_dcl_control to read gpio55.
return gpio_input_data;
}
vm_dcl_gpio_control_level_status_t FT6236_INT_Read(){
vm_dcl_gpio_control_level_status_t gpio_input_data;  // parameter for VM_DCL_GPIO_COMMAND_READ.

vm_dcl_control(g_eint_handle, VM_DCL_GPIO_COMMAND_READ, (void *)&gpio_input_data);   // We call vm_dcl_control to read gpio55.
return gpio_input_data;
}


/****************************************************
* 函数名称 :
* 功    能 :单片机发送起始信号
* 入口参数 :无
* 返回参数 :无
* 注意事项 :
*****************************************************/
void FT6236_Start(void)                                       
{
        SDA_OUT();                     //sda线输出
        delay_us(3);
        SDIN_High;
        SCLK_High;                //SCL最小高电平脉宽:0.6us
        delay_us(4);                //起始信号的最小建立时间:0.6us
        SDIN_Low;                //SCL高电平期间,SDA的一个下降沿表示起始信号
        delay_us(4);                //起始信号的最小保持时间:0.6us
        SCLK_Low;                //箝住总线,为发送器件地址做准备;
        delay_us(2);                //SCL最小低电平脉宽:1.2us,由RET实现
}

/****************************************************
* 函数名称 :
* 功    能 :单片机发送停止信号
* 入口参数 :无
* 返回参数 :无
* 注意事项 :
*****************************************************/
void FT6236_Stop(void)                                                        
{
        SDA_OUT();                     //sda线输出        
        delay_us(3);        
        SCLK_High;                //SCL最小高电平脉宽:0.6us
        delay_us(4);                //停止信号的最小建立时间:0.6us
        SDIN_Low;
        delay_us(4);
        SDIN_High;                //SCL高电平期间,SDA的一个上升沿表示停止信号
        delay_us(2);                                                
}

/****************************************************
* 函数名称 :
* 功    能 :单片机发送应答信号
* 入口参数 :无
* 返回参数 :无
* 注意事项 :单片机读1B数据后发送一个应答信号
*****************************************************/
void FT6236_McuACK(void)                                                        
{
        SCLK_Low;
        SDA_OUT();                     //sda线输出        
        delay_us(3);
        SDIN_Low;
        delay_us(2);                                                                                                                                       
        SCLK_High;                //SCL最小高电平脉宽:0.6us
        delay_us(2);
        SCLK_Low;                //SCL最小低电平脉宽:1.2us
}

/****************************************************
* 函数名称 :
* 功    能 :单片机发送非应答信号
* 入口参数 :无
* 返回参数 :无
* 注意事项 :单片机读数据停止前发送一个非应答信号
*****************************************************/
void FT6236_McuNACK(void)
{
        SCLK_Low;
        SDA_OUT();                                     //sda线输出        
        delay_us(3);
        SDIN_High;
        delay_us(2);                                                                                                                                       
        SCLK_High;                                //SCL最小高电平脉宽:0.6us
        delay_us(2);
        SCLK_Low;                                //SCL最小低电平脉宽:1.2us
}

/****************************************************
* 函数名称 :
* 功    能 :单片机检查FT6236送来的应答信号
* 入口参数 :无
* 返回参数 :1,接收应答失败
                         0,接收应答成功
* 注意事项 :单片机写1个地址/数据后检查
                         全局变量RevAckF:收到FT6236应答信号的标志位,为0表示收到
*****************************************************/
u8 FT6236_CheckAck(void)                                                        
{
        u8 ucErrTime=0;
        SDA_IN();                                      //SDA设置为输入
        SDIN_High;
        SCLK_High;                                //使SDA上数据有效;SCL最小高电平脉宽:0.6us
        delay_us(3);
        while(FT6236_SDA_Read().level_status)
        {        
                ucErrTime++;
                if(ucErrTime>250)                //无应答
                {
                        FT6236_Stop();        
                        return 1;
                }
                delay_us(2);
        }
        SCLK_Low;
        return 0;
}

/****************************************************
* 函数名称 :
* 功    能 :单片机向IIC总线发送1B的地址/数据
* 入口参数 :待发送的1B地址/数据
* 返回参数 :无
* 注意事项 :不是一个完整的数据发送过程;送数的顺序是从高到低
*****************************************************/
void FT6236_WrOneByte(u8 dat)                                                
{
        u8 i;                                                
        SDA_OUT();                                     //sda线输出        
        SCLK_Low;                                //拉低时钟开始数据传输
        delay_us(3);
        for(i = 8; i > 0; i--)                //8位1B地址/数据的长度
        {
                if(dat & 0x80)                 
                        SDIN_High;                //发送"1"
                else
                        SDIN_Low;                //发送"0"
                delay_us(2);
                SCLK_High;                        //使SDA上的数据有效
                delay_us(2);                        //SCL最小高电平脉宽:0.6us                                                        
                SCLK_Low;                        //SCL最小低电平脉宽:1.2us
                delay_us(2);
                dat <<= 1;                                //发送数据左移1位,为下位发送准备        
        }               
}

/****************************************************
* 函数名称 :
* 功    能 :单片机从IIC总线接收1B的数据
* 入口参数 :无
* 返回参数 :收到的1B数据
* 注意事项 :不是一个完整的数据接收过程;从高到低的顺序接收数据
*****************************************************/
u8 FT6236_RdOneByte(void)                                                
{
        u8 i,dat = 0;                                //接收数据位数和内容暂存单元
        SDA_IN();                                                //SDA设置为输入
        delay_us(2);        
        //SDIN_High;                        //使能上拉,准备读取数据
        vm_dcl_control(lcd_sda_handle, VM_DCL_GPIO_COMMAND_ENABLE_PULL, NULL);
        vm_dcl_control(lcd_sda_handle, VM_DCL_GPIO_COMMAND_SET_PULL_HIGH, NULL);

        delay_us(2);
        for(i = 8;i > 0;i--)
        {
                SCLK_Low;
                delay_us(2);
                SCLK_High;
                dat <<= 1;
                if(FT6236_SDA_Read().level_status)
                        dat++;
                delay_us(2);                        //SCL最小低电平脉宽:1.2us
        }
        SDIN_High;
        return(dat);                                //返回1B的数据
}

//向FT6236写入一次数据
//reg:起始寄存器地址
//buf:数据缓缓存区
//len:写数据长度
//返回值:0,成功;1,失败.
u8 FT6236_WR_Reg(u16 reg,u8 *buf,u8 len)
{
        u8 i;
        u8 ret=0;
        FT6236_Start();         
        FT6236_WrOneByte(FT_CMD_WR);        //发送写命令         
        //FT6236_CheckAck();
        ret=FT6236_CheckAck();
    sprintf(g_buff,"FT_CMD_WR = %d", ret);log_info(3, g_buff);

        FT6236_WrOneByte(reg&0XFF);           //发送低8位地址
        FT6236_CheckAck();  
        for(i=0;i<len;i++)
        {           
            FT6236_WrOneByte(buf);          //发数据
                ret=FT6236_CheckAck();
                if(ret)break;  
        }
    FT6236_Stop();                                        //产生一个停止条件
    sprintf(g_buff,"buf = %d", ret);log_info(11, g_buff);

        return ret;
}
//从FT6236读出一次数据
//reg:起始寄存器地址
//buf:数据缓缓存区
//len:读数据长度                          
void FT6236_RD_Reg(u16 reg,u8 *buf,u8 len)
{
        u8 i;
         FT6236_Start();        
         FT6236_WrOneByte(FT_CMD_WR);           //发送写命令         
        FT6236_CheckAck();                                                                                                               
         FT6236_WrOneByte(reg&0XFF);           //发送低8位地址
        FT6236_CheckAck();  
         FT6236_Start();                     
        FT6236_WrOneByte(FT_CMD_RD);           //发送读命令                  
        FT6236_CheckAck();         
        for(i=0;i<len;i++)
        {           
                *buf++ = FT6236_RdOneByte();                //读入1B数据到接收数据缓冲区中
                FT6236_McuACK();                                        //发送应答位         
        }
        FT6236_McuNACK();                                                //n个字节读完,发送非应答位
    FT6236_Stop();                                        //产生一个停止条件         
}
/*
**函数名:FT6236_Init
**传入参数:无
**返回值:无
**功能:初始化FT6236引脚
*/  
void FT6236_Init(void)
{
    sprintf(g_buff,"FT6236_Init = %d", 5);log_info(3, g_buff);

        lcd_reset_handle = vm_dcl_open(VM_DCL_GPIO, 33);          // First, we call vm_dcl_open to get a handle. 55 means gpio55
        //lcd_dc_handle = vm_dcl_open(VM_DCL_GPIO, 47);          // First, we call vm_dcl_open to get a handle. 55 means gpio55
        lcd_wr_handle = vm_dcl_open(VM_DCL_GPIO, 35);          // First, we call vm_dcl_open to get a handle. 55 means gpio55
        lcd_sda_handle = vm_dcl_open(VM_DCL_GPIO, 36);          // First, we call vm_dcl_open to get a handle. 55 means gpio55
        vm_dcl_control(lcd_sda_handle, VM_DCL_GPIO_COMMAND_ENABLE_PULL, NULL);
        vm_dcl_control(lcd_wr_handle, VM_DCL_GPIO_COMMAND_ENABLE_PULL, NULL);
        vm_dcl_control(lcd_sda_handle, VM_DCL_GPIO_COMMAND_SET_PULL_HIGH, NULL);
        vm_dcl_control(lcd_wr_handle, VM_DCL_GPIO_COMMAND_SET_PULL_HIGH, NULL);
    /* Sets the pin direction to OUTPUT */
    vm_dcl_control(lcd_reset_handle, VM_DCL_GPIO_COMMAND_SET_DIRECTION_OUT, NULL);
    /* Sets the pin direction to OUTPUT */
    vm_dcl_control(lcd_wr_handle, VM_DCL_GPIO_COMMAND_SET_DIRECTION_OUT, NULL);
    SDA_OUT();
        u8 temp;
        SDIN_High;
        SCLK_High;
        RST_H;

        RST_L;
        delay_ms(50);
        RST_H;
        delay_ms(100);
        SDIN_High;
        SCLK_High;
        delay_ms(10);
        temp=0;
        FT6236_WR_Reg(FT_DEVIDE_MODE,&temp,1);        //进入正常操作模式


         temp=22;                                                                //触摸有效值,22,越小越灵敏        
         FT6236_WR_Reg(FT_ID_G_THGROUP,&temp,1);        //设置触摸有效值
         temp=12;                                                                //激活周期,不能小于12,最大14
         FT6236_WR_Reg(FT_ID_G_PERIODACTIVE,&temp,1);
    sprintf(g_buff,"INT = %d", FT6236_INT_Read().level_status);log_info(10, g_buff);

/******************************************************/
}
const u16 FT6236_TPX_TBL[5]=
{
        FT_TP1_REG,
        FT_TP2_REG,
        FT_TP3_REG,
        FT_TP4_REG,
        FT_TP5_REG
};
TouchPointRefTypeDef TPR_Structure;
void FT6236_Scan(void)
{
        u8 i=0;
        u8 sta = 0;
        u8 buf[4] = {0};   
        FT6236_RD_Reg(0x02,&sta,1);//读取触摸点的状态            
         if(sta & 0x0f)        //判断是否有触摸点按下,0x02寄存器的低4位表示有效触点个数
         {
                 TPR_Structure.TouchSta = ~(0xFF << (sta & 0x0F));        //~(0xFF << (sta & 0x0F))将点的个数转换为触摸点按下有效标志
                 for(i=0;i<5;i++)                                        //分别判断触摸点1-5是否被按下
                 {
                         if(TPR_Structure.TouchSta & (1<<i))                            //读取触摸点坐标
                         {                                                                                            //被按下则读取对应触摸点坐标数据
                                 FT6236_RD_Reg(FT6236_TPX_TBL,buf,4);        //读取XY坐标值
                                TPR_Structure.x=((u16)(buf[0]&0X0F)<<8)+buf[1];
                                TPR_Structure.y=((u16)(buf[2]&0X0F)<<8)+buf[3];
                                 if((buf[0]&0XC0)!=0X80)
                                 {
                                        TPR_Structure.x=TPR_Structure.y=0;//必须是contact事件,才认为有效        
                                        return;
                                }
                         }
                 }
                 TPR_Structure.TouchSta |= TP_PRES_DOWN;     //触摸按下标记
         }
         else
         {
                 if(TPR_Structure.TouchSta &TP_PRES_DOWN)         //之前是被按下的
                         TPR_Structure.TouchSta &= ~0x80;        //触摸松开标记        
                 else
                 {
                         TPR_Structure.x[0] = 0;
                         TPR_Structure.y[0] = 0;
                         TPR_Structure.TouchSta &=0xe0;        //清楚触摸点有效标记
                 }
         }
}

/* EINT callback, to be invoked when EINT triggers. */
static void eint_callback(void* parameter, VM_DCL_EVENT event, VM_DCL_HANDLE device_handle)
{
        TPR_Structure.TouchSta |= TP_COORD_UD;                                //触摸坐标有更新

        if(TPR_Structure.TouchSta &TP_COORD_UD)                //触摸有按下
        {
                TPR_Structure.TouchSta &= ~TP_COORD_UD;        //清标记
                FT6236_Scan();                                                        //读取触摸坐标
                sprintf(g_buff,"X: %d",TPR_Structure.x[0]);
            log_info(2, g_buff);    /* output log to LCD if have */
                sprintf(g_buff,"Y: %d",TPR_Structure.y[0]);
            log_info(4, g_buff);    /* output log to LCD if have */

                //printf(" ");//插入换行
        }
}

/* Attaches EINT */
//static void eint_attach(void)
void eint_attach(void)
{
    vm_dcl_eint_control_config_t eint_config;
    vm_dcl_eint_control_sensitivity_t sens_data;
    vm_dcl_eint_control_hw_debounce_t deboun_time;
    VM_DCL_STATUS status;

    /* Resets the data structures */
    memset(&eint_config,0, sizeof(vm_dcl_eint_control_config_t));
    memset(&sens_data,0, sizeof(vm_dcl_eint_control_sensitivity_t));
    memset(&deboun_time,0, sizeof(vm_dcl_eint_control_hw_debounce_t));

    /* Opens and attaches VM_PIN_EINT EINT */
    g_eint_handle = vm_dcl_open(VM_DCL_EINT, PIN2EINT(VM_PIN_EINT));

    if(VM_DCL_HANDLE_INVALID == g_eint_handle)
    {
        sprintf(g_buff,"open EINT error");log_info(3, g_buff);
        return;
    }

    /* Usually, before configuring the EINT, we mask it firstly. */
    status = vm_dcl_control(g_eint_handle, VM_DCL_EINT_COMMAND_MASK, NULL);
    if(status != VM_DCL_STATUS_OK)
    {
      sprintf(g_buff,"VM_DCL_EINT_COMMAND_MASK  = %d", status);log_info(3, g_buff);
    }

    /* Registers the EINT callback */
    status = vm_dcl_register_callback(g_eint_handle, VM_DCL_EINT_EVENT_TRIGGER, (vm_dcl_callback)eint_callback, (void*)NULL );
    if(status != VM_DCL_STATUS_OK)
    {
        sprintf(g_buff,"VM_DCL_EINT_EVENT_TRIGGER = %d", status);log_info(3, g_buff);
    }

    /* Configures a FALLING edge to trigger */
    sens_data.sensitivity = 0;
    eint_config.act_polarity = 0;

    /* Sets the auto unmask for the EINT */
    eint_config.auto_unmask = 1;

    /* Sets the EINT sensitivity */
    status = vm_dcl_control(g_eint_handle, VM_DCL_EINT_COMMAND_SET_SENSITIVITY, (void*)&sens_data);
    if(status != VM_DCL_STATUS_OK)
    {
      sprintf(g_buff,"VM_DCL_EINT_COMMAND_SET_SENSITIVITY = %d", status);log_info(3, g_buff);
    }

    /* Sets debounce time to 1ms */
    deboun_time.debounce_time = 1;
    /* Sets debounce time */
    status = vm_dcl_control(g_eint_handle, VM_DCL_EINT_COMMAND_SET_HW_DEBOUNCE, (void*)&deboun_time);
    if(status != VM_DCL_STATUS_OK)
    {
      sprintf(g_buff,"VM_DCL_EINT_COMMAND_SET_HW_DEBOUNCE = %d", status);log_info(3, g_buff);
    }

    /* Usually, before configuring the EINT, we mask it firstly. */
    status = vm_dcl_control(g_eint_handle, VM_DCL_EINT_COMMAND_MASK, NULL);
    if(status != VM_DCL_STATUS_OK)
    {
       sprintf(g_buff,"VM_DCL_EINT_COMMAND_MASK  = %d", status);log_info(3, g_buff);
    }

    /* 1 means enabling the HW debounce; 0 means disabling. */
    eint_config.debounce_enable = 1;

    /* Make sure to call this API at the end as the EINT will be unmasked in this statement. */
    status = vm_dcl_control(g_eint_handle, VM_DCL_EINT_COMMAND_CONFIG, (void*)&eint_config);
    if(status != VM_DCL_STATUS_OK)
    {
      sprintf(g_buff,"VM_DCL_EINT_COMMAND_CONFIG = %d", status);log_info(3, g_buff);
    }
}

void test(){
        log_info(6,"test");
}








补充内容 (2016-5-17 15:00):
thx

一周热门 更多>