1、 补注
a) 硬件,打通通讯通道
若学习者购买了学习板,通常可以在学习板提供的示例代码中找到LCD的相关驱动代码,基本上,这里的驱动的所有代码都可以从里面找到。
从上面的示意图可见,MCU要在LCD上显示内容,需要经过:
1、 Core
2、 Dbus,SystemBus
3、 Bus Matrix
4、 FSMC
5、 SSD1963
6、 LCM
驱动LCD,就要相应地将这些通道开启,初始化,只要其中一个环节未打通,就不可能成功点亮LCD屏。
首先是到SSD1963的引脚,虽然说,MCU与SSD1963显示芯片的连接是通过FSMC方式,但由于FSMC与GPIO是共用引脚的,因此,需要先打开相应的GPIO。
代码:
void GPIO_INIT(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOD| RCC_APB2Periph_GPIOE| RCC_APB2Periph_GPIOF , ENABLE); }
其次,就是FSMC了,这部分的代码,可以直接从学习板的示例代码中复制出来。
然后,是SSD1963显示芯片的初始化代码,也可以直接从学习板的示例代码中复制。
SSD1963,具体的信息可以查看学习板中带的PDF文件,以下是部分摘录:
1 GENERAL DESCRIPTION
SSD1963 is a display controller of 1215K byte frame buffer to support up to 864 x 480 x 24bit graphics content. It also equips parallel MCU interfaces in different bus width to receive graphics data and command from MCU. Its display interface supports common RA M-less LCD driver of color depth up to 24 bit-per-pixel.
2 FEATURES
• Display feature − Built-in 1215K bytes frame buffer. Support up to 864 x 480 at 24bpp display − Support TFT 18/24-bit generic RGB interface panel − Support 8-bit serial RGB interface − Hardware rotation of 0, 90, 180, 270 degree − Hardware display mirroring − Hardware windowing − Programmable brightness, contrast and saturation control − Dynamic Backlight Control (DBC) via PWM signal • MCU connectivity − 8/9/16/18/24-bit MCU interface − Tearing effect signal • I/O Connectivity − 4 GPIO pins • Built-in clock generator • Deep sleep mode for power saving • Core supply power (VDDPLL and VDDD): 1.2V±0.1V • I/O supply power(VDDIO): 1.65V to 3.6V • LCD interface supply power (VDDLCD): 1.65V to 3.6V |
可以看到,这款芯片内建1215K字节帧缓存,最大支持分辨率864x 480,真24位彩色的LCD屏
如果要提高显示效果,可考虑使用帧缓存(framebuffer)。RTGUI支持帧缓存,以后有时间,再更新驱动。
为了显示LCD屏上的每一个像素点,SSD1963提供了很多命令,如:
设置作图坐标,我们会使用 0x2A,0x2B来确定一个矩形区域。
然后开始写入数据之前,调用0x2C来通知SSD1963。同样,可以发送命令0x2E来通知SSD1963,将当前点的像素颜色值放到数据总线上,MCU随后就可以通过FSMC来读取。
其它更多内容,请查看PDF文件。
奋斗板V3的4.3” LCD屏,用的是翰彩4.3” ColorTFT-LCD Module,在相关资料文件夹中,也有相应的PDF文档。硬件连接只要按文档说明正确对应即可。
LCM型号(Model)是 HSD043I9W1-A**
完成以上,整个通讯通道就被打通,LCD屏才能成功点亮。
b) GUI基础函数
RTGUI与UCGUI,其底层的绘图函数都只有很少的几个,复杂图形及文字等显示操作,都在这些功能简单的函数基础上进行的扩展。
RTGUI的五个基本绘图函数(未使用frame buffer的情况下):
/** * graphic operations */ struct rt_device_graphic_ops { void (*set_pixel) (const char *pixel, int x, int y); void (*get_pixel) (char *pixel, int x, int y); void (*draw_hline)(const char *pixel, int x1, int x2, int y); void (*draw_vline)(const char *pixel, int x, int y1, int y2); void (*blit_line) (const char *pixel, int x, int y, rt_size_t size); };
在RTGUI中,把显示驱动作为一个设备来注册。以上五个函数则保存到通用设备的私有数据段。再将显示设备注册为“lcd”。
其中基类rt_devicer的control方法,我们返回了一些信息,如屏幕大小,色彩格式定义等。而其它几个方法其实都是空方法,因为LCD驱动不提供这些功能。
如下:
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 = &ssd1963_ops; GPIO_INIT(); FSMC_LCD_Init(); LCD_INIT(); lcd_clear(); /* register graphic device driver */ rt_device_register(&_lcd_device, "lcd", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE); }
………… #ifdef RT_USING_RTGUI { extern void rtgui_system_server_init(void); 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 */ rtgui_touch_hw_init(); /* re-init device driver */ rt_device_init_all(); /* find lcd device */ lcd = rt_device_find("lcd"); /* set lcd device as rtgui graphic driver */ rtgui_graphic_set_device(lcd); /* init rtgui system server */ rtgui_system_server_init(); } #endif /* #ifdef RT_USING_RTGUI */ } int rt_application_init() { …………
/* * File : driver.h * This file is part of RTGUI in RT-Thread RTOS * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rt-thread.org/license/LICENSE * * Change Logs: * Date Author Notes * 2009-10-04 Bernard first version */ #ifndef __RTGUI_DRIVER_H__ #define __RTGUI_DRIVER_H__ #include <rtgui/list.h> #include <rtgui/color.h> struct rtgui_graphic_driver_ops { /* set and get pixel in (x, y) */ void (*set_pixel)(rtgui_color_t *c, int x, int y); void (*get_pixel)(rtgui_color_t *c, int x, int y); void (*draw_hline)(rtgui_color_t *c, int x1, int x2, int y); void (*draw_vline)(rtgui_color_t *c, int x , int y1, int y2); /* draw raw hline */ void (*draw_raw_hline)(rt_uint8_t *pixels, int x1, int x2, int y); }; struct rtgui_graphic_driver { /* pixel format and byte per pixel */ rt_uint8_t pixel_format; rt_uint8_t bits_per_pixel; rt_uint16_t pitch; /* screen width and height */ rt_uint16_t width; rt_uint16_t height; /* framebuffer address and ops */ volatile rt_uint8_t *framebuffer; rt_device_t device; const struct rtgui_graphic_driver_ops *ops; }; ……………… ……………… ………………
/* * File : driver.c * This file is part of RTGUI in RT-Thread RTOS * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.rt-thread.org/license/LICENSE * * Change Logs: * Date Author Notes * 2009-10-04 Bernard first version */ #include <rtthread.h> #include <rtgui/driver.h> struct rtgui_graphic_driver _driver; ……………… ……………… ……………… rt_err_t rtgui_graphic_set_device(rt_device_t device) { rt_err_t result; struct rt_device_graphic_info info; /* get framebuffer address */ result = rt_device_control(device, RTGRAPHIC_CTRL_GET_INFO, &info); if (result != RT_EOK) { /* get device information failed */ return -RT_ERROR; } /* initialize framebuffer driver */ _driver.device = device; _driver.pixel_format = info.pixel_format; _driver.bits_per_pixel = info.bits_per_pixel; _driver.width = info.width; _driver.height = info.height; _driver.pitch = _driver.width * _driver.bits_per_pixel / 8; _driver.framebuffer = info.framebuffer; if (info.framebuffer != RT_NULL) { /* is a frame buffer device */ _driver.ops = rtgui_framebuffer_get_ops(_driver.pixel_format); } else { /* is a pixel device */ _driver.ops = rtgui_pixel_device_get_ops(_driver.pixel_format); } return RT_EOK; } ……………… ……………… ………………