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

软件环境: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】加入LCD设备驱动文件

(1)登陆https://github.com/,然后在搜索栏输入RTGUI,可以找到RT-Thread分支下的RTGUI组件,如下图:

点击RTGUI链接,可以在打开的页面中点击“Download ZIP”按钮,打包下载RTGUI组件,如下图。

(2)解压RTGUI-master分支源码,将components目录下的rtgui组件复制到rt-thread-1.2.2/components目录下,如下图。

【2】开启RTGUI的编译选项

打开rtconfig.h文件,定位到164行附近,在“SECTION: RT-Thread/GUI”处,打开RTGUI 编译开关,代码修改如下:

/* SECTION: RT-Thread/GUI */

#define RT_USING_RTGUI

/* name length of RTGUI object */

#define RTGUI_NAME_MAX 12

/* support 16 weight font */

#define RTGUI_USING_FONT16

/* support Chinese font */

#define RTGUI_USING_FONTHZ

/* use DFS as file interface */

#define RTGUI_USING_DFS_FILERW

/* use font file as Chinese font */

#define RTGUI_USING_HZ_FILE

/* use Chinese bitmap font */

#define RTGUI_USING_HZ_BMP

/* use small size in RTGUI */

#define RTGUI_USING_SMALL_SIZE

/* use mouse cursor */

/* #define RTGUI_USING_MOUSE_CURSOR */

/* default font size in RTGUI */

#define RTGUI_DEFAULT_FONT_SIZE 16

/* image support */

/* #define RTGUI_IMAGE_XPM */

/* #define RTGUI_IMAGE_BMP */

修改完成后保存。然后再命令行窗口运行scons --tartet=mdk4 -s。打开KeilMDK 可以看到RTGUI组被加入进来,如下图。

【3】设置触摸屏驱动条件编译选项

(1)修改rtgui_config.h

打开rtgui_config.h,定位到53行附近,注释掉RTGUI_USING_CALIBRATION定义,代码修改如下:

... ...

//#define RTGUI_USING_TOUCH_PANEL

//#define RTGUI_USING_CALIBRATION

#define RTGUI_USING_VFRAMEBUFFER

修改完毕成保存。

(2)在有关触摸屏相关的操作处添加#ifdef RTGUI_USING_TOUCH_PANEL

打开application.c,定位到125行附近,代码修改如下:

#ifdef RT_USING_RTGUI

{

extern void rt_hw_lcd_init();

extern void rtgui_touch_hw_init(void);

rt_device_t lcd;

/* init lcd */

rt_hw_lcd_init();

/* init touch panel */

#ifdef RTGUI_USING_TOUCH_PANEL  

rtgui_touch_hw_init();

#endif /* #ifdef RTGUI_USING_TOUCH_PANEL */

/* find lcd device */

lcd = rt_device_find("lcd");

/* set lcd device as rtgui graphic driver */

rtgui_graphic_set_device(lcd);

#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(cali_setup);

calibration_set_after(cali_store);

calibration_init();

#endif /* #ifdef
RTGUI_USING_CALIBRATION*/

... ...

修改完成后保存。

(3)修改编译脚本

使用Notepad++打开rt-thread-1.2.2\components\rtgui\apps目录下的sconscript文件,定位到第9行,修改如下:

... ...

cwd = GetCurrentDir()

src = Glob(‘*.c‘)

group = DefineGroup(‘RTGUI‘, src, depend = [‘RTGUI_USING_CALIBRATION‘])

... ...

修改完成后保存。

(4)将touch.c从KeilMDK工程中移除,同时将stm32f103ze-ek/drivers目录下的touch.h和touch.c重命名成touch_driver.c和touch_driver.h,以备后用

【4】修改LCD的硬件接口

LCD的硬件接口原理图如下:

从LCD接口原理图可以看出,PC5为触摸屏中断请求线,PA5,PA6,PA7为SPI1接口,PG11为触摸屏总线的片选信号,PB1为LCD背光控制,FSMC[15:0] 为数据总线,PD5(FSMC_NWE)为写使能,PD4(FSMC_NOE)为读使能,PF0(FSMC_A0)指令/数据选择线。

LCD地址计算方法:

A,正如上图所示,对于16位宽度的外部存储器,stm32f103的FSMC将在内部使用HADDR[25:1]产生外部存储器的地址FSMC_A[24:0],而HADDR[0]未接;

B,LCD的CS引脚决定它的起始地址,STM32的CPU仅引出了4个片选信号,也就是CPU硬件最多只能外接4个总线型设备。安富莱开发板(V3)具有5个FSMC外设,所以开发板外扩一个地址译码器电路,如下图:

将NE4空间分为4部分,第1份给LCD,第2份给LAN,即当FSMC_A19=0、FSMC_NE4=0时选通LCD。STM32的NE4的起始地址是0x6c000000,FSMC_A19对应于HADDR[20],所以安富莱开发板(V3)的LCD起始地址为0x6c000000;

C,LCD的A0引脚决定传送的是地址还是数据,安富莱开发板(V3)上连接的是FSMC_A[0]即HADDR[1],所以安富莱开发板(V3)的IO_ADDR = 0x6c000000,IO_DATA = 0x6c100002。

安富莱开发板(V3)的LCD模块的显示控制IC为OTM4001A

(1)添加otm4001a.c驱动文件

在安富莱开发板(V3)的配套光盘中可以找到有关tft_lcd实验的例子,这里将例程 Ex007-TFT显示文字图片例程\User\bsp目录下bsp_tft_lcd.h和bsp_tft_lcd.c复制到stm32f103ze-ek/drivers目录下,并分别重命名为otm4001a.h和otm4001a.c,如下图:

(2)将otm4001a.c加入KeilMDK工程,同时将ssd1289.c从KeilMDK工程中移除。

(3)修改drivers目录下的脚本,将其加入编译列表。

<1>使用Notepad++打开stm32f103ze-ek/drivers目录下SConscript文件,定位到第34行加入下面代码:

# add RTGUI drvers.

if GetDepend(‘RT_USING_RTGUI‘):

src += [‘touch_driver.c‘]

if rtconfig.RT_USING_LCD_TYPE == ‘ILI932X‘:

src += [‘ili_lcd_general.c‘]

elif rtconfig.RT_USING_LCD_TYPE == ‘SSD1289‘:

src += [‘ssd1289.c‘]

elif rtconfig.RT_USING_LCD_TYPE == ‘OTM4001A‘:

src += [‘otm4001a.c‘]

CPPPATH = [cwd]

... ...

修改完成后保存并关闭。

<2>使用Notepad++打开stm32f103ze-ek目录下rtconfig.py文件,定位到第20行加入下面代码:

... ...

# lcd panel options

# ‘FMT0371‘,‘ILI932X‘, ‘SSD1289‘,‘OTM4001A‘

RT_USING_LCD_TYPE = ‘OTM4001A

... ...

修改完成后保存并关闭。

【5】OTM4001A的驱动代码移植

(1)移植后的otm4001a.c代码如下:

#include "stm32f10x.h"
#include "otm4001a.h"

//Êä³öÖض¨Ïò.µ±²»½øÐÐÖض¨Ïòʱ.
#define printf               rt_kprintf //ʹÓÃrt_kprintfÀ´Êä³ö
//#define printf(...)                       //ÎÞÊä³ö

/* ¶¨ÒåLCDÇý¶¯Æ÷µÄ·ÃÎʵØÖ·
	TFT½Ó¿ÚÖеÄRSÒý½ÅÁ¬½ÓFSMC_A0Òý½Å£¬ÓÉÓÚÊÇ16bitģʽ£¬RS¶ÔÓ¦A1µØÖ·Ïߣ¬Òò´Ë
	LCD_RAMµÄµØÖ·ÊÇ+2
*/

typedef struct
{
	__IO uint16_t LCD_REG;
	__IO uint16_t LCD_RAM;
}
LCD_TypeDef;

#define LCD_BASE        ((uint32_t)(0x60000000 | 0x0C000000))
#define LCD							((LCD_TypeDef *)LCD_BASE)

static void delay(int cnt);
static void LCD_CtrlLinesConfig(void);
static void LCD_FSMCConfig(void);

/*******************************************************************************
*	º¯ÊýÃû: LCD_WriteReg
*	²Î  Êý: LCD_Reg £º¼Ä´æÆ÷µØÖ·;  LCD_RegValue : ¼Ä´æÆ÷Öµ
*	·µ  »Ø: ÎÞ
*	¹¦  ÄÜ: ÐÞ¸ÄLCD¿ØÖÆÆ÷µÄ¼Ä´æÆ÷µÄÖµ
*/
void LCD_WriteReg(__IO uint16_t LCD_Reg, uint16_t LCD_RegValue)
{
	/* Write 16-bit Index, then Write Reg */
	LCD->LCD_REG = LCD_Reg;
	/* Write 16-bit Reg */
	LCD->LCD_RAM = LCD_RegValue;
}
/*******************************************************************************
*	º¯ÊýÃû: LCD_ReadReg
*	²Î  Êý: LCD_Reg £º¼Ä´æÆ÷µØÖ·
*	·µ  »Ø: ¼Ä´æÆ÷µÄÖµ
*	¹¦  ÄÜ: ¶ÁLCD¿ØÖÆÆ÷µÄ¼Ä´æÆ÷µÄÖµ
*/
uint16_t LCD_ReadReg(__IO uint16_t LCD_Reg)
{
	/* Write 16-bit Index (then Read Reg) */
	LCD->LCD_REG = LCD_Reg;
	/* Read 16-bit Reg */
	return (LCD->LCD_RAM);
}

/*******************************************************************************
*
*LCD_ReadData()
*·µ  »Ø: ¼Ä´æÆ÷µÄÖµ
*¹¦  ÄÜ: ¶ÁLCD¿ØÖÆÆ÷µÄ¼Ä´æÆ÷µÄÖ

********************************************************************************/
uint16_t LCD_ReadData()
{
		/* Read 16-bit Reg */
		return (LCD->LCD_RAM);
}

/*******************************************************************************
*	º¯ÊýÃû: LCD_WriteRAM_Prepare
*	²Î  Êý: ÎÞ
*	·µ  »Ø: ÎÞ
*	¹¦  ÄÜ: дÏÔ´æÇ°µÄ×¼±¸£¬¼´ÉèÖÃÏÔ´æ¼Ä´æÆ÷µØÖ·¡£
*/
void LCD_WriteRAM_Prepare(void)
{
	LCD->LCD_REG = 0x202;	           //write data to GRAM
}

/*******************************************************************************
*	º¯ÊýÃû: LCD_WriteRAM
*	²Î  Êý: RGB_Code : ÑÕÉ«´úÂë
*	·µ  »Ø: ÎÞ
*	¹¦  ÄÜ: дÏԴ棬ÏÔ´æµØÖ·×Ô¶¯Ôö¼Ó¡£ÊÊÓÃÓÚÁ¬Ðøд¡£
*/
void LCD_WriteRAM(uint16_t RGB_Code)
{
	/* Write 16-bit GRAM Reg */
	LCD->LCD_RAM = RGB_Code;
}

/*******************************************************************************
*	º¯ÊýÃû: LCD_WriteRAM1
*	²Î  Êý: RGB_Code : ÑÕÉ«´úÂë
*	·µ  »Ø: ÎÞ
*	¹¦  ÄÜ: дÏԴ棬ÏÔ´æµØÖ·×Ô¶¯Ôö¼Ó¡£ÊÊÓÃÓÚдµ¥¸öÏñËØ¡£
*/
void LCD_WriteRAM1(uint16_t RGB_Code)
{
	LCD->LCD_REG = 0x202;

	/* Write 16-bit GRAM Reg */
	LCD->LCD_RAM = RGB_Code;
}

/*******************************************************************************
*	º¯ÊýÃû: LCD_ReadRAM
*	²Î  Êý: ÎÞ
*	·µ  »Ø: ÏÔ´æÊý¾Ý
*	¹¦  ÄÜ: ¶ÁÏԴ棬µØÖ·×Ô¶¯Ôö¼Ó
*/
uint16_t LCD_ReadRAM(void)
{
  /* Read 16-bit Reg */
  return LCD->LCD_RAM;
}

/*******************************************************************************
*	º¯ÊýÃû: LCD_SetCursor
*	²Î  Êý: Xpos : X×ø±ê; Ypos: Y×ø±ê
*	·µ  »Ø: ÎÞ
*	¹¦  ÄÜ: ÉèÖùâ±êλÖÃ
*/
void LCD_SetCursor(uint16_t Xpos, uint16_t Ypos)
{
	/*
		px£¬py ÊÇÎïÀí×ø±ê£¬ x£¬yÊÇÐéÄâ×ø±ê
		ת»»¹«Ê½:
		py = 399 - x;
		px = y;
	*/
	//LCD_WriteReg(0x0200, Ypos);  			/* px */     //gram address set horizontal
	//LCD_WriteReg(0x0201, 399 - Xpos);	/* py */	 //gram address set vertical

  //ÎïÀí×ø±êºÍÐéÄâ×ø±ê¶ÔÓ¦
	LCD_WriteReg(0x0200, Xpos);  				/* px */     //gram address set horizontal
	LCD_WriteReg(0x0201, Ypos);					/* py */	 //gram address set vertical
}

/*******************************************************************************
*	º¯ÊýÃû: LCD_ReadGRAM
*	²Î  Êý:
*	·µ  »Ø: ÎÞ
*	¹¦  ÄÜ: ¶ÁÈ¡ÏÔ´æ
*/
static unsigned short LCD_ReadGRAM(int x,int y)
{
     unsigned short temp;
     LCD_SetCursor(x,y);
	 LCD_WriteRAM_Prepare();

	 temp=LCD_ReadData();
	 temp=LCD_ReadData();
	 return temp;
}
/******************************************************************************************************/

static unsigned short deviceid=0;
/*
*********************************************************************************************************
*	º¯ Êý Ãû: otm4001_hw_init
*	¹¦ÄÜ˵Ã÷: ³õʼ»¯LCD
*	ÐÎ    ²Î£ºÎÞ
*	·µ »Ø Öµ: ÎÞ
*********************************************************************************************************
*/
void otm4001_hw_init(void)
{
	//uint16_t id;

	/* ÅäÖÃLCD¿ØÖÆ¿ÚÏßGPIO */
	LCD_CtrlLinesConfig();

	/* ÅäÖÃFSMC½Ó¿Ú£¬Êý¾Ý×ÜÏß */
	LCD_FSMCConfig();

	/* FSMCÖØÖúó±ØÐë¼ÓÑÓ³Ù²ÅÄÜ·ÃÎÊ×ÜÏßÉ豸  */
	delay(2000); //20ms

	deviceid = LCD_ReadReg(0x0000);  	/* ¶ÁÈ¡LCDÇý¶¯Ð¾Æ¬ID */
	printf("LCD ID %08x\r\n",deviceid);

	/* ³õʼ»¯LCD£¬Ð´LCD¼Ä´æÆ÷½øÐÐÅäÖà */
	LCD_WriteReg(0x0000, 0x0000);
	LCD_WriteReg(0x0001, 0x0100);
	LCD_WriteReg(0x0002, 0x0100);

	/*
		R003H ¼Ä´æÆ÷ºÜ¹Ø¼ü£¬ Entry Mode £¬¾ö¶¨ÁËɨÃè·½Ïò
		²Î¼û£ºSPFD5420A.pdf µÚ15Ò³

		240x400ÆÁÄ»ÎïÀí×ø±ê(px,py)ÈçÏÂ:
		    R003 = 0x1018                  R003 = 0x1008
		  -------------------          -------------------
		 |(0,0)              |        |(0,0)              |
		 |                   |        |					  				|
		 |  ^           ^    |        |   ^           ^   |
		 |  |           |    |        |   |           |   |
		 |  |           |    |        |   |           |   |
		 |  |           |    |        |   |           |   |
		 |  |  ------>  |    |        |   | <------   |   |
		 |  |           |    |        |   |           |   |
		 |  |           |    |        |   |           |   |
		 |  |           |    |        |   |           |   |
		 |  |           |    |        |   |           |   |
		 |                   |        |					  				|
		 |                   |        |                   |
		 |      (x=239,y=399)|        |      (x=239,y=399)|
		 |-------------------|        |-------------------|
		 |                   |        |                   |
		  -------------------          -------------------

		°´ÕÕ°²¸»À³¿ª·¢°åLCDµÄ·½Ïò£¬ÎÒÃÇÆÚÍûµÄÐéÄâ×ø±êºÍɨÃè·½ÏòÈçÏ£º(ºÍÉÏͼµÚ1¸öÎǺÏ)
		 --------------------------------
		|  |(0,0)                        |
		|  |     --------->              |
		|  |         |                   |
		|  |         |                   |
		|  |         |                   |
		|  |         V                   |
		|  |     --------->              |
		|  |                    (399,239)|
		 --------------------------------

		ÐéÄâ×ø±ê(x,y) ºÍÎïÀí×ø±êµÄת»»¹Øϵ
		x = 399 - py;
		y = px;

		py = 399 - x;
		px = y;
	*/
	LCD_WriteReg(0x0003, 0x1018); /* 0x1018 1030 */
	LCD_WriteReg(0x0003,0x1030); //Entry Mode
	LCD_WriteReg(0x0008, 0x0808);//display Control2
	LCD_WriteReg(0x0009, 0x0001);//display Control3
	LCD_WriteReg(0x000B, 0x0010);//low power Control
	LCD_WriteReg(0x000C, 0x0000);//External Display interface control 1
	LCD_WriteReg(0x000F, 0x0000);//external dispaly interface Control 2
	LCD_WriteReg(0x0007, 0x0001);//display control1
	LCD_WriteReg(0x0010, 0x0013);//panel interface control 1
	LCD_WriteReg(0x0011, 0x0501);//panel interface control 2
	LCD_WriteReg(0x0012, 0x0300);//panel interface control 3
	LCD_WriteReg(0x0020, 0x021E);//panel interface control 4
	LCD_WriteReg(0x0021, 0x0202);//panel interface control 5
	LCD_WriteReg(0x0090, 0x8000);//frame marker control
	LCD_WriteReg(0x0100, 0x17B0);//power control 1
	LCD_WriteReg(0x0101, 0x0147);//power control 2
	LCD_WriteReg(0x0102, 0x0135);//power control 3
	LCD_WriteReg(0x0103, 0x0700);//power control 4
	LCD_WriteReg(0x0107, 0x0000);
	LCD_WriteReg(0x0110, 0x0001);
	LCD_WriteReg(0x0210, 0x0000);//Window horizontal ramaddress start
	LCD_WriteReg(0x0211, 0x00EF);//window horizontal ramaddress end
	LCD_WriteReg(0x0212, 0x0000);//window vertical ram address start
	LCD_WriteReg(0x0213, 0x018F);//window vertical ramaddress end
	LCD_WriteReg(0x0280, 0x0000);
	LCD_WriteReg(0x0281, 0x0004);
	LCD_WriteReg(0x0282, 0x0000);
	LCD_WriteReg(0x0300, 0x0101);//  y control
	LCD_WriteReg(0x0301, 0x0B2C);
	LCD_WriteReg(0x0302, 0x1030);
	LCD_WriteReg(0x0303, 0x3010);
	LCD_WriteReg(0x0304, 0x2C0B);
	LCD_WriteReg(0x0305, 0x0101);
	LCD_WriteReg(0x0306, 0x0807);
	LCD_WriteReg(0x0307, 0x0708);
	LCD_WriteReg(0x0308, 0x0107);
	LCD_WriteReg(0x0309, 0x0105);
	LCD_WriteReg(0x030A, 0x0F04);
	LCD_WriteReg(0x030B, 0x0F00);
	LCD_WriteReg(0x030C, 0x000F);
	LCD_WriteReg(0x030D, 0x040F);
	LCD_WriteReg(0x030E, 0x0300);
	LCD_WriteReg(0x030F, 0x0701);//y control
	LCD_WriteReg(0x0400, 0x3500);//BASE IMAGE NUMBER OF LINE
	LCD_WriteReg(0x0401, 0x0001);//base image display control
	LCD_WriteReg(0x0404, 0x0000);//base image vertical scroll control
	LCD_WriteReg(0x0500, 0x0000);
	LCD_WriteReg(0x0501, 0x0000);
	LCD_WriteReg(0x0502, 0x0000);
	LCD_WriteReg(0x0503, 0x0000);
	LCD_WriteReg(0x0504, 0x0000);
	LCD_WriteReg(0x0505, 0x0000);
	LCD_WriteReg(0x0600, 0x0000);
	LCD_WriteReg(0x0606, 0x0000);
	LCD_WriteReg(0x06F0, 0x0000);
	LCD_WriteReg(0x07F0, 0x5420);
	LCD_WriteReg(0x07DE, 0x0000);
	LCD_WriteReg(0x07F2, 0x00DF);
	LCD_WriteReg(0x07F3, 0x0810);
	LCD_WriteReg(0x07F4, 0x0077);
	LCD_WriteReg(0x07F5, 0x0021);
	LCD_WriteReg(0x07F0, 0x0000);
	LCD_WriteReg(0x0007, 0x0173);//diplay control

	/* ÉèÖÃÏÔʾ´°¿Ú WINDOWS */
	LCD_WriteReg(0x0210, 0);		/* ˮƽÆðʼµØÖ· */
	LCD_WriteReg(0x0211, 239);	/* ˮƽ½áÊø×ø±ê */
	LCD_WriteReg(0x0212, 0);		/* ´¹Ö±ÆðʼµØÖ· */
	LCD_WriteReg(0x0213, 399);	/* ´¹Ö±½áÊøµØÖ· */
}

static void delay(int cnt)
{
    volatile unsigned int dl;
    while(cnt--)
    {
        for(dl=0; dl<500; dl++);
    }
}

/*
*********************************************************************************************************
*	º¯ Êý Ãû: LCD_CtrlLinesConfig
*	¹¦ÄÜ˵Ã÷: ÅäÖÃLCD¿ØÖÆ¿ÚÏߣ¬FSMC¹Ü½ÅÉèÖÃΪ¸´Óù¦ÄÜ
*	ÐÎ    ²Î£ºÎÞ
*	·µ »Ø Öµ: ÎÞ
*********************************************************************************************************
*/
static void LCD_CtrlLinesConfig(void)
{
	GPIO_InitTypeDef GPIO_InitStructure;

	RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);

	/* ʹÄÜ FSMC, GPIOD, GPIOE, GPIOF, GPIOG ºÍ AFIO ʱÖÓ */
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
	                     RCC_APB2Periph_GPIOF | RCC_APB2Periph_GPIOG |
	                     RCC_APB2Periph_AFIO, ENABLE);

	/* ÉèÖÃ PD.00(D2), PD.01(D3), PD.04(NOE), PD.05(NWE), PD.08(D13), PD.09(D14),
	 PD.10(D15), PD.14(D0), PD.15(D1) Ϊ¸´ÓÃÍÆÍìÊä³ö */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5 |
	                            GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_14 |
	                            GPIO_Pin_15;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_Init(GPIOD, &GPIO_InitStructure);

	/* ÉèÖÃ PE.07(D4), PE.08(D5), PE.09(D6), PE.10(D7), PE.11(D8), PE.12(D9), PE.13(D10),
	 PE.14(D11), PE.15(D12) Ϊ¸´ÓÃÍÆÍìÊä³ö */
	/* PE3,PE4 ÓÃÓÚA19, A20, STM32F103ZE-EK(REV 1.0)±ØÐëʹÄÜ */
	/* PE5,PE6 ÓÃÓÚA19, A20, STM32F103ZE-EK(REV 2.0)±ØÐëʹÄÜ */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
	                            GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 |
	                            GPIO_Pin_15 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_5 | GPIO_Pin_6;
	GPIO_Init(GPIOE, &GPIO_InitStructure);

	/* ÉèÖà PF.00(A0 (RS))  Ϊ¸´ÓÃÍÆÍìÊä³ö */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
	GPIO_Init(GPIOF, &GPIO_InitStructure);

	/* ÉèÖà PG.12(NE4 (LCD/CS)) Ϊ¸´ÓÃÍÆÍìÊä³ö - CE3(LCD /CS) */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
	GPIO_Init(GPIOG, &GPIO_InitStructure);

}

/*
*********************************************************************************************************
*	º¯ Êý Ãû: LCD_FSMCConfig
*	¹¦ÄÜ˵Ã÷: ÅäÖÃFSMC²¢¿Ú·ÃÎÊʱÐò
*	ÐÎ    ²Î£ºÎÞ
*	·µ »Ø Öµ: ÎÞ
*********************************************************************************************************
*/
static void LCD_FSMCConfig(void)
{
	FSMC_NORSRAMInitTypeDef  FSMC_NORSRAMInitStructure;
  FSMC_NORSRAMTimingInitTypeDef  FSMC_NORSRAMTimingInitStructure;

  /*-- FSMC Configuration ------------------------------------------------------*/
  /*----------------------- SRAM Bank 4 ----------------------------------------*/
  /* FSMC_Bank1_NORSRAM4 configuration */
  FSMC_NORSRAMTimingInitStructure.FSMC_AddressSetupTime = 1;
  FSMC_NORSRAMTimingInitStructure.FSMC_AddressHoldTime = 0;
  FSMC_NORSRAMTimingInitStructure.FSMC_DataSetupTime = 2;
  FSMC_NORSRAMTimingInitStructure.FSMC_BusTurnAroundDuration = 0;
  FSMC_NORSRAMTimingInitStructure.FSMC_CLKDivision = 0;
  FSMC_NORSRAMTimingInitStructure.FSMC_DataLatency = 0;
  FSMC_NORSRAMTimingInitStructure.FSMC_AccessMode = FSMC_AccessMode_B;

  /* Color LCD configuration ------------------------------------
     LCD configured as follow:
        - Data/Address MUX = Disable
        - Memory Type = SRAM
        - Data Width = 16bit
        - Write Operation = Enable
        - Extended Mode = Enable
        - Asynchronous Wait = Disable */
  FSMC_NORSRAMInitStructure.FSMC_Bank = FSMC_Bank1_NORSRAM4;
  FSMC_NORSRAMInitStructure.FSMC_DataAddressMux = FSMC_DataAddressMux_Disable;
  FSMC_NORSRAMInitStructure.FSMC_MemoryType = FSMC_MemoryType_SRAM;
  FSMC_NORSRAMInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_16b;
  FSMC_NORSRAMInitStructure.FSMC_BurstAccessMode = FSMC_BurstAccessMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalPolarity = FSMC_WaitSignalPolarity_Low;
  FSMC_NORSRAMInitStructure.FSMC_WrapMode = FSMC_WrapMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignalActive = FSMC_WaitSignalActive_BeforeWaitState;
  FSMC_NORSRAMInitStructure.FSMC_WriteOperation = FSMC_WriteOperation_Enable;
  FSMC_NORSRAMInitStructure.FSMC_WaitSignal = FSMC_WaitSignal_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ExtendedMode = FSMC_ExtendedMode_Disable;
  FSMC_NORSRAMInitStructure.FSMC_WriteBurst = FSMC_WriteBurst_Disable;
  FSMC_NORSRAMInitStructure.FSMC_ReadWriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;
  FSMC_NORSRAMInitStructure.FSMC_WriteTimingStruct = &FSMC_NORSRAMTimingInitStructure;

  FSMC_NORSRAMInit(&FSMC_NORSRAMInitStructure);

  /* - BANK 3 (of NOR/SRAM Bank 0~3) is enabled */
  FSMC_NORSRAMCmd(FSMC_Bank1_NORSRAM4, ENABLE);

}

static uint8_t s_bright;	/* ±³¹âÁÁ¶È */
/*
*********************************************************************************************************
*	º¯ Êý Ãû: LCD_SetBackLight
*	¹¦ÄÜ˵Ã÷: ³õʼ»¯¿ØÖÆLCD±³¾°¹âµÄGPIO,ÅäÖÃΪPWMģʽ¡£
*			µ±¹Ø±Õ±³¹âʱ£¬½«CPU IOÉèÖÃΪ¸¡¶¯ÊäÈëģʽ£¨ÍƼöÉèÖÃΪÍÆÍìÊä³ö£¬²¢Çý¶¯µ½µÍµçƽ)£»½«TIM3¹Ø±Õ Ê¡µç
*	ÐÎ    ²Î£º_bright ÁÁ¶È£¬0ÊÇÃð£¬255ÊÇ×îÁÁ
*	·µ »Ø Öµ: ÎÞ
*
*	±³¹â¿ÚÏßÊÇ PB1, ¸´Óù¦ÄÜÑ¡Ôñ TIM3_CH4
*
*	µ±¹Ø±Õ±³¹âʱ£¬
*		½«CPU IOÉèÖÃΪ¸¡¶¯ÊäÈëģʽ£¨ÍƼöÉèÖÃΪÍÆÍìÊä³ö£¬²¢Çý¶¯µ½µÍµçƽ)
*		½«TIM3¹Ø±Õ Ê¡µç
*********************************************************************************************************
*/
void lcd_set_backlight(uint8_t _bright)
{
	GPIO_InitTypeDef GPIO_InitStructure;
	TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
	TIM_OCInitTypeDef  TIM_OCInitStructure;
	s_bright = _bright;

	/* µÚ1²½£º´ò¿ªGPIOB RCC_APB2Periph_AFIO µÄʱÖÓ	*/
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_AFIO, ENABLE);

	if (_bright == 0)
	{
		/* ÅäÖñ³¹âGPIOΪÊäÈëģʽ */
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOB, &GPIO_InitStructure);

		/* ¹Ø±ÕTIM3 */
		TIM_Cmd(TIM3, DISABLE);
		return;
	}
	else if (_bright == BRIGHT_MAX)	/* ×î´óÁÁ¶È */
	{
		/* ÅäÖñ³¹âGPIOΪÍÆÍìÊä³öģʽ */
		GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
		GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
		GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
		GPIO_Init(GPIOB, &GPIO_InitStructure);

		GPIO_SetBits(GPIOB, GPIO_Pin_1);

		/* ¹Ø±ÕTIM3 */
		TIM_Cmd(TIM3, DISABLE);
		return;
	}

	/* ÅäÖñ³¹âGPIOΪ¸´ÓÃÍÆÍìÊä³öģʽ */
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOB, &GPIO_InitStructure);

	/* ʹÄÜTIM3µÄʱÖÓ */
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);

	/*
		TIM3 ÅäÖÃ: ²úÉú1·PWMÐźÅ;
		TIM3CLK = 72 MHz, Prescaler = 0(²»·ÖƵ), TIM3 counter clock = 72 MHz
		¼ÆË㹫ʽ£º
		PWMÊä³öƵÂÊ = TIM3 counter clock /(ARR + 1)

		ÎÒÃÇÆÚÍûÉèÖÃΪ100Hz

		Èç¹û²»¶ÔTIM3CLKÔ¤·ÖƵ£¬ÄÇô²»¿ÉÄܵõ½100HzµÍƵ¡£
		ÎÒÃÇÉèÖ÷ÖƵ±È = 1000£¬ ÄÇô  TIM3 counter clock = 72KHz
		TIM_Period = 720 - 1;
		ƵÂÊϲ»À´¡£
	 */
	TIM_TimeBaseStructure.TIM_Period = 720 - 1;	/* TIM_Period = TIM3 ARR Register */
	TIM_TimeBaseStructure.TIM_Prescaler = 0;
	TIM_TimeBaseStructure.TIM_ClockDivision = 0;
	TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

	TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

	/* PWM1 Mode configuration: Channel1 */
	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
	TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
	/*
		_bright = 1 ʱ, TIM_Pulse = 1
		_bright = 255 ʱ, TIM_Pulse = TIM_Period
	*/
	TIM_OCInitStructure.TIM_Pulse = (TIM_TimeBaseStructure.TIM_Period * _bright) / BRIGHT_MAX;	/* ¸Ä±äÕ¼¿Õ±È */

	TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
	TIM_OC4Init(TIM3, &TIM_OCInitStructure);
	TIM_OC4PreloadConfig(TIM3, TIM_OCPreload_Enable);

	TIM_ARRPreloadConfig(TIM3, ENABLE);

	/* ʹÄÜ TIM3 ¶¨Ê±Æ÷ */
	TIM_Cmd(TIM3, ENABLE);
}
/*******************************************************************************
*	º¯ÊýÃû: GetBackLight
*	Êä  Èë: ÎÞ
*	Êä  ³ö:	·µ»Øµ±Ç°ÁÁ¶ÈÖµ
*	¹¦ÄÜ˵Ã÷£º»ñÈ¡µ±Ç°ÁÁ¶ÈÖµ£¨0-255)
*/
uint8_t lcd_get_backlight(void)
{
	return s_bright;
}

/**************************************************************************
* ÅäÖÃRT-Thread LCD½Ó¿Ú
*
****************************************************************************/

/*ÉèÖÃÏñËصãÑÕÉ«,x,y*/
void lcd_set_pixel(const char *pixel,int x,int y)
{
  LCD_SetCursor(x,y);
	// LCD_WriteRAM1(*(rt_uint16_t *)pixel);
	LCD_WriteRAM_Prepare();
	LCD_WriteRAM(*(rt_uint16_t*)pixel);

}

/*»ñÈ¡ÏñËصãÑÕÉ«*/
void lcd_get_pixel(char *pixel,int x,int y)
{
     *(rt_uint16_t*)pixel=LCD_ReadGRAM(x, y);
}

/*  »­Ë®Æ½Ïß*/
void  lcd_draw_hline(const char *pixel,int x1,int x2,int y)
{
  /* [5:4]-ID~ID0 [3]-AM-1´¹Ö±-0ˮƽ */
  LCD_WriteReg(0x0003,0x1030 |0<<3);  //AM=0 hline
	LCD_SetCursor(x1, y);

	LCD_WriteRAM_Prepare();
  while(x1<x2)
	{
		LCD_WriteRAM(*(rt_uint16_t *)pixel);
		x1++;
	}

}

/*´¹Ö±Ïß*/
void  lcd_draw_vline(const char *pixel,int x,int y1,int y2)
{
  /* [5:4]-ID~ID0 [3]-AM-1´¹Ö±-0ˮƽ */
  LCD_WriteReg(0x0003,0x1030 |1<<3);  //AM=1 vline
	LCD_SetCursor(x,y1);
	LCD_WriteRAM_Prepare();
  while(y1<y2)
  {
		LCD_WriteRAM(*(rt_uint16_t*)pixel);
		y1++;
  }

}

void  lcd_blit_line(const char * pixels,int x,int y,rt_size_t size)
{
   rt_uint16_t *ptr;

   ptr = (rt_uint16_t*) pixels;

   /* [5:4]-ID~ID0 [3]-AM-1´¹Ö±-0ˮƽ */
   LCD_WriteReg(0x0003,0x1030 |0<<3);  //AM=0 hline

   LCD_SetCursor(x,y);
   LCD_WriteRAM_Prepare();
   while(size)
   {
   		LCD_WriteRAM(*ptr ++);
			size --;
   }

}

struct rt_device_graphic_ops otm4001_ops =
{
	lcd_set_pixel,
	lcd_get_pixel,
	lcd_draw_hline,
	lcd_draw_vline,
	lcd_blit_line

};

struct rt_device _lcd_device;
static rt_err_t lcd_init(rt_device_t dev)
{
	return RT_EOK;
}

static rt_err_t lcd_open(rt_device_t dev, rt_uint16_t oflag)
{
	return RT_EOK;
}

static rt_err_t lcd_close(rt_device_t dev)
{
	return RT_EOK;
}

static rt_err_t lcd_control(rt_device_t dev, rt_uint8_t cmd, void *args)
{
	switch (cmd)
	{
	case RTGRAPHIC_CTRL_GET_INFO:
		{
			struct rt_device_graphic_info *info;

			info = (struct rt_device_graphic_info*) args;
			RT_ASSERT(info != RT_NULL);

			info->bits_per_pixel = 16;
			info->pixel_format = RTGRAPHIC_PIXEL_FORMAT_RGB565P;
			info->framebuffer = RT_NULL;
			info->width = 240;
			info->height = 400;
		}
		break;

	case RTGRAPHIC_CTRL_RECT_UPDATE:
		/* nothong to be done */
		break;

	default:
		break;
	}

	return RT_EOK;
}

void rt_hw_lcd_init(void)
{

	/* register lcd device */
	_lcd_device.type  = RT_Device_Class_Graphic;
	_lcd_device.init  = lcd_init;
	_lcd_device.open  = lcd_open;
	_lcd_device.close = lcd_close;
	_lcd_device.control = lcd_control;
	_lcd_device.read  = RT_NULL;
	_lcd_device.write = RT_NULL;

	_lcd_device.user_data = &otm4001_ops;

  otm4001_hw_init();

	lcd_set_backlight(200);
    /* register graphic device driver */
	rt_device_register(&_lcd_device, "lcd",
	RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
}

(2)移植后的otm4001a.h代码如下:

#ifndef _OTM4001_H_INCLUDE
#define _OTM4001_H_INCLUDE

#include "stm32f10x.h"
#include "rtthread.h"
#include <rtgui/rtgui.h>
#include <rtgui/driver.h>
#include <rtgui/rtgui_server.h>
#include <rtgui/rtgui_system.h>

/* ¶¨ÒåLCDÏÔʾÇøÓòµÄ·Ö±æÂÊ */
#define LCD_HEIGHT	240		/* ¸ß¶È£¬µ¥Î»£ºÏñËØ */
#define LCD_WIDTH		400		/* ¿í¶È£¬µ¥Î»£ºÏñËØ */

/* LCD ¼Ä´æÆ÷¶¨Òå, LR_ǰ׺ÊÇLCD RegisterµÄ¼òд */
#define LR_CTRL1		0x007	/* ¶ÁдÏÔ´æµÄ¼Ä´æÆ÷µØÖ· */
#define LR_GRAM			0x202	/* ¶ÁдÏÔ´æµÄ¼Ä´æÆ÷µØÖ· */
#define LR_GRAM_X		0x200	/* ÏÔ´æˮƽµØÖ·£¨ÎïÀíX×ø±ê£©*/
#define LR_GRAM_Y		0x201	/* ÏÔ´æ´¹Ö±µØÖ·£¨ÎïÀíY×ø±ê£©*/

/* LCD ÑÕÉ«´úÂ룬CL_ÊÇColorµÄ¼òд */
enum
{
	CL_WHITE        = 0xFFFF,	/* °×É« */
	CL_BLACK        = 0x0000,	/* ºÚÉ« */
	CL_GREY         = 0xF7DE,	/* »ÒÉ« */
	CL_BLUE         = 0x001F,	/* À¶É« */
	CL_BLUE2        = 0x051F,	/* dzÀ¶É« */
	CL_RED          = 0xF800,	/* ºìÉ« */
	CL_MAGENTA      = 0xF81F,	/* ºì×ÏÉ«£¬ÑóºìÉ« */
	CL_GREEN        = 0x07E0,	/* ÂÌÉ« */
	CL_CYAN         = 0x7FFF,	/* À¶ÂÌÉ«£¬ÇàÉ« */
	CL_YELLOW       = 0xFFE0,	/* »ÆÉ« */
	CL_MASK			= 0x9999	/* ÑÕÉ«ÑÚÂ룬ÓÃÓÚÎÄ×Ö±³¾°Í¸Ã÷ */
};

/* ×ÖÌå´úÂë */
enum
{
	FC_ST_16X16 = 0,		/* ËÎÌå15x16µãÕó £¨¿íx¸ß£© */
	FC_ST_24X24 = 1			/* ËÎÌå24x24µãÕó £¨¿íx¸ß£© */
};

/* ×ÖÌåÊôÐԽṹ, ÓÃÓÚLCD_DispStr() */
typedef struct
{
	uint16_t usFontCode;	/* ×ÖÌå´úÂë 0 ±íʾ16µãÕó */
	uint16_t usTextColor;	/* ×ÖÌåÑÕÉ« */
	uint16_t usBackColor;	/* ÎÄ×Ö±³¾°ÑÕÉ«£¬Í¸Ã÷ */
	uint16_t usSpace;		/* ÎÄ×Ö¼ä¾à£¬µ¥Î» = ÏñËØ */
}FONT_T;

/* ±³¾°¹â¿ØÖÆ */
#define BRIGHT_MAX		255
#define BRIGHT_MIN		0
#define BRIGHT_DEFAULT	200
#define BRIGHT_STEP		5

/* ¿É¹©Íⲿģ¿éµ÷Óõĺ¯Êý */

void lcd_set_backlight(uint8_t _bright);
uint8_t lcd_get_backlight(void);

#endif

然后保存,接下来就可以编译了。

时间: 2024-10-20 15:40:45

RT-Thread 学习笔记(十一)--- 开启基于RTGUI的LCD显示功能的相关文章

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

软件环境: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)重

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

软件环境: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 上篇文章中我们LCD驱动进行了移植,接下来进行编译和调试 [1]在命令行中使用scons编译,出现

Boost Thread学习笔记三

下面先对condition_impl进行简要分析.condition_impl在其构造函数中会创建两个Semaphore(信号量):m_gate.m_queue,及一个Mutex(互斥体,跟boost::mutex类似,但boost::mutex是基于CriticalSection<临界区>的):m_mutex,其中:m_queue相当于当前所有等待线程的等待队列,构造函数中调用CreateSemaphore来创建Semaphore时,lMaximumCount参数被指定为(std::nume

《Hibernate学习笔记十一》:树状结构设计

<Hibernate学习笔记十一>:树状结构设计 这是马士兵老师讲解Hibernate的一个作业题,树状结构设计,这是一个比较典型的例子,因此有必要写篇博文记录下. 树状结构的设计,它是在同一个类中使用了多对一(ManyToOne)和一对多(OneToMany). 在完成这个题目我们应该按照如下的步骤进行: 1.先思考数据库的模型应该是什么样的?? 数据库中的模型应该如下:即存在id p_id 2.思考面向对象的模型,及如何来进行映射??? 根据数据库中表的特点,对象应该有id name;由于

初探swift语言的学习笔记十一(performSelector)

作者:fengsh998 原文地址:http://blog.csdn.net/fengsh998/article/details/35842441 转载请注明出处 如果觉得文章对你有所帮助,请通过留言或关注微信公众帐号fengsh998来支持我,谢谢! 在OC中使用好好的performSelector,但不知为什么在swift有意的被拿掉了.更有甚者连IMP, objc_msgSend也不能用了.虽然想不通为什么,但应该有他的道理.就不纠结了. 大家可能在OC中使用得更多的就是延时处理,及后台处

第十七篇:实例分析(4)--初探WDDM驱动学习笔记(十一)

感觉有必要把 KMDDOD_INITIALIZATION_DATA 中的这些函数指针的意思解释一下, 以便进一步的深入代码. DxgkDdiAddDevice 前面已经说过, 这个函数的主要内容是,将BASIC_DISPLAY_DRIVER实例指针存在context中, 以便后期使用, 支持多实例. DxgkDdiStartDevice 取得设备信息, 往注册表中加入内容, 从POST设备中获取FRAME BUFFER以及相关信息(DxgkCbAcquirePostDisplayOwnershi

Linux System Programming 学习笔记(十一) 时间

1. 内核提供三种不同的方式来记录时间: Wall time (or real time):actual time and date in the real world Process time:the time that a process spends executing on a processor 包括用户时间user time 和 系统时间system time Monotonic time:use the system's uptime (time since boot) for t

Boost Thread学习笔记二

除了thread,boost::thread另一个重要组成部分是mutex,以及工作在mutex上的boost::mutex::scoped_lock.condition和barrier,这些都是为实现线程同步提供的. mutexboost提供的mutex有6种:boost::mutexboost::try_mutexboost::timed_mutexboost::recursive_mutexboost::recursive_try_mutexboost::recursive_timed_m

Boost Thread学习笔记

thread自然是boost::thread库的主 角,但thread类的实现总体上是比较简单的,前面已经说过,thread只是一个跨平台的线程封装库,其中按照所使用的编译选项的不同,分别决定使用 Windows线程API还是pthread,或者Macintosh Carbon平台的thread实现.以下只讨论Windows,即使用 BOOST_HAS_WINTHREADS的情况.thread类提供了两种构造函数:thread::thread()thread::thread(const func