文章目錄
- 前言
- 一、資源介紹
- 二、配置程序
- 三、分析程序
- 四、解決方法
- 五、總結
前言
隨著物聯網、智能家居、智能控制等行業的極速發展,小而美的且反應迅速且成本低的,模塊化,定制化的嵌入式系統的需求越來越大,其中降低使用要求,提高用戶體驗,人機互動是一個非常好的方法,所以本文記錄的是除錯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));
在進行編譯下載現象則變成正常

五、總結
- 遇到問題不要灰心,不要放棄,白嫖黨是沒有競爭力的,成為有競爭力的人是你能去解決問題
- 多看官方的檔案等資料,了解操作的原理
-理解軟體包的每個提供的功能性,根據自己使用的功能分析可能存在問題的操作,在跟蹤流程,查看原始碼邏輯是否存在問題,每一步的操作是否正確
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/236116.html
標籤:其他
