软件环境:Win7,Keil MDK 4.72a, IAR EWARM 7.2, GCC 4.2,Python 2.7 ,SCons 2.3.2
硬件环境:Armfly STM32F103ZE-EK v3.0开发板
参考文章:RT-Thread编程指南
RT-Thread_1.2.0+lwip+rtgui0.8.0 移植心得
RT-Thread RTOS组件:RTGUI教程 Hello World
前面基本解决了显示驱动问题,接下来将要解决触摸屏的驱动问题。
【1】加入触屏屏的驱动文件
(1)重命名stm32f103ze-ek/drivers目录下touch.c文件,解决重名文件问题
将touch.c从KeilMDK工程中移除,同时将stm32f103ze-ek/drivers目录下的touch.h和touch.c重命名成touch_driver.c和touch_driver.h,然后再将其加入到工程中。
打开touch_driver.c文件,定位到第5行,修改如下:
... ...
#include "board.h"
#include "touch_driver.h"
... ...
(2)修改touch_driver.c文件中的相关硬件接口
上面的原理图中给出了触摸屏SPI接口,触摸屏的片选线PG11,中断线是PC5,Busy线是PB5,所以也要将touch_driver.c中断接口修改过来。定位到17行附近,代码修改如下:
/*
MISO PA6
MOSI PA7
CLK PA5
CS PG11
INT PC5
BUSY PB5
*/
#define CS_0() GPIO_ResetBits(GPIOG,GPIO_Pin_11)
#define CS_1() GPIO_SetBits(GPIOG,GPIO_Pin_11)
定位到80行附近修给触摸屏的分辨率
#define X_WIDTH 240
#define Y_WIDTH 400
然后定位到202行附近,修改如下:
/* touch time is too short and we lost the position already. */
if ((!touched_down) && GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_5) != 0)
return;
if (GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_5) != 0)
{
... ...
定位到209行附近,代码修改如下:
// PC5 --> EXTI9_5
static void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
/* Enable the EXTI9_5 Interrupt */
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
rt_inline void EXTI_Enable(rt_uint32_t enable)
{
EXTI_InitTypeDef EXTI_InitStructure;
/* Configure EXTI */
EXTI_InitStructure.EXTI_Line = EXTI_Line5;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;//FallingϽµÑØ RisingÉÏÉý
... ...
EXTI_Init(&EXTI_InitStructure);
EXTI_ClearITPendingBit(EXTI_Line5);
}
static void EXTI_Configuration(void)
{
/* PC5 touch INT */
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOC,&GPIO_InitStructure);
}
GPIO_EXTILineConfig(GPIO_PortSourceGPIOC, GPIO_PinSource5);
/* Configure EXTI */
EXTI_Enable(1);
}
... ...
定位到351行附近,代码修改如下:
/* RT-Thread Device Interface */
static rt_err_t rtgui_touch_init (rt_device_t dev)
{
NVIC_Configuration();
EXTI_Configuration();
/* PG11 touch CS */
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
GPIO_Init(GPIOG,&GPIO_InitStructure);
CS_1();
}
CS_0();
WriteDataTo7843( 1<<7 ); /*打开中断 */
CS_1();
return RT_EOK;
}
... ...
定位到406行附近,代码修改如下:
/* SPI1 config */
{
#ifndef RT_USING_SPI1
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
... ...
SPI_I2S_DeInit(SPI1);
SPI_Init(SPI1, &SPI_InitStructure);
#endif /* RT_USING_SPI1 */
/* Enable SPI_MASTER */
SPI_Cmd(SPI1, ENABLE);
SPI_CalculateCRC(SPI1, DISABLE);
... ...
} /* SPI1 config */
(3)spi_device_f
修改完成后保存。
【2】修改rt_spi_flash_device.c文件中与SPI1相关部分代码
打开rt_spi_flash_device.c,去掉RT_USING_SPI条件编译,加入RT_USING_SPI1 条件编译。定位到21行附近,代码修改如下:
/*
* SPI1_MOSI: PA7
* SPI1_MISO: PA6
* SPI1_SCK : PA5
*
* SPI Flash CE: PB2
* Touch Panel CS: PG11
*/
static int rt_hw_spi_init(void)
{
#ifdef RT_USING_SPI1
/*SPI1: register spi bus */
{
... ...
stm32_spi_register(SPI1, &stm32_spi, "spi1");
}
#endif /* RT_USING_SPI1 */
/* attach spi flash cs */
#ifdef RT_USING_SPI_FLASH
{
static struct rt_spi_device spi_device;
static struct stm32_spi_cs spi_cs;
... ...
rt_spi_bus_attach_device(&spi_device, "spiflash", "spi1", (void*)&spi_cs);
}
#endif /* RT_USING_SPI_FLASH */
return 0;
... ...
}
INIT_DEVICE_EXPORT(rt_hw_spi_init);
void rt_spi_flash_device_init(void)
{
#if defined(RT_USING_DFS) && defined(RT_USING_DFS_ELMFAT)
w25qxx_init("flash0", "spiflash");
#endif /* RT_USING_DFS && RT_USING_DFS_ELMFAT */
}
修改完成后保存。
(4)在rtconfig.h文件中加入RT_USING_SPI1定义,打开rtconfig.h,定位到93行附近,加入下面代码:
/* SECTION: device filesystem */
#define RT_USING_SPI
#define RT_USING_SPI1
#define RT_USING_SPI_FLASH
#define RT_USING_DFS
... ...
修改完成后保存。然后重新scons编译,出现错误:Undefined Symbol "rtgui_touch_hw_init",reference to appliction.o.
解决办法:
打开appliction.c文件,定位到136行附近,修改'RTGUI_USING_TOUCHPANEL 为'RT_USING_TOUCHPANEL,修改如下:
... ...
#ifdef RT_USING_TOUCHPANEL
/* initilize touch panel */
rtgui_touch_hw_init();
#endif /* RT_USING_TOUCHPANEL */
/* find lcd device */
lcd = rt_device_find("lcd");
... ...
修改完成后保存。
打开touch_device.c文件,定位到492行附近,代码修改如下:
//外部中断PC5
#ifdef RT_USING_TOUCHPANEL
void EXTI9_5_IRQHandler(void)
{
/* disable interrupt */
EXTI_Enable(0);
/* start timer */
rt_timer_start(touch->poll_timer);
EXTI_ClearITPendingBit(EXTI_Line5);
}
#endif /* RT_USING_TOUCHPANEL*/
修改完成后保存。
因为'RTGUI_USING_TOUCHPANEL定义在rtgui_config.h中,不在rtconfig.h中,scons 脚本编译时找不到这个符号,然后删除掉rtgui_config.h中的RTGUI_USING_TOUCHPANEL 定义,在rtconfig.h加入RT_USING_TOUCHPANEL定义,代码如下:
/* SECTION: RT-Thread/GUI */
#define RT_USING_RTGUI
#define RT_USING_TOUCHPANEL
/* name length of RTGUI object */
... ...
修改完成后保存。
然后重新scons编译,编译通过,下载到开发板上,结果显示如下:
\ | /
- RT - Thread Operating System
/ | \ 1.2.2 build Apr 14 2015
2006 - 2013 Copyright by rt-thread team
sdcard init failed
dm9000 id: 0x90000a46
finsh />operating at 100M full duplex mode
lwIP-1.4.1 initialized!
set font size to 16
W25Q64BV or W25Q64CV detection
flash0 mount to /.
sd0 mount to /dev failed.
LCD ID 00005420
finsh />list_device()
device type
-------- ----------
touch SPI Device
lcd Graphic Device
flash0 Block Device
spiflash SPI Device
spi1 SPI Bus
e0 Network Interface
uart3 Character Device
uart2 Character Device
uart1 Character Device
0, 0x00000000
finsh />touch up: (0, 0)
touch up: (0, 0)
touch up: (0, 0)
touch up: (0, 0)
可以看到,输入list_device()命令后,看到了touch设备,在LCD上触摸几下,终端有触摸位置输出,因为还没有矫正,所以输出的点不确定。
【3】触摸屏校正
为了加入触摸屏校正文件calibration.c,需要对相关脚本文件作下修改
(1)用Notepad++打开compenonts/rtgui/Sconscript,导入根目录变量,修改如下:
import os
Import('RTT_ROOT')
from building import *
cwd = GetCurrentDir()
objs = []
list = os.listdir(cwd)
... ...
修改完成后保存。
(2)用Notepad++打开compenonts/rtgui/apps/Sconscript,修改编译选项,代码修改如下:
from building import *
import os
cwd = GetCurrentDir()
if GetDepend('RT_USING_CALIBRATION'):
src = Glob('*.c')
group = DefineGroup('RTGUI', src, depend = ['RT_USING_CALIBRATION'])
... ...
(3)在rtconfig.h中加入RT_USING_CALIBRATION定义,修改如下:
/* SECTION: RT-Thread/GUI */
#define RT_USING_RTGUI
#define RT_USING_TOUCHPANEL
#define RT_USING_CALIBRATION
/* name length of RTGUI object */
#define RTGUI_NAME_MAX 12
/* support 16 weight font */
#define RTGUI_USING_FONT16
... ...
修改完成后保存。
(4)打开rtgui_config.h定位到52行附近,打开注释掉的RTGUI_USING_CALIBRATION定义:
//#define RTGUI_USING_DESKTOP_WINDOW
//#undef RTGUI_USING_SMALL_SIZE
//#define RTGUI_USING_TOUCHPANEL
#define RTGUI_USING_CALIBRATION
#define RTGUI_USING_BRG565
#endif
(5)在命令终端中执行scons --target=mdk4 -s,然后打开keilMDK,可以在RTGUI组中看到calibration.c文件。
打开calibration.c,定位到143附近行和177行开始的地方,将屏幕四个角画点的rtgui_dc_draw_text()的第二个参数的字符串改短一点,不然字符显示不全,当然这是可选的,代码修改如下:
<pre name="code" class="cpp">
struct rtgui_widget *widget = RTGUI_WIDGET(object);
rtgui_rect_t label_rect = {2, 100, 230, 300};
switch (event->type)
{
case RTGUI_EVENT_PAINT:
{
struct rtgui_dc *dc;
struct rtgui_rect rect;
dc = rtgui_dc_begin_drawing(widget);
if (dc == RT_NULL) break;
/* get rect information */
rtgui_widget_get_rect(widget, &rect);
/* clear whole window */
RTGUI_WIDGET_BACKGROUND(widget) = white;
rtgui_dc_fill_rect(dc, &rect);
/* reset color */
RTGUI_WIDGET_BACKGROUND(widget) = green;
RTGUI_WIDGET_FOREGROUND(widget) = black;
switch (calibration_ptr->step)
{
case CALIBRATION_STEP_LEFTTOP:
rtgui_dc_draw_hline(dc,
0,
2 * CALIBRATION_WIDTH,
CALIBRATION_HEIGHT);
rtgui_dc_draw_vline(dc,
CALIBRATION_WIDTH,
0,
2 * CALIBRATION_HEIGHT);
rtgui_dc_draw_text(dc,
"Touch the left top!",
&label_rect);
RTGUI_WIDGET_FOREGROUND(widget) = red;
rtgui_dc_fill_circle(dc,
CALIBRATION_WIDTH,
CALIBRATION_HEIGHT,
4);
break;
case CALIBRATION_STEP_RIGHTTOP:
rtgui_dc_draw_hline(dc,
calibration_ptr->width - 2 * CALIBRATION_WIDTH,
calibration_ptr->width,
CALIBRATION_HEIGHT);
rtgui_dc_draw_vline(dc,
calibration_ptr->width - CALIBRATION_WIDTH,
0,
2 * CALIBRATION_HEIGHT);
rtgui_dc_draw_text(dc,
"Touch the right top!",
&label_rect);
RTGUI_WIDGET_FOREGROUND(widget) = red;
rtgui_dc_fill_circle(dc,
calibration_ptr->width - CALIBRATION_WIDTH,
CALIBRATION_HEIGHT,
4);
break;
case CALIBRATION_STEP_LEFTBOTTOM:
rtgui_dc_draw_hline(dc,
0,
2 * CALIBRATION_WIDTH,
calibration_ptr->height - CALIBRATION_HEIGHT);
rtgui_dc_draw_vline(dc,
CALIBRATION_WIDTH,
calibration_ptr->height - 2 * CALIBRATION_HEIGHT,
calibration_ptr->height);
rtgui_dc_draw_text(dc,
"Touch the left bottom!",
&label_rect);
RTGUI_WIDGET_FOREGROUND(widget) = red;
rtgui_dc_fill_circle(dc,
CALIBRATION_WIDTH,
calibration_ptr->height - CALIBRATION_HEIGHT,
4);
break;
case CALIBRATION_STEP_RIGHTBOTTOM:
rtgui_dc_draw_hline(dc,
calibration_ptr->width - 2 * CALIBRATION_WIDTH,
calibration_ptr->width,
calibration_ptr->height - CALIBRATION_HEIGHT);
rtgui_dc_draw_vline(dc,
calibration_ptr->width - CALIBRATION_WIDTH,
calibration_ptr->height - 2 * CALIBRATION_HEIGHT,
calibration_ptr->height);
rtgui_dc_draw_text(dc,
"Touch the right bottom!",
&label_rect);
RTGUI_WIDGET_FOREGROUND(widget) = red;
rtgui_dc_fill_circle(dc,
calibration_ptr->width - CALIBRATION_WIDTH,
calibration_ptr->height - CALIBRATION_HEIGHT,
4);
break;
case CALIBRATION_STEP_CENTER:
rtgui_dc_draw_hline(dc,
calibration_ptr->width / 2 - CALIBRATION_WIDTH,
calibration_ptr->width / 2 + CALIBRATION_WIDTH,
calibration_ptr->height / 2);
rtgui_dc_draw_vline(dc,
calibration_ptr->width / 2,
calibration_ptr->height / 2 - CALIBRATION_HEIGHT,
calibration_ptr->height / 2 + CALIBRATION_HEIGHT);
rtgui_dc_draw_text(dc,
"Touch the center to finish Calibration!",
&label_rect);
RTGUI_WIDGET_FOREGROUND(widget) = red;
rtgui_dc_fill_circle(dc,
calibration_ptr->width / 2,
calibration_ptr->height / 2,
4);
break;
}
然后保存并scons编译,下载,复位后,在终端中输入calibration(),可得到如下显示:
finsh />calibration()
0, 0x00000000
finsh />
但是在按下屏幕上红点进行校正时,下面是终端输出的结果:
finsh />calibration()
0, 0x00000000
finsh />touch up: (481, 3773)
touch up: (3511, 3673)
touch up: (3491, 306)
touch up: (423, 285)
touch up: (1895, 2144)
可能是内存分配问题,demo_appliction.c中的控件演示打开的太多,不能正常显示,此问题留待后面解决。
【4】校正数据存储与加载
一个正常的系统不想每次启动时都要在终端输入命令进行校正,需要在一些代码,在系统启动时自动加载存储数据。
(1)新建文件touch_setup.c,并加入下面代码(参考ModiF1的部分代码修改而来):
#include <rtthread.h>
#include <dfs_posix.h>
#include <rtgui/calibration.h>
#include "stdlib.h"//for atoi
#include <touch_setup.h>
#define cali_file "/cali.ini"
static const char* kn_touch_min_x = "touch_min_x";
static const char* kn_touch_max_x = "touch_max_x";
static const char* kn_touch_min_y = "touch_min_y";
static const char* kn_touch_max_y = "touch_max_y";
static rt_uint32_t read_line(int fd, char* line, rt_uint32_t line_size)
{
char *pos, *next;
rt_uint32_t length;
length = read(fd, line, line_size);
if (length > 0)
{
pos = strstr(line, "\r\n");
if (pos == RT_NULL)
{
pos = strstr(line, "\n");
next = pos ++;
}
else next = pos + 2;
if (pos != RT_NULL)
{
*pos = '\0';
/* move back */
lseek(fd, -(length - (next - line)), SEEK_CUR);
length = pos - line;
}
else length = 0;
}
return length;
}
static void cali_load_default(void)
{
/*
struct calibration_data setup;
rt_kprintf("cali_load_default!\r\n");
//OTM4001 default calibration data
setup.min_x = 0x3aa8;
setup.max_x = 0x792f;
setup.min_y = 0xd7f1;
setup.max_y = 0x573b;
cali_save(&setup);
*/
}
rt_err_t cali_load(struct calibration_data* setup)
{
int fd, length;
char line[64];
rt_kprintf("Load calibration data\n");
fd = open(cali_file, O_RDONLY, 0);
if (fd >= 0)
{
length = read_line(fd, line, sizeof(line));
if (strcmp(line, "[config]") == 0)
{
char* begin;
// touch_min_x
length = read_line(fd, line, sizeof(line));
if (length == 0)
{
close(fd);
cali_load_default();
return RT_EOK;
}
if (strncmp(line, kn_touch_min_x, sizeof(kn_touch_min_x) - 1) == 0)
{
begin = strchr(line, '=');
begin++;
setup->min_x = atoi(begin);
}
// touch_max_x
length = read_line(fd, line, sizeof(line));
if (length == 0)
{
close(fd);
cali_load_default();
return RT_EOK;
}
if (strncmp(line, kn_touch_max_x, sizeof(kn_touch_max_x) - 1) == 0)
{
begin = strchr(line, '=');
begin++;
setup->max_x = atoi(begin);
}
// touch_min_y
length = read_line(fd, line, sizeof(line));
if (length == 0)
{
close(fd);
cali_load_default();
return RT_EOK;
}
if (strncmp(line, kn_touch_min_y, sizeof(kn_touch_min_y) - 1) == 0)
{
begin = strchr(line, '=');
begin++;
setup->min_y = atoi(begin);
}
// touch_max_y
length = read_line(fd, line, sizeof(line));
if (length == 0)
{
close(fd);
cali_load_default();
return RT_EOK;
}
if (strncmp(line, kn_touch_max_y, sizeof(kn_touch_max_y) - 1) == 0)
{
begin = strchr(line, '=');
begin++;
setup->max_y = atoi(begin);
}
}
else
{
close(fd);
cali_load_default();
return RT_EOK;
}
}
else
{
close(fd);
cali_load_default();
return -RT_ERROR;
}
close(fd);
return RT_EOK;
}
rt_err_t cali_save(struct calibration_data* cali)
{
int fd, size;
char* p_str;
char* buf = rt_malloc(1024);
if (buf == RT_NULL)
{
rt_kprintf("no memory\r\n");
return RT_ENOMEM;
}
p_str = buf;
fd = open(cali_file, O_WRONLY | O_TRUNC, 0);
if (fd >= 0)
{
size = sprintf(p_str, "[config]\r\n"); // [config] sprintf(p_str,"")
p_str += size;
size = sprintf(p_str, "%s=%d\r\n", kn_touch_min_x, cali->min_x); //touch_min_x
p_str += size;
size = sprintf(p_str, "%s=%d\r\n", kn_touch_max_x, cali->max_x); //touch_max_x
p_str += size;
size = sprintf(p_str, "%s=%d\r\n", kn_touch_min_y, cali->min_y); //touch_min_y
p_str += size;
size = sprintf(p_str, "%s=%d\r\n", kn_touch_max_y, cali->max_y); //touch_max_y
p_str += size;
}
size = write(fd, buf, p_str - buf);
if (size == (p_str - buf))
{
rt_kprintf("file write succeed:\r\n");
}
close(fd);
rt_free(buf);
return RT_EOK;
}
/** This let the user space to restore the last calibration data.
*
* calibration_restore is a callback before calibration started. If it returns
* RT_TRUE, the calibration won't be started. In this condition, you must setup
* the calibration_data via something like:
*
* device = rt_device_find("touch");
* if(device != RT_NULL)
* rt_device_control(device, RT_TOUCH_CALIBRATION_DATA, &data);
*
* It it returns RT_FALSE, the normal calibration process will be started. If
* you don't have such feature, there is no need to call this function. The
* calibration will always be started by RTGUI.
*/
rt_bool_t calibration_restore(void)
{
//rt_kprintf("cali setup entered\n");
struct calibration_data setup;
if(cali_load(&setup) == RT_EOK)
{
struct calibration_data data;
rt_device_t device;
/* update the calibration data */
data.min_x = setup.min_x;
data.max_x = setup.max_x;
data.min_y = setup.min_y;
data.max_y = setup.max_y;
rt_kprintf("cali finished (%d, %d), (%d, %d)\n",
data.min_x,
data.max_x,
data.min_y,
data.max_y);
device = rt_device_find("touch");
if(device != RT_NULL)
rt_device_control(device, RT_TOUCH_CALIBRATION_DATA, &data);
return RT_TRUE;
}
/* if have no the calibration data,return false */
return RT_FALSE;
}
/** This provide ways to save the calibration_data to user space.
*
* calibration_after is a callback after the calibration has finished. User
* space could use this function to save the data to some where else. No need
* to call this if you don't have such function.
*/
void calibration_store(struct calibration_data *data)
{
struct calibration_data store;
store.min_x = data->min_x;
store.max_x = data->max_x;
store.min_y = data->min_y;
store.max_y = data->max_y;
cali_save(&store);
rt_kprintf("cali finished (%d, %d), (%d, %d)\n",
data->min_x,
data->max_x,
data->min_y,
data->max_y);
}
(2)新建文件touch_setup.h,加入下面代码:
#ifndef __TOUCH_SETUP_H_
#define __TOUCH_SETUP_H_
#include <rtthread.h>
#include <rtgui/calibration.h>
rt_err_t cali_load(struct calibration_data* setup);
rt_err_t cali_save(struct calibration_data* setup);
rt_bool_t calibration_restore(void);
void calibration_store(struct calibration_data *data);
//the pointer to load user data ,need to initialize
void calibration_set_restore(rt_bool_t (*calibration_restore)(void));
//the pointer to save user data ,need to initialize
void calibration_set_after(void (*calibration_after)(struct calibration_data *data));
#endif
(3)修改application.c文件,定位到136行附近,代码修改如下:
#ifndef RT_USING_COMPONENTS_INIT
/* init rtgui system server */
rtgui_system_server_init();
#endif /*#ifndef RT_USING_COMPONENTS_INIT*/
#ifdef RTGUI_USING_CALIBRATION
calibration_set_restore(calibration_restore);//initialize the pointer to load user data
calibration_set_after(calibration_store); //initialize the poiter to save user data
calibration_init();
#endif /* RTGUI_USING_CALIBRATION */
gui_application_init();
}
#endif /* RT_USING_RTGUI */
(4)打开calibration.c文件,定位到380行附近,如下下面代码:
#ifdef RT_USING_FINSH
#include <finsh.h>
void calibration(void)
{
_cali_restore = RT_NULL;
calibration_init();
}
FINSH_FUNCTION_EXPORT(calibration, perform touch calibration);
#endif
下面我感觉有必要对下面两个接口API函数坐下解释:
static rt_bool_t (*_cali_restore)(void);
void calibration_set_restore(rt_bool_t (*calibration_restore)(void))
{
_cali_restore = calibration_restore;
}
static void (*_cali_after)(struct calibration_data *data);
void calibration_set_after(void (*calibration_after)(struct calibration_data *data))
{
_cali_after = calibration_after;
}
_cali_restore和_cali_after这两个函数指针在没有实际定义的指针给它们赋值时,指针为空(RT_NULL),为了让calibration.c的342行附近,代码如下:
if (_cali_after)
_cali_after(&calibration_ptr->data);
如果_cali_after指针不空,将校正完的数据存储到到用户空间。
在系统启动时,需要从用户空间读取校正数据,如果读取成功,那么通过下面代码将其加入到系统中:
device = rt_device_find("touch");
if(device != RT_NULL)
rt_device_control(device, RT_TOUCH_CALIBRATION_DATA, &data);
return RT_TRUE;
所以上面分别给出了
_cali_restore和_cali_after这两个函数接口函数rt_bool_t calibration_restore(void)和void calibration_store(struct calibration_data *data),并在application.c的初始化部分调用了它们。
(5)在MDK中将touch_setup.c加入到Applications中。
系统启动时第一次因为用户空间没有cali.ini文件而读取失败,导致系统初始化时启动校正程序,但校正完成后,校正数据便cali.ini文件的形式存储到用户空间。下次启动时因问用户空间有了cali.ini数据校正文件而不再启动校正程序。
然后编译下载,复位后,按屏幕提示校正,发现可以正常触摸按钮,给开发板复位,发现没有启动触摸屏校正程序,在初始化完成后在触摸屏上按钮可以正常响应。这时终端输出如下:
set font size to 16
W25Q64BV or W25Q64CV detection
flash0 mount to /.
sd0 mount to /dev.
LCD ID 00005420
Load calibration data
cali finished (165, 3774), (3894, 173)
finsh />