文章目录
- 前言
- 一、资源介绍
- 二、配置过程
- 三、分析过程
- 四、解决方法
- 五、总结
前言
随着物联网、智能家居、智能控制等行业的极速发展,小而美的且反应迅速且成本低的,模块化,定制化的嵌入式系统的需求越来越大,其中降低使用要求,提高用户体验,人机交互是一个非常好的方法,所以本文记录的是调试rtthread+触摸芯片GT9147芯片的记录及流程
一、资源介绍
硬件资源如下
- MCU:STM3H750XB
- 开发板:rt-thread官方的开发板art-pi
- LCD:4.3寸800*480 RGB LCD
- 触摸驱动芯片:GT9147
- 使用LTDC接口驱动LCD(本文未操作)
- 使用IIC接口驱动触摸芯片GT9147
软件是使用rtthread studio2.0.0版本
使用软件包:gt9147
二、配置过程
- 添加gt9147软件包
- 打开art-pi开发板中连接gt9147芯片的IIC接口
- 根据软件包初始化示例注册驱动
#include "gt9147.h"
#define GT9147_RST_PIN 51
#define GT9147_IRQ_PIN 108
int rt_hw_gt9147_port(void)
{
struct rt_touch_config config;
rt_uint8_t rst;
rst = GT9147_RST_PIN;
config.dev_name = "i2c1";
config.irq_pin.pin = GT9147_IRQ_PIN;
config.irq_pin.mode = PIN_MODE_INPUT_PULLDOWN;
config.user_data = &rst;
rt_hw_gt9147_init("gt", &config);
return 0;
}
INIT_ENV_EXPORT(rt_hw_gt9147_port);
- 打开软件包的示例文件,使用文件中的代码
#include <rtthread.h>
#include "gt9147.h"
#define THREAD_PRIORITY 25
#define THREAD_STACK_SIZE 1024
#define THREAD_TIMESLICE 5
static rt_thread_t gt9147_thread = RT_NULL;
static rt_sem_t gt9147_sem = RT_NULL;
static rt_device_t dev = RT_NULL;
static struct rt_touch_data *read_data;
static struct rt_touch_info info;
static void gt9147_entry(void *parameter)
{
rt_device_control(dev, RT_TOUCH_CTRL_GET_INFO, &info);
read_data = (struct rt_touch_data *)rt_malloc(sizeof(struct rt_touch_data) * info.point_num);
while (1)
{
rt_sem_take(gt9147_sem, RT_WAITING_FOREVER);
if (rt_device_read(dev, 0, read_data, info.point_num) == info.point_num)
{
for (rt_uint8_t i = 0; i < info.point_num; i++)
{
if (read_data[i].event == RT_TOUCH_EVENT_DOWN || read_data[i].event == RT_TOUCH_EVENT_MOVE)
{
rt_kprintf("%d %d %d %d %d\n", read_data[i].track_id,
read_data[i].x_coordinate,
read_data[i].y_coordinate,
read_data[i].timestamp,
read_data[i].width);
}
}
}
rt_device_control(dev, RT_TOUCH_CTRL_ENABLE_INT, RT_NULL);
}
}
static rt_err_t rx_callback(rt_device_t dev, rt_size_t size)
{
rt_sem_release(gt9147_sem);
rt_device_control(dev, RT_TOUCH_CTRL_DISABLE_INT, RT_NULL);
return 0;
}
/* Test function */
int gt9147_sample(const char *name, rt_uint16_t x, rt_uint16_t y)
{
void *id;
dev = rt_device_find(name);
if (dev == RT_NULL)
{
rt_kprintf("can't find device:%s\n", name);
return -1;
}
if (rt_device_open(dev, RT_DEVICE_FLAG_INT_RX) != RT_EOK)
{
rt_kprintf("open device failed!");
return -1;
}
id = rt_malloc(sizeof(rt_uint8_t) * 8);
rt_device_control(dev, RT_TOUCH_CTRL_GET_ID, id);
rt_uint8_t * read_id = (rt_uint8_t *)id;
rt_kprintf("id = %d %d %d %d \n", read_id[0] - '0', read_id[1] - '0', read_id[2] - '0', read_id[3] - '0');
rt_device_control(dev, RT_TOUCH_CTRL_SET_X_RANGE, &x); /* if possible you can set your x y coordinate*/
rt_device_control(dev, RT_TOUCH_CTRL_SET_Y_RANGE, &y);
rt_device_control(dev, RT_TOUCH_CTRL_GET_INFO, id);
rt_kprintf("range_x = %d \n", (*(struct rt_touch_info*)id).range_x);
rt_kprintf("range_y = %d \n", (*(struct rt_touch_info*)id).range_y);
rt_kprintf("point_num = %d \n", (*(struct rt_touch_info*)id).point_num);
rt_free(id);
rt_device_set_rx_indicate(dev, rx_callback);
gt9147_sem = rt_sem_create("dsem", 0, RT_IPC_FLAG_FIFO);
if (gt9147_sem == RT_NULL)
{
rt_kprintf("create dynamic semaphore failed.\n");
return -1;
}
gt9147_thread = rt_thread_create("thread1",
gt9147_entry,
RT_NULL,
THREAD_STACK_SIZE,
THREAD_PRIORITY,
THREAD_TIMESLICE);
if (gt9147_thread != RT_NULL)
rt_thread_startup(gt9147_thread);
return 0;
}
- 加入以下代码自动启动触摸示例线程
int touch_init(void)
{
gt9147_sample("gt", 800, 480);
return RT_EOK;
}
INIT_APP_EXPORT(touch_init);
下载运行
遇到问题以上问题,设置的触摸参数是800 * 480,但是初始化的范围是480 * 480,初始化代码没问题,实际触摸检测到的范围也是480 * 480,与设置实际不符。
三、分析过程
- 打开gt9147源码,找到触摸框架的操作函数
static struct rt_touch_ops touch_ops =
{
.touch_readpoint = gt9147_read_point,
.touch_control = gt9147_control,
};
- 出现的问题初始化时都提示参数已经是不正确的,那么问题应该是在gt9147_control函数中,查找初始化调用了一下关于这个函数的操作
rt_device_control(dev, RT_TOUCH_CTRL_GET_ID, id);
rt_device_control(dev, RT_TOUCH_CTRL_SET_X_RANGE, &x);
rt_device_control(dev, RT_TOUCH_CTRL_SET_Y_RANGE, &y);
rt_device_control(dev, RT_TOUCH_CTRL_GET_INFO, id);
上面有两个是读取ID和参数的,两个是设置X,Y参数的,读取只是读操作,一般不会是读的问题,所以有可能是设置不成功或者出错,打开源码中的gt9147_control函数中设置X,Y的操作。
以下为设置XY的关键代码,其他代码未贴出
/* hardware section */
static const rt_uint8_t GT9147_CFG_TBL[] =
{
0X00, 0XE0, 0X01, 0X10, 0X01, 0X05, 0X3C, 0X00, 0X02, 0X08,
0X1E, 0X08, 0X50, 0X3C, 0X0F, 0X05, 0X00, 0X00, 0XFF, 0X67,
0X50, 0X00, 0X00, 0X18, 0X1A, 0X1E, 0X14, 0X89, 0X28, 0X0A,
0X30, 0X2E, 0XBB, 0X0A, 0X03, 0X00, 0X00, 0X02, 0X33, 0X1D,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X32, 0X00, 0X00,
0X2A, 0X1C, 0X5A, 0X94, 0XC5, 0X02, 0X07, 0X00, 0X00, 0X00,
0XB5, 0X1F, 0X00, 0X90, 0X28, 0X00, 0X77, 0X32, 0X00, 0X62,
0X3F, 0X00, 0X52, 0X50, 0X00, 0X52, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X0F,
0X0F, 0X03, 0X06, 0X10, 0X42, 0XF8, 0X0F, 0X14, 0X00, 0X00,
0X00, 0X00, 0X1A, 0X18, 0X16, 0X14, 0X12, 0X10, 0X0E, 0X0C,
0X0A, 0X08, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X29, 0X28, 0X24, 0X22, 0X20, 0X1F, 0X1E, 0X1D,
0X0E, 0X0C, 0X0A, 0X08, 0X06, 0X05, 0X04, 0X02, 0X00, 0XFF,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF,
0XFF, 0XFF, 0XFF, 0XFF,
};
static rt_err_t gt9147_control(struct rt_touch_device *device, int cmd, void *data)
{
rt_uint8_t buf[4];
rt_uint8_t i = 0;
rt_uint8_t *config;
config = (rt_uint8_t *)rt_calloc(1, sizeof(GT9147_CFG_TBL) + GTP_ADDR_LENGTH);
if (config == RT_NULL)
{
LOG_D("malloc config memory failed\n");
return -RT_ERROR;
}
config[0] = (rt_uint8_t)((GT9147_CONFIG >> 8) & 0xFF); /* config reg */
config[1] = (rt_uint8_t)(GT9147_CONFIG & 0xFF);
memcpy(&config[2], GT9147_CFG_TBL, sizeof(GT9147_CFG_TBL)); /* config table */
switch(cmd)
{
case RT_TOUCH_CTRL_SET_X_RANGE: /* set x range */
{
rt_uint16_t x_ran;
x_ran = *(rt_uint16_t *)data;
config[4] = (rt_uint8_t)(x_ran >> 8);
config[3] = (rt_uint8_t)(x_ran & 0xff);
break;
}
case RT_TOUCH_CTRL_SET_Y_RANGE: /* set y range */
{
rt_uint16_t y_ran;
y_ran = *(rt_uint16_t *)data;
config[6] = (rt_uint8_t)(y_ran >> 8);
config[5] = (rt_uint8_t)(y_ran & 0xff);
break;
}
}
if (gt9147_write_reg(gt9147_client, sizeof(GT9147_CFG_TBL) + GTP_ADDR_LENGTH, config) != RT_EOK) /* send config */
{
LOG_D("send config failed\n");
return -RT_ERROR;
}
buf[0] = (rt_uint8_t)((GT9147_CHECK_SUM >> 8) & 0xFF);
buf[1] = (rt_uint8_t)(GT9147_CHECK_SUM & 0xFF);
buf[2] = 0;
for(i = GTP_ADDR_LENGTH; i < sizeof(GT9147_CFG_TBL) + GTP_ADDR_LENGTH; i++)
buf[GTP_ADDR_LENGTH] += config[i];
buf[2] = (~buf[2]) + 1;
buf[3] = 1;
gt9147_write_reg(gt9147_client, 4, buf);
rt_free(config);
return RT_EOK;
}
- 查找操作的内容和变量,以及对应的关系
可以找到设置X轴范围是操作数组 config[3] 和 config[4]
可以找到设置X轴范围是操作数组 config[5] 和 config[6]
其他参数都未变,其实就是使用了配置表GT9147_CFG_TBL的
GT9147_CFG_TBL[1]
GT9147_CFG_TBL[2]
GT9147_CFG_TBL[3]
GT9147_CFG_TBL[4]
进行设置X Y的范围。
从配置代码看,默认配置表的X为0x01E0,也就是10进制的480,Y为0x0110,也就是10进制的272。
再回看设置过程先设置流程,每次进行设置操作都会从配置表进行以下代码操作memcpy(&config[2], GT9147_CFG_TBL, sizeof(GT9147_CFG_TBL)); /* config table */
拷贝参数再进行X转换写入
那么问题就找到了
第一步设置X为800时,拷贝默认的配置表参数是X:480、Y:272,经参数设置之后变成X:800、Y:272
第二步设置Y为480时,拷贝默认的配置表参数是X:480、Y:272,经参数设置之后变成X:480、Y:480
四、解决方法
- 直接修改配置表的参数为自己参数,进行设置的时候不进行转换(个人不推荐,兼容性和扩展性不好)
- 将每次修改后的变量保存下来,将配置表设置成非常量数据类型
static rt_uint8_t GT9147_CFG_TBL[] =
{
0X00, 0XE0, 0X01, 0X10, 0X01, 0X05, 0X3C, 0X00, 0X02, 0X08,
0X1E, 0X08, 0X50, 0X3C, 0X0F, 0X05, 0X00, 0X00, 0XFF, 0X67,
0X50, 0X00, 0X00, 0X18, 0X1A, 0X1E, 0X14, 0X89, 0X28, 0X0A,
0X30, 0X2E, 0XBB, 0X0A, 0X03, 0X00, 0X00, 0X02, 0X33, 0X1D,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X32, 0X00, 0X00,
0X2A, 0X1C, 0X5A, 0X94, 0XC5, 0X02, 0X07, 0X00, 0X00, 0X00,
0XB5, 0X1F, 0X00, 0X90, 0X28, 0X00, 0X77, 0X32, 0X00, 0X62,
0X3F, 0X00, 0X52, 0X50, 0X00, 0X52, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X0F,
0X0F, 0X03, 0X06, 0X10, 0X42, 0XF8, 0X0F, 0X14, 0X00, 0X00,
0X00, 0X00, 0X1A, 0X18, 0X16, 0X14, 0X12, 0X10, 0X0E, 0X0C,
0X0A, 0X08, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0X00, 0X29, 0X28, 0X24, 0X22, 0X20, 0X1F, 0X1E, 0X1D,
0X0E, 0X0C, 0X0A, 0X08, 0X06, 0X05, 0X04, 0X02, 0X00, 0XFF,
0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00,
0X00, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF, 0XFF,
0XFF, 0XFF, 0XFF, 0XFF,
};
将修改后的参数更新到配置表中,在**gt9147_control**最后加入以下代码更新
memcpy(GT9147_CFG_TBL, &config[2], sizeof(GT9147_CFG_TBL));
在进行编译下载现象则变成正常
五、总结
- 遇到问题不要灰心,不要放弃,白嫖党是没有竞争力的,成为有竞争力的人是你能去解决问题
- 多看官方的文档等资料,了解操作的原理
-理解软件包的每个提供的功能性,根据自己使用的功能分析可能存在问题的操作,在跟踪流程,查看源码逻辑是否存在问题,每一步的操作是否正确