软件环境: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)重命名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
修改完成后保存。
打开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上触摸几下,终端有触摸位置输出,因为还没有矫正,所以输出的点不确定。
为了加入触摸屏校正文件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)<触屏屏驱动移植和测试>
原文地址:http://blog.csdn.net/aping_cs_dn/article/details/44975353