返回列表 发新帖我要提问本帖赏金: 30.00元(功能说明)

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

[复制链接]
1950|3
 楼主| yuyy1989 发表于 2025-1-24 17:43 | 显示全部楼层 |阅读模式
STM32L562E-DK板载了一块240x240的彩色LCD屏幕,这块屏幕是通过FMC连接的
微信截图_20250123113432.png
FSMC(Flexible Static Memory Controller,可变静态存储控制器)是STM32系列采用的一种新型的存储器扩展技术,支持多种静态存储器类型,STM32通过FSMC可以与SRAM、ROM、PSRAM、NOR Flash和NANDFlash存储器的引脚直接相连,除了存储器之外也可以用来控制8080或6800接口的TFT-LCD屏幕
微信截图_20250123113732.png
板载的这块屏幕型号是FRD154BP2902-D-CTQ,分辨率240x240,主控是ST7789H2-G4,通过8080接口连接,16位数据线
微信截图_20250124173438.png
在官方库里有现成的驱动程序,不过现在先不使用官方驱动,先来自己实现一下这块屏幕的驱动,最后再介绍一下怎么使用官方驱动
打开STM32CubeMX,按照ST7789H2的时序要求配置FMC参数
微信截图_20250123160229.png
当前时钟频率是110MHz,一个时钟周期是9.1ns,需要把时间要求都换算成时钟周期

微信截图_20250124173228.png
LCD所接IO的作用如下
微信截图_20250123170244.png
可以看到FMC中并没有控制区分命令和数据的专用引脚,使用了一个地址信号来替代,因此想要区分命令和数据时需要向FMC写入相应的地址,看一下FMC的地址分配
微信截图_20250123171720.png
微信截图_20250123171753.png
需要注意的是16位宽时地址位会左移一位,所以LCD接的A[0]实际要用bit1来写入,因此发送数据时要写入的地址是0x60000002,发送命令时要写入的地址是0x60000000,接下来实现发送命令和发送数据的方法
  1. #define LCD_CMD_ADDR  0x60000000
  2. #define LCD_DATA_ADDR 0x60000002
  3. void LCD_WriteData(uint16_t data)
  4. {
  5.     *(__IO uint16_t *)LCD_DATA_ADDR = data;
  6. }
  7. void LCD_WriteCMD(uint16_t cmd)
  8. {
  9.     *(__IO uint16_t *)LCD_CMD_ADDR = cmd;
  10. }
  11. uint16_t ReadData(void)
  12. {
  13.     uint16_t data;
  14.     data = *(__IO uint16_t *)LCD_DATA_ADDR;
  15.     return data;
  16. }
LCD初始化过程
  1. void LCD_Init(void)
  2. {
  3.     LL_GPIO_ResetOutputPin(LCD_PWR_ON_GPIO_Port,LCD_PWR_ON_Pin);
  4.    
  5.     LL_GPIO_ResetOutputPin(LCD_RST_GPIO_Port,LCD_RST_Pin);
  6.     LL_mDelay(1);
  7.     LL_GPIO_SetOutputPin(LCD_RST_GPIO_Port,LCD_RST_Pin);
  8.     LL_mDelay(120);
  9.    
  10.     LCD_WriteCMD(0x10);
  11.     LL_mDelay(10);
  12.     //软复位
  13.     LCD_WriteCMD(0x01);
  14.     LL_mDelay(200);
  15.     LCD_WriteCMD(0x11);
  16.     LL_mDelay(120);
  17.     //屏幕方向 0竖 0xA0横 0xC0倒竖 0x60倒横
  18.     LCD_WriteCMD(0x36);
  19.     LCD_WriteData(0x00);
  20.     //颜色格式 0x03 444 0x05 565 0x06 666
  21.     LCD_WriteCMD(0x3A);
  22.     LCD_WriteData(0x06);
  23.     //反色显示
  24.     LCD_WriteCMD(0x21);
  25.     //列地址
  26.     LCD_WriteCMD(0x2A);
  27.     LCD_WriteData(0x00);
  28.     LCD_WriteData(0x00);
  29.     LCD_WriteData(0x00);
  30.     LCD_WriteData(0xEF);
  31.     //行地址
  32.     LCD_WriteCMD(0x2B);
  33.     LCD_WriteData(0x00);
  34.     LCD_WriteData(0x00);
  35.     LCD_WriteData(0x00);
  36.     LCD_WriteData(0xEF);
  37.     //颜色数据格式
  38.     LCD_WriteCMD(0xB0);
  39.     LCD_WriteData(0x00);
  40.     LCD_WriteData(0xF1);
  41.     //porch
  42.     LCD_WriteCMD(0xB2);
  43.     LCD_WriteData(0x0C);
  44.     LCD_WriteData(0x0C);
  45.     LCD_WriteData(0x00);
  46.     LCD_WriteData(0x33);
  47.     LCD_WriteData(0x33);
  48.     //gate
  49.     LCD_WriteCMD(0xB7);
  50.     LCD_WriteData(0x35);
  51.     //vcom
  52.     LCD_WriteCMD(0xBB);
  53.     LCD_WriteData(0x1F);
  54.     //lcm
  55.     LCD_WriteCMD(0xC0);
  56.     LCD_WriteData(0x2C);
  57.     //VDV and VRH Command Enable
  58.     LCD_WriteCMD(0xC2);
  59.     LCD_WriteData(0x01);
  60.     LCD_WriteData(0xC3);
  61.     //VDV
  62.     LCD_WriteCMD(0xC4);
  63.     LCD_WriteData(0x20);
  64.     //Frame Rate Control in normal mode
  65.     LCD_WriteCMD(0xC6);
  66.     LCD_WriteData(0x0F);
  67.     //Power
  68.     LCD_WriteCMD(0xD0);
  69.     LCD_WriteData(0xA4);
  70.     LCD_WriteData(0xA1);
  71.     //Positive Voltage Gamma
  72.     LCD_WriteCMD(0xE0);
  73.     LCD_WriteData(0xD0);
  74.     LCD_WriteData(0x08);
  75.     LCD_WriteData(0x11);
  76.     LCD_WriteData(0x08);
  77.     LCD_WriteData(0x0C);
  78.     LCD_WriteData(0x15);
  79.     LCD_WriteData(0x39);
  80.     LCD_WriteData(0x33);
  81.     LCD_WriteData(0x50);
  82.     LCD_WriteData(0x36);
  83.     LCD_WriteData(0x13);
  84.     LCD_WriteData(0x14);
  85.     LCD_WriteData(0x29);
  86.     LCD_WriteData(0x2D);
  87.     //Negative Voltage Gamma
  88.     LCD_WriteCMD(0xE1);
  89.     LCD_WriteData(0xD0);
  90.     LCD_WriteData(0x08);
  91.     LCD_WriteData(0x10);
  92.     LCD_WriteData(0x08);
  93.     LCD_WriteData(0x06);
  94.     LCD_WriteData(0x06);
  95.     LCD_WriteData(0x39);
  96.     LCD_WriteData(0x44);
  97.     LCD_WriteData(0x51);
  98.     LCD_WriteData(0x0B);
  99.     LCD_WriteData(0x16);
  100.     LCD_WriteData(0x14);
  101.     LCD_WriteData(0x2F);
  102.     LCD_WriteData(0x31);
  103.     //TE
  104.     LCD_WriteCMD(0x35);
  105.     LCD_WriteData(0x01);
  106.     //开启显示
  107.     LCD_WriteCMD(0x29);
  108. }
测试方法,实现在屏幕上显示渐变色
  1. void LCD_SetPos(uint16_t x,uint16_t y)
  2. {
  3.     LCD_WriteCMD(0x2A);
  4.     LCD_WriteData((x>>8)&0xFF);
  5.     LCD_WriteData(x&0xFF);
  6.     LCD_WriteData(0x00);
  7.     LCD_WriteData(0xEF);
  8.    
  9.     LCD_WriteCMD(0x2B);
  10.     LCD_WriteData((y>>8)&0xFF);
  11.     LCD_WriteData(y&0xFF);
  12.     LCD_WriteData(0x00);
  13.     LCD_WriteData(0xEF);
  14. }

  15. void LCD_Test(void)
  16. {
  17.     uint8_t r,g,b;
  18.     uint16_t rgb[2];
  19.     uint8_t i = 0;
  20.     uint8_t j = 0;
  21.     while(i < 240)
  22.     {
  23.         LCD_SetPos(0,i);
  24.         if(i<63 || i >188)
  25.         {
  26.             r = 252 - 4*(i%63);
  27.             g = 252 - r;
  28.             b = 0;
  29.         }
  30.         else if(i<126)
  31.         {
  32.             g = 252 - 4*(i%63);
  33.             b = 252 - g;
  34.             r = 0;
  35.         }
  36.         else if(i<189)
  37.         {
  38.             b = 252 - 4*(i%63);
  39.             r = 252 - b;
  40.             g = 0;
  41.         }
  42.         rgb[0] = (r<<8)|g;
  43.         rgb[1] = (b<<8);
  44.         j = 0;
  45.         LCD_WriteCMD(0x2C);
  46.         while(j < 240)
  47.         {
  48.             LCD_WriteData(rgb[0]);
  49.             LCD_WriteData(rgb[1]);
  50.             j+=1;
  51.         }
  52.         i+=1;
  53.     }
  54. }
运行效果
微信截图_20250124172548.png

LCD的基础驱动就完成了,后面就可以加上显示文字和图片的方法了,如果你不想自己花时间去弄,官方也提供了现成的代码,接下来介绍一下如何用官方提供的驱动控制这块屏幕
如果你使用了STM32CubeMX配置工程,打开C:\Users\你的用户名\STM32Cube\Repository\STM32Cube_FW_L5_V1.5.1,这里就是STM32CubeMX下载的L562的库
微信截图_20250124164330.png
也可以到官网上下载https://www.st.com.cn/zh/embedded-software/stm32cubel5.html#overview或者github https://github.com/STMicroelectronics/STM32CubeL5
把Utilities文件夹和Drivers文件夹里的BSP文件夹拷贝到你的工程相应的文件夹下
微信截图_20250124165159.png 微信截图_20250124165213.png
并从例程里找个stm32l562e_discovery_conf.h放到BSP的STM32L562E-DK文件夹里
微信截图_20250124171049.png
在Keil里新建3个分组,名字可以是其他的
微信截图_20250124165529.png
添加文件
微信截图_20250124170005.png
添加头文件路径
微信截图_20250124170115.png
使用官方库提供的方法初始化LCD,官方库里已有FMC初始化方法,可以把工程生成的FMC初始化方法注释掉
  1. #include "stm32l562e_discovery_lcd.h"
  2. #include "stm32_lcd.h"
  3. void LCDInit2(void)
  4. {
  5.     LCD_UTILS_Drv_t lcdDrv;
  6.     /* Initialize the LCD */
  7.     if (BSP_LCD_Init(0, LCD_ORIENTATION_PORTRAIT) != BSP_ERROR_NONE)
  8.     {
  9.         Error_Handler();
  10.     }
  11.     /* Set UTIL_LCD functions */
  12.     lcdDrv.DrawBitmap  = BSP_LCD_DrawBitmap;
  13.     lcdDrv.FillRGBRect = BSP_LCD_FillRGBRect;
  14.     lcdDrv.DrawHLine   = BSP_LCD_DrawHLine;
  15.     lcdDrv.DrawVLine   = BSP_LCD_DrawVLine;
  16.     lcdDrv.FillRect    = BSP_LCD_FillRect;
  17.     lcdDrv.GetPixel    = BSP_LCD_ReadPixel;
  18.     lcdDrv.SetPixel    = BSP_LCD_WritePixel;
  19.     lcdDrv.GetXSize    = BSP_LCD_GetXSize;
  20.     lcdDrv.GetYSize    = BSP_LCD_GetYSize;
  21.     lcdDrv.SetLayer    = BSP_LCD_SetActiveLayer;
  22.     lcdDrv.GetFormat   = BSP_LCD_GetFormat;
  23.     UTIL_LCD_SetFuncDriver(&lcdDrv);
  24.     /* Clear the LCD */
  25.     UTIL_LCD_Clear(UTIL_LCD_COLOR_WHITE);
  26.     BSP_LCD_DisplayOn(0);
  27.     UTIL_LCD_SetTextColor(UTIL_LCD_COLOR_BLUE);
  28.     UTIL_LCD_SetBackColor(UTIL_LCD_COLOR_WHITE);
  29.     UTIL_LCD_SetFont(&Font24);
  30.     UTIL_LCD_DisplayStringAt(0, 80, (uint8_t *)"STM32L562E-DK", CENTER_MODE);
  31.     UTIL_LCD_DisplayStringAt(0, 120, (uint8_t *)"LCD Test", CENTER_MODE);
  32.     UTIL_LCD_DisplayStringAt(0, 160, (uint8_t *)"yuyy1989", CENTER_MODE);
  33. }
运行效果
微信截图_20250124172556.png
官方库提供了划线画图显示文字的方法,有兴趣的可以研究一下,这里就先不展开了
微信截图_20250124172724.png
最后附上屏幕和ST7789H2的数据手册 FRD154BP2902-D-CTQ.pdf (1.34 MB, 下载次数: 2) ST7789H2.pdf (3.01 MB, 下载次数: 2)

打赏榜单

lvxinjia123 打赏了 30.00 元 2025-06-08
理由:学习了新的屏幕驱动方法

lulugl 发表于 2025-2-6 08:10 | 显示全部楼层

感谢分享这么精彩的文章!

gaoyang9992006 发表于 2025-2-7 10:03 | 显示全部楼层
还没用过这种方式,跟你好好学学
gaoyang9992006 发表于 2025-2-7 10:07 | 显示全部楼层
以前都是用SPI控制这种屏幕,没用过这8080接口,学习一下,一会儿我照猫画虎试试。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

168

主题

826

帖子

10

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