【转】STM32 + RT Thread OS 学习笔记[四]

[复制链接]
 楼主| sunmeat 发表于 2015-1-22 09:55 | 显示全部楼层 |阅读模式

1、  补注

a)      硬件,打通通讯通道

若学习者购买了学习板,通常可以在学习板提供的示例代码中找到LCD的相关驱动代码,基本上,这里的驱动的所有代码都可以从里面找到。

图像 082.png
图像 083.png


 楼主| sunmeat 发表于 2015-1-22 10:01 | 显示全部楼层
从上面的示意图可见,MCU要在LCD上显示内容,需要经过:
1、  Core
2、  Dbus,SystemBus
3、  Bus Matrix
4、  FSMC
5、  SSD1963
6、  LCM

 楼主| sunmeat 发表于 2015-1-22 10:03 | 显示全部楼层
驱动LCD,就要相应地将这些通道开启,初始化,只要其中一个环节未打通,就不可能成功点亮LCD屏。

首先是到SSD1963的引脚,虽然说,MCU与SSD1963显示芯片的连接是通过FSMC方式,但由于FSMC与GPIO是共用引脚的,因此,需要先打开相应的GPIO。
代码:
  1. void GPIO_INIT(void)
  2. {
  3.     RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC
  4.                         | RCC_APB2Periph_GPIOD| RCC_APB2Periph_GPIOE| RCC_APB2Periph_GPIOF , ENABLE);
  5. }
作为新手,我就因为没打开GPIO,这么一句代码的问题,查了一个月才找到,杯具得不能再杯具了……

其次,就是FSMC了,这部分的代码,可以直接从学习板的示例代码中复制出来。
 楼主| sunmeat 发表于 2015-1-22 10:07 | 显示全部楼层
然后,是SSD1963显示芯片的初始化代码,也可以直接从学习板的示例代码中复制。
SSD1963,具体的信息可以查看学习板中带的PDF文件,以下是部分摘录:
图像 084.png
图像 085.png
可以看到,这款芯片内建1215K字节帧缓存,最大支持分辨率864x 480,真24位彩色的LCD屏
如果要提高显示效果,可考虑使用帧缓存(framebuffer)。RTGUI支持帧缓存,以后有时间,再更新驱动。
itachier 发表于 2015-1-22 10:08 | 显示全部楼层
:handshake
 楼主| sunmeat 发表于 2015-1-22 10:09 | 显示全部楼层
为了显示LCD屏上的每一个像素点,SSD1963提供了很多命令,如:
图像 086.png
设置作图坐标,我们会使用 0x2A,0x2B来确定一个矩形区域。
然后开始写入数据之前,调用0x2C来通知SSD1963。同样,可以发送命令0x2E来通知SSD1963,将当前点的像素颜色值放到数据总线上,MCU随后就可以通过FSMC来读取。

其它更多内容,请查看PDF文件。
 楼主| sunmeat 发表于 2015-1-22 10:31 | 显示全部楼层

奋斗板V3的4.3” LCD屏,用的是翰彩4.3” ColorTFT-LCD Module,在相关资料文件夹中,也有相应的PDF文档。硬件连接只要按文档说明正确对应即可。
LCM型号(Model)是 HSD043I9W1-A**

完成以上,整个通讯通道就被打通,LCD屏才能成功点亮。
 楼主| sunmeat 发表于 2015-1-22 10:31 | 显示全部楼层
b)      GUI基础函数
RTGUI与UCGUI,其底层的绘图函数都只有很少的几个,复杂图形及文字等显示操作,都在这些功能简单的函数基础上进行的扩展。
RTGUI的五个基本绘图函数(未使用frame buffer的情况下):
  1. /**
  2. * graphic operations
  3. */
  4. struct rt_device_graphic_ops
  5. {
  6.     void (*set_pixel) (const char *pixel, int x, int y);
  7.     void (*get_pixel) (char *pixel, int x, int y);

  8.     void (*draw_hline)(const char *pixel, int x1, int x2, int y);
  9.     void (*draw_vline)(const char *pixel, int x, int y1, int y2);

  10.     void (*blit_line) (const char *pixel, int x, int y, rt_size_t size);
  11. };
分别是:
l  画一个点
l  取一个点的色彩值
l  画一条水平线
l  画一条垂直线
l  画一条水平线,水平线上每个点的色彩值在“数组”中指定
 楼主| sunmeat 发表于 2015-1-22 10:32 | 显示全部楼层
在RTGUI中,把显示驱动作为一个设备来注册。以上五个函数则保存到通用设备的私有数据段。再将显示设备注册为“lcd”。
其中基类rt_devicer的control方法,我们返回了一些信息,如屏幕大小,色彩格式定义等。而其它几个方法其实都是空方法,因为LCD驱动不提供这些功能。
如下:
  1. void rt_hw_lcd_init(void)
  2. {

  3.     /* register lcd device */
  4.     _lcd_device.type  = RT_Device_Class_Graphic;
  5.     _lcd_device.init  = lcd_init;
  6.     _lcd_device.open  = lcd_open;
  7.     _lcd_device.close = lcd_close;
  8.     _lcd_device.control = lcd_control;
  9.     _lcd_device.read  = RT_NULL;
  10.     _lcd_device.write = RT_NULL;

  11.     _lcd_device.user_data = &ssd1963_ops;
  12.     GPIO_INIT();
  13.     FSMC_LCD_Init();
  14.     LCD_INIT();
  15.     lcd_clear();

  16.     /* register graphic device driver */
  17.     rt_device_register(&_lcd_device, "lcd",
  18.         RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_STANDALONE);
  19. }
 楼主| sunmeat 发表于 2015-1-22 10:33 | 显示全部楼层
在application.c中,RTGUI取得设备“lcd”,并将它转化为rtgui_graphic_driver类,如下:
  1. …………
  2. #ifdef RT_USING_RTGUI
  3.     {
  4.         extern void rtgui_system_server_init(void);
  5.         extern void rt_hw_lcd_init();
  6.         extern void rtgui_touch_hw_init(void);

  7.         rt_device_t lcd;

  8.         /* init lcd */
  9.         rt_hw_lcd_init();

  10.         /* init touch panel */
  11.         rtgui_touch_hw_init();

  12.         /* re-init device driver */
  13.         rt_device_init_all();

  14.         /* find lcd device */
  15.         lcd = rt_device_find("lcd");

  16.         /* set lcd device as rtgui graphic driver */
  17.        <strong> rtgui_graphic_set_device(lcd);</strong>

  18.         /* init rtgui system server */
  19.         rtgui_system_server_init();
  20.     }
  21. #endif /* #ifdef RT_USING_RTGUI */
  22. }

  23. int rt_application_init()
  24. {
  25. …………
 楼主| sunmeat 发表于 2015-1-22 10:33 | 显示全部楼层
  1. /*
  2. * File      : driver.h
  3. * This file is part of RTGUI in RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date           Author       Notes
  12. * 2009-10-04     Bernard      first version
  13. */
  14. #ifndef __RTGUI_DRIVER_H__
  15. #define __RTGUI_DRIVER_H__

  16. #include <rtgui/list.h>
  17. #include <rtgui/color.h>

  18. <strong>struct rtgui_graphic_driver_ops</strong>
  19. {
  20.     /* set and get pixel in (x, y) */
  21.     void (*set_pixel)(rtgui_color_t *c, int x, int y);
  22.     void (*get_pixel)(rtgui_color_t *c, int x, int y);

  23.     void (*draw_hline)(rtgui_color_t *c, int x1, int x2, int y);
  24.     void (*draw_vline)(rtgui_color_t *c, int x , int y1, int y2);

  25.     /* draw raw hline */
  26.     void (*<strong>draw_raw_hline</strong>)(rt_uint8_t *pixels, int x1, int x2, int y);
  27. };

  28. <strong>struct rtgui_graphic_driver</strong>
  29. {
  30.     /* pixel format and byte per pixel */
  31.     rt_uint8_t pixel_format;
  32.     rt_uint8_t bits_per_pixel;
  33.     rt_uint16_t pitch;

  34.     /* screen width and height */
  35.     rt_uint16_t width;
  36.     rt_uint16_t height;

  37.     /* framebuffer address and ops */
  38.     volatile rt_uint8_t *framebuffer;
  39.     rt_device_t device;
  40.     <strong>const struct rtgui_graphic_driver_ops *ops;</strong>
  41. };
  42. ………………
  43. ………………
  44. ………………
 楼主| sunmeat 发表于 2015-1-22 10:33 | 显示全部楼层
  1. /*
  2. * File      : driver.c
  3. * This file is part of RTGUI in RT-Thread RTOS
  4. * COPYRIGHT (C) 2006 - 2009, RT-Thread Development Team
  5. *
  6. * The license and distribution terms for this file may be
  7. * found in the file LICENSE in this distribution or at
  8. * http://www.rt-thread.org/license/LICENSE
  9. *
  10. * Change Logs:
  11. * Date           Author       Notes
  12. * 2009-10-04     Bernard      first version
  13. */
  14. #include <rtthread.h>
  15. #include <rtgui/driver.h>

  16. struct rtgui_graphic_driver _driver;

  17. ………………
  18. ………………
  19. ………………
  20. rt_err_t rtgui_graphic_set_device(rt_device_t device)
  21. {
  22.     rt_err_t result;
  23.     struct rt_device_graphic_info info;

  24.     /* get framebuffer address */
  25.     result = rt_device_control(device, RTGRAPHIC_CTRL_GET_INFO, &info);
  26.     if (result != RT_EOK)
  27.     {
  28.         /* get device information failed */
  29.         return -RT_ERROR;
  30.     }

  31.     /* initialize framebuffer driver */
  32.     _driver.device = device;
  33.     _driver.pixel_format = info.pixel_format;
  34.     _driver.bits_per_pixel = info.bits_per_pixel;
  35.     _driver.width = info.width;
  36.     _driver.height = info.height;
  37.     _driver.pitch = _driver.width * _driver.bits_per_pixel / 8;
  38.     _driver.framebuffer = info.framebuffer;

  39.     if (info.framebuffer != RT_NULL)
  40.     {
  41.         /* is a frame buffer device */
  42.         _driver.ops = rtgui_framebuffer_get_ops(_driver.pixel_format);
  43.     }
  44.     else
  45.     {
  46.         /* is a pixel device */
  47.         <strong>_driver.ops = rtgui_pixel_device_get_ops(_driver.pixel_format);</strong>
  48.     }

  49.     return RT_EOK;
  50. }
  51. ………………
  52. ………………
  53. ………………
 楼主| sunmeat 发表于 2015-1-22 10:34 | 显示全部楼层
其它代码就不列出来了,最终实现的是GUI色彩定义与硬件的色彩定义分隔,在RTGUI中统一一种方式定义色彩,而不用关心具体LCD硬件对色彩的定义。不过,对于函数draw_raw_hline()来说,需要手工转换色彩。【感觉这篇就是讲的液晶,没什么用】
mmuuss586 发表于 2015-1-22 18:57 | 显示全部楼层

学习下;
yinhaix 发表于 2015-6-2 17:37 | 显示全部楼层
您需要登录后才可以回帖 登录 | 注册

本版积分规则

208

主题

2132

帖子

13

粉丝
快速回复 在线客服 返回列表 返回顶部