RT-Thread 学习笔记(十三)--- 开启基于RTGUI的LCD显示功能(3)

软件环境: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文件中的相关硬件接口

RT-Thread 学习笔记(十三)--- 开启基于RTGUI的LCD显示功能(3)_第1张图片

上面的原理图中给出了触摸屏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()的第二个参数的字符串改短一点,不然字符显示不全,当然这是可选的,代码修改如下:


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 
#include 
#include 
#include "stdlib.h"//for atoi
#include 

#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 
#include 

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
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 />






你可能感兴趣的:(RT-Thread 学习笔记(十三)--- 开启基于RTGUI的LCD显示功能(3))