zoukankan      html  css  js  c++  java
  • STM32 + RT Thread OS 学习笔记[四]

    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);
    }


    作为新手,我就因为没打开GPIO,这么一句代码的问题,查了一个月才找到,杯具得不能再杯具了……

    其次,就是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);
    };


    分别是:

    • l  画一个点
    • l  取一个点的色彩值
    • l  画一条水平线
    • l  画一条垂直线
    • l  画一条水平线,水平线上每个点的色彩值在“数组”中指定

    在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);
    }


    在application.c中,RTGUI取得设备“lcd”,并将它转化为rtgui_graphic_driver类,如下:

    …………
    #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;
    }
    ………………
    ………………
    ………………


    其它代码就不列出来了,最终实现的是GUI色彩定义与硬件的色彩定义分隔,在RTGUI中统一一种方式定义色彩,而不用关心具体LCD硬件对色彩的定义。不过,对于函数 draw_raw_hline()来说,需要手工转换色彩。

  • 相关阅读:
    SSH框架的简单上传功能的实现
    笔记:《C++ Primer》第3章
    笔记:《C++ Primer》第1章和第2章
    tcl脚本学习十三:列表命令集
    tcl脚本学习十二: upvar的学习
    tcl脚本学习十一:proc应用 (带默认参数)
    tcl脚本学习十:proc 子函数的使用
    tcl脚本学习八:while循环的使用
    tcl脚本学习九:for循环的学习
    tcl脚本学习七:if的学习
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3188538.html
Copyright © 2011-2022 走看看