软件环境: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
然后保存,接下来就可以编译了。RT-Thread 学习笔记(十一)--- 开启基于RTGUI的LCD显示功能
原文地址:http://blog.csdn.net/aping_cs_dn/article/details/44939777