打印
[STM32L5]

【STM32L562E-DK试用】5.使用FMC驱动LCD屏幕

[复制链接]
70|0
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
STM32L562E-DK板载了一块240x240的彩色LCD屏幕,这块屏幕是通过FMC连接的

FSMC(Flexible Static Memory Controller,可变静态存储控制器)是STM32系列采用的一种新型的存储器扩展技术,支持多种静态存储器类型,STM32通过FSMC可以与SRAM、ROM、PSRAM、NOR Flash和NANDFlash存储器的引脚直接相连,除了存储器之外也可以用来控制8080或6800接口的TFT-LCD屏幕

板载的这块屏幕型号是FRD154BP2902-D-CTQ,分辨率240x240,主控是ST7789H2-G4,通过8080接口连接,16位数据线

在官方库里有现成的驱动程序,不过现在先不使用官方驱动,先来自己实现一下这块屏幕的驱动,最后再介绍一下怎么使用官方驱动
打开STM32CubeMX,按照ST7789H2的时序要求配置FMC参数

当前时钟频率是110MHz,一个时钟周期是9.1ns,需要把时间要求都换算成时钟周期


LCD所接IO的作用如下

可以看到FMC中并没有控制区分命令和数据的专用引脚,使用了一个地址信号来替代,因此想要区分命令和数据时需要向FMC写入相应的地址,看一下FMC的地址分配


需要注意的是16位宽时地址位会左移一位,所以LCD接的A[0]实际要用bit1来写入,因此发送数据时要写入的地址是0x60000002,发送命令时要写入的地址是0x60000000,接下来实现发送命令和发送数据的方法
#define LCD_CMD_ADDR  0x60000000
#define LCD_DATA_ADDR 0x60000002
void LCD_WriteData(uint16_t data)
{
    *(__IO uint16_t *)LCD_DATA_ADDR = data;
}
void LCD_WriteCMD(uint16_t cmd)
{
    *(__IO uint16_t *)LCD_CMD_ADDR = cmd;
}
uint16_t ReadData(void)
{
    uint16_t data;
    data = *(__IO uint16_t *)LCD_DATA_ADDR;
    return data;
}
LCD初始化过程
void LCD_Init(void)
{
    LL_GPIO_ResetOutputPin(LCD_PWR_ON_GPIO_Port,LCD_PWR_ON_Pin);
   
    LL_GPIO_ResetOutputPin(LCD_RST_GPIO_Port,LCD_RST_Pin);
    LL_mDelay(1);
    LL_GPIO_SetOutputPin(LCD_RST_GPIO_Port,LCD_RST_Pin);
    LL_mDelay(120);
   
    LCD_WriteCMD(0x10);
    LL_mDelay(10);
    //软复位
    LCD_WriteCMD(0x01);
    LL_mDelay(200);
    LCD_WriteCMD(0x11);
    LL_mDelay(120);
    //屏幕方向 0竖 0xA0横 0xC0倒竖 0x60倒横
    LCD_WriteCMD(0x36);
    LCD_WriteData(0x00);
    //颜色格式 0x03 444 0x05 565 0x06 666
    LCD_WriteCMD(0x3A);
    LCD_WriteData(0x06);
    //反色显示
    LCD_WriteCMD(0x21);
    //列地址
    LCD_WriteCMD(0x2A);
    LCD_WriteData(0x00);
    LCD_WriteData(0x00);
    LCD_WriteData(0x00);
    LCD_WriteData(0xEF);
    //行地址
    LCD_WriteCMD(0x2B);
    LCD_WriteData(0x00);
    LCD_WriteData(0x00);
    LCD_WriteData(0x00);
    LCD_WriteData(0xEF);
    //颜色数据格式
    LCD_WriteCMD(0xB0);
    LCD_WriteData(0x00);
    LCD_WriteData(0xF1);
    //porch
    LCD_WriteCMD(0xB2);
    LCD_WriteData(0x0C);
    LCD_WriteData(0x0C);
    LCD_WriteData(0x00);
    LCD_WriteData(0x33);
    LCD_WriteData(0x33);
    //gate
    LCD_WriteCMD(0xB7);
    LCD_WriteData(0x35);
    //vcom
    LCD_WriteCMD(0xBB);
    LCD_WriteData(0x1F);
    //lcm
    LCD_WriteCMD(0xC0);
    LCD_WriteData(0x2C);
    //VDV and VRH Command Enable
    LCD_WriteCMD(0xC2);
    LCD_WriteData(0x01);
    LCD_WriteData(0xC3);
    //VDV
    LCD_WriteCMD(0xC4);
    LCD_WriteData(0x20);
    //Frame Rate Control in normal mode
    LCD_WriteCMD(0xC6);
    LCD_WriteData(0x0F);
    //Power
    LCD_WriteCMD(0xD0);
    LCD_WriteData(0xA4);
    LCD_WriteData(0xA1);
    //Positive Voltage Gamma
    LCD_WriteCMD(0xE0);
    LCD_WriteData(0xD0);
    LCD_WriteData(0x08);
    LCD_WriteData(0x11);
    LCD_WriteData(0x08);
    LCD_WriteData(0x0C);
    LCD_WriteData(0x15);
    LCD_WriteData(0x39);
    LCD_WriteData(0x33);
    LCD_WriteData(0x50);
    LCD_WriteData(0x36);
    LCD_WriteData(0x13);
    LCD_WriteData(0x14);
    LCD_WriteData(0x29);
    LCD_WriteData(0x2D);
    //Negative Voltage Gamma
    LCD_WriteCMD(0xE1);
    LCD_WriteData(0xD0);
    LCD_WriteData(0x08);
    LCD_WriteData(0x10);
    LCD_WriteData(0x08);
    LCD_WriteData(0x06);
    LCD_WriteData(0x06);
    LCD_WriteData(0x39);
    LCD_WriteData(0x44);
    LCD_WriteData(0x51);
    LCD_WriteData(0x0B);
    LCD_WriteData(0x16);
    LCD_WriteData(0x14);
    LCD_WriteData(0x2F);
    LCD_WriteData(0x31);
    //TE
    LCD_WriteCMD(0x35);
    LCD_WriteData(0x01);
    //开启显示
    LCD_WriteCMD(0x29);
}
测试方法,实现在屏幕上显示渐变色
void LCD_SetPos(uint16_t x,uint16_t y)
{
    LCD_WriteCMD(0x2A);
    LCD_WriteData((x>>8)&0xFF);
    LCD_WriteData(x&0xFF);
    LCD_WriteData(0x00);
    LCD_WriteData(0xEF);
   
    LCD_WriteCMD(0x2B);
    LCD_WriteData((y>>8)&0xFF);
    LCD_WriteData(y&0xFF);
    LCD_WriteData(0x00);
    LCD_WriteData(0xEF);
}

void LCD_Test(void)
{
    uint8_t r,g,b;
    uint16_t rgb[2];
    uint8_t i = 0;
    uint8_t j = 0;
    while(i < 240)
    {
        LCD_SetPos(0,i);
        if(i<63 || i >188)
        {
            r = 252 - 4*(i%63);
            g = 252 - r;
            b = 0;
        }
        else if(i<126)
        {
            g = 252 - 4*(i%63);
            b = 252 - g;
            r = 0;
        }
        else if(i<189)
        {
            b = 252 - 4*(i%63);
            r = 252 - b;
            g = 0;
        }
        rgb[0] = (r<<8)|g;
        rgb[1] = (b<<8);
        j = 0;
        LCD_WriteCMD(0x2C);
        while(j < 240)
        {
            LCD_WriteData(rgb[0]);
            LCD_WriteData(rgb[1]);
            j+=1;
        }
        i+=1;
    }
}
运行效果


LCD的基础驱动就完成了,后面就可以加上显示文字和图片的方法了,如果你不想自己花时间去弄,官方也提供了现成的代码,接下来介绍一下如何用官方提供的驱动控制这块屏幕
如果你使用了STM32CubeMX配置工程,打开C:\Users\你的用户名\STM32Cube\Repository\STM32Cube_FW_L5_V1.5.1,这里就是STM32CubeMX下载的L562的库

也可以到官网上下载https://www.st.com.cn/zh/embedded-software/stm32cubel5.html#overview或者github https://github.com/STMicroelectronics/STM32CubeL5
把Utilities文件夹和Drivers文件夹里的BSP文件夹拷贝到你的工程相应的文件夹下

并从例程里找个stm32l562e_discovery_conf.h放到BSP的STM32L562E-DK文件夹里

在Keil里新建3个分组,名字可以是其他的

添加文件

添加头文件路径

使用官方库提供的方法初始化LCD,官方库里已有FMC初始化方法,可以把工程生成的FMC初始化方法注释掉
#include "stm32l562e_discovery_lcd.h"
#include "stm32_lcd.h"
void LCDInit2(void)
{
    LCD_UTILS_Drv_t lcdDrv;
    /* Initialize the LCD */
    if (BSP_LCD_Init(0, LCD_ORIENTATION_PORTRAIT) != BSP_ERROR_NONE)
    {
        Error_Handler();
    }
    /* Set UTIL_LCD functions */
    lcdDrv.DrawBitmap  = BSP_LCD_DrawBitmap;
    lcdDrv.FillRGBRect = BSP_LCD_FillRGBRect;
    lcdDrv.DrawHLine   = BSP_LCD_DrawHLine;
    lcdDrv.DrawVLine   = BSP_LCD_DrawVLine;
    lcdDrv.FillRect    = BSP_LCD_FillRect;
    lcdDrv.GetPixel    = BSP_LCD_ReadPixel;
    lcdDrv.SetPixel    = BSP_LCD_WritePixel;
    lcdDrv.GetXSize    = BSP_LCD_GetXSize;
    lcdDrv.GetYSize    = BSP_LCD_GetYSize;
    lcdDrv.SetLayer    = BSP_LCD_SetActiveLayer;
    lcdDrv.GetFormat   = BSP_LCD_GetFormat;
    UTIL_LCD_SetFuncDriver(&lcdDrv);
    /* Clear the LCD */
    UTIL_LCD_Clear(UTIL_LCD_COLOR_WHITE);
    BSP_LCD_DisplayOn(0);
    UTIL_LCD_SetTextColor(UTIL_LCD_COLOR_BLUE);
    UTIL_LCD_SetBackColor(UTIL_LCD_COLOR_WHITE);
    UTIL_LCD_SetFont(&Font24);
    UTIL_LCD_DisplayStringAt(0, 80, (uint8_t *)"STM32L562E-DK", CENTER_MODE);
    UTIL_LCD_DisplayStringAt(0, 120, (uint8_t *)"LCD Test", CENTER_MODE);
    UTIL_LCD_DisplayStringAt(0, 160, (uint8_t *)"yuyy1989", CENTER_MODE);
}
运行效果

官方库提供了划线画图显示文字的方法,有兴趣的可以研究一下,这里就先不展开了

最后附上屏幕和ST7789H2的数据手册 FRD154BP2902-D-CTQ.pdf (1.34 MB) ST7789H2.pdf (3.01 MB)

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

认证:同飞软件研发工程师
简介:制冷系统单片机软件开发,使用PID控制温度

156

主题

756

帖子

7

粉丝