码迷,mamicode.com
首页 > 其他好文 > 详细

RT-Thread 学习笔记(十三)--- 开启基于RTGUI的LCD显示功能(3)<触屏屏驱动移植和测试>

时间:2015-04-16 10:24:32      阅读:293      评论:0      收藏:0      [点我收藏+]

标签:rt-thread   触摸屏   rtgui   

软件环境: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é?éy
... ...
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中的控件演示打开的太多,不能正常显示,此问题留待后面解决。






RT-Thread 学习笔记(十三)--- 开启基于RTGUI的LCD显示功能(3)<触屏屏驱动移植和测试>

标签:rt-thread   触摸屏   rtgui   

原文地址:http://blog.csdn.net/aping_cs_dn/article/details/44975353

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!