软件环境: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
然后保存,接下来就可以编译了。