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