5 缺少常用的LCD驱动软件包

发布于 2021-03-13 15:22:26

RTTStudio创建的工程现在是不是还没有lcd相关的驱动啊,对于开发板的LCD支持也只有一部分,我用的STM32F407的板子就没有,这款应该说是32里很主流的一款片子了吧
当然可能针对每款显示屏都开发驱动太过繁琐,所以能不能出一个LCD驱动开发的教程之类的,感觉rtt里留的显示驱动接口不是很明了(当然也说明我水平一般。。),但还是希望能有个稍微详细点的说明指导

查看更多

关注者
0
被浏览
260
Aurora_zk
Aurora_zk 2021-03-16

我采用的是正点原子的F767 屏幕使用的是4.3寸的RGB屏,使用成功
我发现在stm32是有LCD设备的
在Kconfig文件中添加

    config BSP_USING_LCD
        bool "Enable LCD"
        select BSP_USING_LTDC//这是RGB屏中的,TFT屏可以不写
        select BSP_USING_SDRAM//407应该使用BSP_USING_SRAM
        default n

下面是我配置的一些过程需要根据你的实际情况改写,最后附上一些自己根据正点原子的LCD驱动改写的一些显示函数

CUBEMX设置

调试I/O配置

PB5在显示屏中作为背光使用
image-20210313164513522.png

SDRAM配置

在使用显示屏时,用到了SRAM,SDRAM通过FMC接口,与STM32相连。关于FMC与SDRAM不做过多解释,在这仅仅讲解如何通过STM32CubeMX进行配置。SDRAM的配置如下图所示。需要特别注意的是Write recovery time选项,在正点原子中的数值是2。

image-20210313165157122.png

在对SDRAM的参数选项配置完成后需要改变默认的I/O从而与阿波罗的开发板相对应。更改后的I/O如下图

image-20210313165546488.png

LTDC配置

RGBLCD用的是LTDC,LTDC除了自身外,还需要使能后对时钟进行配置。LTDC的参数配置如下(参数配置跟显示屏有关,可以在正点原子例程中找到对应参数)。

image-20210313165756673.png
image-20210313165903889.png
eeadfeca5eac6fdfca4361ae2907dbdd.png

DMA2D使能,设置时钟

image-20210313170819401.png

只改写了部分显示函数,如有需要可自行根据响应格式修改,其中font.h完全复制正点原子的未修改

lcd.h
/*
 * @Author: Aurora-zk
 * @Date: 2021-03-11 10:29:32
 * @LastEditors: Aurora-zk
 * @LastEditTime: 2021-03-13 17:53:06
 * @contact: pk-ing@nyist.edu.cn
 * @FilePath: \stm32f767-atk-apollo-lcd\board\Custom_Module\lcd\lcd.h
 */

#ifndef __LCD_H
#define __LCD_H        
#include "main.h"     
#include "stdlib.h" 

struct drv_lcd_device
{
    struct rt_device parent;

    struct rt_device_graphic_info lcd_info;

    struct rt_semaphore lcd_lock;

    /* 0:front_buf is being used 1: back_buf is being used*/
    rt_uint8_t cur_buf;
    rt_uint8_t *front_buf;
    rt_uint8_t *back_buf;
};


struct lcd_dev
{              
    rt_uint16_t width;
    rt_uint16_t height;
    rt_uint8_t  dir;
    rt_uint8_t *framebuffer; 
};       

extern rt_uint16_t  POINT_COLOR;
extern rt_uint16_t  BACK_COLOR; 

//显示方向定义,以屏幕PCB丝印方向为正方向
#define RtoL  0         //从右到左
#define UtoD  1         //从上到下
#define LtoR  2         //从左到右
#define DtoU  3         //从下到上



//画笔颜色
#define WHITE              0xFFFF
#define BLACK              0x0000      
#define BLUE              0x001F  
#define BRED             0XF81F
#define GRED              0XFFE0
#define GBLUE             0X07FF
#define RED                0xF800
#define MAGENTA            0xF81F
#define GREEN              0x07E0
#define CYAN               0x7FFF
#define YELLOW             0xFFE0
#define BROWN              0XBC40 //棕色
#define BRRED              0XFC07 //棕红色
#define GRAY               0X8430 //灰色
//GUI颜色

#define DARKBLUE           0X01CF    //深蓝色
#define LIGHTBLUE           0X7D7C    //浅蓝色  
#define GRAYBLUE            0X5458 //灰蓝色


#define LIGHTGREEN          0X841F 
#define LGRAY              0XC618 

#define LGRAYBLUE        0XA651 
#define LBBLUE           0X2B12
void LCD_Update(void);
void LCD_Display_Dir(rt_uint8_t dir);
void LCD_Clear(rt_uint16_t color);
void LCD_Fast_DrawPoint(rt_uint16_t x, rt_uint16_t y,rt_uint16_t color);
void LCD_DrawPoint(rt_uint16_t x, rt_uint16_t y);
void LCD_ShowChar(rt_uint16_t x,rt_uint16_t y,rt_uint8_t num,rt_uint8_t size,rt_uint8_t mode);
void LCD_Draw_Circle(rt_uint16_t x0,rt_uint16_t y0,rt_uint8_t r);

#endif
lcd.c
/*
 * @Author: Aurora-zk
 * @Date: 2021-03-11 10:19:51
 * @LastEditors: Aurora-zk
 * @LastEditTime: 2021-03-13 17:54:28
 * @contact: pk-ing@nyist.edu.cn
 * @FilePath: \stm32f767-atk-apollo-lcd\board\Custom_Module\lcd\lcd.c
 */
#include "lcd.h"
#include "font.h"  
#include <lcd_port.h>

rt_uint16_t POINT_COLOR = 0x0000;
rt_uint16_t BACK_COLOR = 0xFFFF;  

struct lcd_dev lcddev;
struct drv_lcd_device *lcd;

void LCD_Update(void)
{
    lcd->parent.control(&lcd->parent, RTGRAPHIC_CTRL_RECT_UPDATE, RT_NULL);
}

void LCD_Display_Dir(rt_uint8_t dir)
{
    lcddev.dir = dir;
    lcddev.framebuffer = lcd->lcd_info.framebuffer;
    if (lcddev.dir == RtoL || lcddev.dir == LtoR){
        lcddev.width = lcd->lcd_info.width;
        lcddev.height = lcd->lcd_info.height;
    }
    else if (lcddev.dir == UtoD || lcddev.dir == DtoU){
        
        lcddev.width = lcd->lcd_info.height;
        lcddev.height = lcd->lcd_info.width;
    }
}


void LCD_Clear(rt_uint16_t color)
{
    for (int i = 0; i < LCD_BUF_SIZE / 2; i++)
    {
        lcddev.framebuffer[2 * i] = color % 16;
        lcddev.framebuffer[2 * i + 1] = color / 16;
    }
    LCD_Update();
}

void LCD_Fast_DrawPoint(rt_uint16_t x, rt_uint16_t y,rt_uint16_t color)
{
    int i;
    
    if (lcddev.dir == RtoL){
        i = lcddev.width * y + x;
    }else if (lcddev.dir == UtoD){
        i = (lcddev.width - x - 1) * lcddev.height + y;
    }else if (lcddev.dir == LtoR){
        i = (lcddev.height - y) * lcddev.width - x - 1;
    }else if (lcddev.dir == DtoU){
        i = (x + 1) * lcddev.height - y - 1;
    }
    if (i > LCD_BUF_SIZE / 2){
        return;
    }
    lcddev.framebuffer[2 * i] = color % 16;
    lcddev.framebuffer[2 * i + 1] = color / 16;
}

void LCD_DrawPoint(rt_uint16_t x, rt_uint16_t y)
{
    LCD_Fast_DrawPoint(x, y, POINT_COLOR);
}

void LCD_ShowChar(rt_uint16_t x,rt_uint16_t y,rt_uint8_t num,rt_uint8_t size,rt_uint8_t mode)
{
    rt_uint8_t temp,t1,t;
    rt_uint16_t y0=y;
    rt_uint8_t csize=(size/8+((size%8)?1:0))*(size/2);
    num=num-' ';
    for(t=0;t<csize;t++)
    {   
        if(size==12)temp=asc2_1206[num][t];      
        else if(size==16)temp=asc2_1608[num][t];    
        else if(size==24)temp=asc2_2412[num][t];    
        else if(size==32)temp=asc2_3216[num][t];    
        else return;                            
        for(t1=0;t1<8;t1++)
        {                
            if(temp&0x80)LCD_Fast_DrawPoint(x,y,POINT_COLOR);
            else if(mode==0)LCD_Fast_DrawPoint(x,y,BACK_COLOR);
            temp<<=1;
            y++;
            if(y>=lcddev.height)return;        
            if((y-y0)==size)
            {
                y=y0;
                x++;
                if(x>=lcddev.width)return;    
                break;
            }
        }       
    }                            
}

void LCD_Draw_Circle(rt_uint16_t x0,rt_uint16_t y0,rt_uint8_t r)
{
    int a,b;
    int di;
    a=0;b=r;      
    di=3-(r<<1);           
    while(a<=b)
    {
        LCD_DrawPoint(x0+a,y0-b);            
        LCD_DrawPoint(x0+b,y0-a);               
        LCD_DrawPoint(x0+b,y0+a);                       
        LCD_DrawPoint(x0+a,y0+b);            
        LCD_DrawPoint(x0-a,y0+b);               
        LCD_DrawPoint(x0-b,y0+a);             
        LCD_DrawPoint(x0-a,y0-b);                     
        LCD_DrawPoint(x0-b,y0-a);                             
        a++;    
        if(di<0)di +=4*a+6;      
        else
        {
            di+=10+4*(a-b);   
            b--;
        }                             
    }
}                 

void lcd_test()
{
    lcd = (struct drv_lcd_device *)rt_device_find("lcd");
    LCD_Display_Dir(RtoL);
    LCD_Clear(WHITE);
    POINT_COLOR = BLUE;
    BACK_COLOR = WHITE;
    LCD_Draw_Circle(240,136,200);
    
    LCD_DrawPoint(1,1);
    
    LCD_ShowChar(240,136,'6',32,0);
    LCD_Update();
    rt_thread_mdelay(1000);
    LCD_ShowChar(240,136,'7',32,1);
    LCD_Update();
    
    LCD_Display_Dir(DtoU);
    rt_thread_mdelay(1000);
    LCD_DrawPoint(1,1);
    LCD_ShowChar(240,136,'?',32,0);
    LCD_Update();
}
INIT_APP_EXPORT(lcd_test);
4 个回答
tyustli
tyustli 2021-03-15
StackYuan
StackYuan 2021-03-15

可能走8080的LCD屏需要自己动手,大部分走SPI的屏幕基本上不需要自己写驱动了吧

cxhxy12345
cxhxy12345 2021-03-15

SPI本来就有底层的驱动写好的,每个厂家的芯片也有对应的驱动包提供。但你要在编写一个API接口对接底层的驱动,同时为上层的GUI提供一个接口。这样你就可以通过通用的GUI来绘制LCD显示界面了。但对不同的显示屏,需要修改的就是你的API函数。
建议你用PersimonUI,配合柿饼M3。全程用JS开发,简单快捷高效。

撰写答案

请登录后再发布答案,点击登录

发布
问题

分享
好友

手机
浏览

扫码手机浏览