这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 活动中心 » 板卡试用 » STM32H747I-DISCO开发指南【LCD屏幕使用】

共1条 1/1 1 跳转至

STM32H747I-DISCO开发指南【LCD屏幕使用】

菜鸟
2025-11-27 00:41:29     打赏

一、硬件介绍

1、产品特点

STM32H747I-DISCO开发板基于Arm的STM32H747XIH6微控制器拥有Cortex-M7内核(带双精度浮点单元,运行频率高达 480 MHz) 和 Cortex-M4内核(带单精度浮点单元,运行频率高达 240 MHz)的双核性能,板载配备2MB的Flash存储器和1MB的RAM、4英寸TFT LCD触摸显示屏(480x800) 具有MIPI DSI接口等;

image-20251109210717816.png



规格参数

image.png

24 MHz 晶振(X1),用于USB OTG HS PHY 和摄像头模块;

25 MHz 晶振(X2),用于主时钟发生器和以太网 PHY;

32.768 kHz 晶体(X3),用于RTC;

25 MHz 晶振(X4),仅用于STLINK-V3E;


硬件框图


image-20251110230635570.png



2、功能引脚示意图 / 原理图

主要原理图

image-20251109215821403.png

image-20251109215821403


二、功能配置

1、LCD屏幕

硬件介绍

4 英寸 TFT-LCD 的分辨率为 480x800 像素,可显示高达 16.7M 种颜色,LCD 与微控制器之间的接口是一个 2-Lane MIPI 信号,带 MIPI DSI 接口;

image-20251125112458684.png

image-20251125112458684

特性

4 英寸 TFT 彩色 LCD

480(RGB)x800 像素

16.7M 色彩显示

最多两路 MIPI/DSI 数据

电容触摸屏支持单点触摸和手势,或双点触摸

LCD 和触摸屏共用 2.8V-3.3V 电源,背光使用 5V 电源


原理图

image-20251109215321547.png



2、创建工程

1、工程配置

打开 STM32CubeMX ,选择创建 STM32H747I-DISCO 模板,进行相关配置;

image-20251115232242460

image-20251115232242460.png


image-20251115232438506

image-20251115232438506.png



配置LCD接口

屏幕驱动IC:NT35510

根据驱动IC手册进行相关配置;

image-20251125201624969.png

image-20251125201624969

配置 Conmmd 命令模式

image-20251125202513794.png

image-20251125202513794

三、代码编写

1、在工程目录下,创建 BSP文件夹 ,导入屏幕驱动IC等相关文件;

2、将图像转换(ARGB888)后存储在文件中 xxx.h ,用于后续的展示;


效果:在LCD屏幕上显示自定义的图片内容;

主要相关代码

#include "main.h"
#include "cat.h"
#include <stdio.h>


const LCD_UTILS_Drv_t LCD_UTIL_Driver =
    {
        BSP_LCD_DrawBitmap,
        BSP_LCD_FillRGBRect,
        BSP_LCD_DrawHLine,
        BSP_LCD_DrawVLine,
        BSP_LCD_FillRect,
        BSP_LCD_ReadPixel,
        BSP_LCD_WritePixel,
        LCD_GetXSize,
        LCD_GetYSize,
        BSP_LCD_SetActiveLayer,
        BSP_LCD_GetPixelFormat
};

static const uint32_t *Images[] =
  {
        image_800x480
};

uint8_t pColFull[] = {0x00, 0x00, 0x03, 0x1F}; /* 0 -> 799 */
uint8_t pPage[] = {0x00, 0x00, 0x01, 0xDF};    /* 0 -> 479 */


// 清除缓存
static void LCD_FlushCacheRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h);

int main(void)
{
  MPU_Config();
  CPU_CACHE_Enable();
  HAL_Init();
  SystemClock_Config();
  BSP_SDRAM_Init(0);

  if (LCD_Init() != BSP_ERROR_NONE)
  {
    Error_Handler();
  }

  memset((void *)LCD_FRAME_BUFFER, 0x00, 800U * 480U * 4U); // ARGB8888 全黑
  LCD_FlushCacheRect(0, 0, 800, 480);
  HAL_DSI_Refresh(&hlcd_dsi);

  /* 层0定义为 800x480 的 ARGB8888 帧缓冲 */
  Lcd_Ctx[0].ActiveLayer = 0;
  Lcd_Ctx[0].PixelFormat = LCD_PIXEL_FORMAT_ARGB8888;
  Lcd_Ctx[0].BppFactor = 4;
  Lcd_Ctx[0].XSize = 800;
  Lcd_Ctx[0].YSize = 480;


  __HAL_DSI_WRAPPER_DISABLE(&hlcd_dsi);
  LCD_LayertInit(0, LCD_FRAME_BUFFER);
  UTIL_LCD_SetFuncDriver(&LCD_UTIL_Driver);
  HAL_LTDC_SetPitch(&hlcd_ltdc, Lcd_Ctx[0].XSize, 0);
  __HAL_DSI_WRAPPER_ENABLE(&hlcd_dsi);

  HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 4, NT35510_CMD_CASET, pColFull);
  HAL_DSI_LongWrite(&hlcd_dsi, 0, DSI_DCS_LONG_PKT_WRITE, 4, NT35510_CMD_RASET, pPage);


  /* 拷贝全屏图片 */
  CopyPicture((uint32_t *)Images[0], (uint32_t *)LCD_FRAME_BUFFER, 0, 0, 800, 480);
  LCD_FlushCacheRect(0, 0, 800, 480); 
  HAL_DSI_Refresh(&hlcd_dsi);

  while (1)
  {
    HAL_Delay(1000);
  }
}

//清除缓存内容
static void LCD_FlushCacheRect(uint16_t x, uint16_t y, uint16_t w, uint16_t h)
{
  uint32_t bytes_per_pixel = 4; // ARGB8888
  uint32_t line_stride = 800 * bytes_per_pixel;
  uint32_t addr = (uint32_t)LCD_FRAME_BUFFER + (uint32_t)y * line_stride + (uint32_t)x * bytes_per_pixel;
  uint32_t size = (uint32_t)h * line_stride; // 按整行区域清理更安全

  // 32字节对齐到 cache line
  uint32_t start = addr & ~((uint32_t)0x1F);
  uint32_t end = (addr + size + 31U) & ~((uint32_t)0x1F);
  SCB_CleanDCache_by_Addr((uint32_t *)start, end - start);
}


int32_t LCD_GetXSize(uint32_t Instance, uint32_t *XSize)
{
  *XSize = Lcd_Ctx[0].XSize;

  return BSP_ERROR_NONE;
}

int32_t LCD_GetYSize(uint32_t Instance, uint32_t *YSize)
{
  *YSize = Lcd_Ctx[0].YSize;

  return BSP_ERROR_NONE;
}


static uint8_t LCD_Init(void)
{
  DSI_PHY_TimerTypeDef PhyTimings;
  NT35510_IO_t IOCtx;
  static NT35510_Object_t NT35510Obj;
  static void *Lcd_CompObj = NULL;

  BSP_LCD_Reset(0);
  LCD_MspInit();

  PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC;
  PeriphClkInitStruct.PLL3.PLL3M = 5;
  PeriphClkInitStruct.PLL3.PLL3N = 160;
  PeriphClkInitStruct.PLL3.PLL3FRACN = 0;
  PeriphClkInitStruct.PLL3.PLL3P = 2;
  PeriphClkInitStruct.PLL3.PLL3Q = 2;
  PeriphClkInitStruct.PLL3.PLL3R = 19;
  PeriphClkInitStruct.PLL3.PLL3VCOSEL = RCC_PLL3VCOWIDE;
  PeriphClkInitStruct.PLL3.PLL3RGE = RCC_PLL3VCIRANGE_2;

  HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);

  hlcd_dsi.Instance = DSI;

  HAL_DSI_DeInit(&(hlcd_dsi));

  dsiPllInit.PLLNDIV = 100;
  dsiPllInit.PLLIDF = DSI_PLL_IN_DIV5;
  dsiPllInit.PLLODF = DSI_PLL_OUT_DIV1;

  hlcd_dsi.Init.NumberOfLanes = DSI_TWO_DATA_LANES;
  hlcd_dsi.Init.TXEscapeCkdiv = 0x4;

  HAL_DSI_Init(&(hlcd_dsi), &(dsiPllInit));

  CmdCfg.VirtualChannelID = 0;
  CmdCfg.HSPolarity = DSI_HSYNC_ACTIVE_HIGH;
  CmdCfg.VSPolarity = DSI_VSYNC_ACTIVE_HIGH;
  CmdCfg.DEPolarity = DSI_DATA_ENABLE_ACTIVE_HIGH;
  CmdCfg.ColorCoding = DSI_RGB888;
  CmdCfg.CommandSize = HACT;
  CmdCfg.TearingEffectSource = DSI_TE_DSILINK;
  CmdCfg.TearingEffectPolarity = DSI_TE_RISING_EDGE;
  CmdCfg.VSyncPol = DSI_VSYNC_FALLING;
  CmdCfg.AutomaticRefresh = DSI_AR_DISABLE;
  CmdCfg.TEAcknowledgeRequest = DSI_TE_ACKNOWLEDGE_ENABLE;
  HAL_DSI_ConfigAdaptedCommandMode(&hlcd_dsi, &CmdCfg);

  LPCmd.LPGenShortWriteNoP = DSI_LP_GSW0P_ENABLE;
  LPCmd.LPGenShortWriteOneP = DSI_LP_GSW1P_ENABLE;
  LPCmd.LPGenShortWriteTwoP = DSI_LP_GSW2P_ENABLE;
  LPCmd.LPGenShortReadNoP = DSI_LP_GSR0P_ENABLE;
  LPCmd.LPGenShortReadOneP = DSI_LP_GSR1P_ENABLE;
  LPCmd.LPGenShortReadTwoP = DSI_LP_GSR2P_ENABLE;
  LPCmd.LPGenLongWrite = DSI_LP_GLW_ENABLE;
  LPCmd.LPDcsShortWriteNoP = DSI_LP_DSW0P_ENABLE;
  LPCmd.LPDcsShortWriteOneP = DSI_LP_DSW1P_ENABLE;
  LPCmd.LPDcsShortReadNoP = DSI_LP_DSR0P_ENABLE;
  LPCmd.LPDcsLongWrite = DSI_LP_DLW_ENABLE;
  HAL_DSI_ConfigCommand(&hlcd_dsi, &LPCmd);

  LTDC_Init();
  HAL_DSI_Start(&(hlcd_dsi));

  PhyTimings.ClockLaneHS2LPTime = 35;
  PhyTimings.ClockLaneLP2HSTime = 35;
  PhyTimings.DataLaneHS2LPTime = 35;
  PhyTimings.DataLaneLP2HSTime = 35;
  PhyTimings.DataLaneMaxReadTime = 0;
  PhyTimings.StopWaitTime = 10;
  HAL_DSI_ConfigPhyTimer(&hlcd_dsi, &PhyTimings);

  IOCtx.Address = 0;
  IOCtx.GetTick = BSP_GetTick;
  IOCtx.WriteReg = DSI_IO_Write;
  IOCtx.ReadReg = DSI_IO_Read;

  NT35510_RegisterBusIO(&NT35510Obj, &IOCtx);
  Lcd_CompObj = (&NT35510Obj);

  NT35510_Init(Lcd_CompObj, NT35510_COLMOD_RGB888, LCD_ORIENTATION_LANDSCAPE);

  LPCmd.LPGenShortWriteNoP = DSI_LP_GSW0P_DISABLE;
  LPCmd.LPGenShortWriteOneP = DSI_LP_GSW1P_DISABLE;
  LPCmd.LPGenShortWriteTwoP = DSI_LP_GSW2P_DISABLE;
  LPCmd.LPGenShortReadNoP = DSI_LP_GSR0P_DISABLE;
  LPCmd.LPGenShortReadOneP = DSI_LP_GSR1P_DISABLE;
  LPCmd.LPGenShortReadTwoP = DSI_LP_GSR2P_DISABLE;
  LPCmd.LPGenLongWrite = DSI_LP_GLW_DISABLE;
  LPCmd.LPDcsShortWriteNoP = DSI_LP_DSW0P_DISABLE;
  LPCmd.LPDcsShortWriteOneP = DSI_LP_DSW1P_DISABLE;
  LPCmd.LPDcsShortReadNoP = DSI_LP_DSR0P_DISABLE;
  LPCmd.LPDcsLongWrite = DSI_LP_DLW_DISABLE;
  HAL_DSI_ConfigCommand(&hlcd_dsi, &LPCmd);

  HAL_DSI_ConfigFlowControl(&hlcd_dsi, DSI_FLOW_CONTROL_BTA);
  HAL_DSI_ForceRXLowPower(&hlcd_dsi, ENABLE);

  return BSP_ERROR_NONE;
}

void LTDC_Init(void)
{
  hlcd_ltdc.Instance = LTDC;
  HAL_LTDC_DeInit(&hlcd_ltdc);

  hlcd_ltdc.Init.HorizontalSync = HSYNC;
  hlcd_ltdc.Init.VerticalSync = VSYNC;
  hlcd_ltdc.Init.AccumulatedHBP = HSYNC + HBP;
  hlcd_ltdc.Init.AccumulatedVBP = VSYNC + VBP;
  hlcd_ltdc.Init.AccumulatedActiveH = VSYNC + VBP + VACT;
  hlcd_ltdc.Init.AccumulatedActiveW = HSYNC + HBP + HACT;
  hlcd_ltdc.Init.TotalHeigh = VSYNC + VBP + VACT + VFP;
  hlcd_ltdc.Init.TotalWidth = HSYNC + HBP + HACT + HFP;

  hlcd_ltdc.Init.Backcolor.Blue = 0;
  hlcd_ltdc.Init.Backcolor.Green = 0;
  hlcd_ltdc.Init.Backcolor.Red = 0;

  hlcd_ltdc.Init.HSPolarity = LTDC_HSPOLARITY_AL;
  hlcd_ltdc.Init.VSPolarity = LTDC_VSPOLARITY_AL;
  hlcd_ltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL;
  hlcd_ltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC;
  hlcd_ltdc.Instance = LTDC;

  HAL_LTDC_Init(&hlcd_ltdc);
}


void LCD_LayertInit(uint16_t LayerIndex, uint32_t Address)
{
  LTDC_LayerCfgTypeDef layercfg;

  layercfg.WindowX0 = 0;
  layercfg.WindowX1 = Lcd_Ctx[0].XSize;
  layercfg.WindowY0 = 0;
  layercfg.WindowY1 = Lcd_Ctx[0].YSize;
  layercfg.PixelFormat = LTDC_PIXEL_FORMAT_ARGB8888;
  layercfg.FBStartAdress = Address;
  layercfg.Alpha = 255;
  layercfg.Alpha0 = 0;
  layercfg.Backcolor.Blue = 0;
  layercfg.Backcolor.Green = 0;
  layercfg.Backcolor.Red = 0;
  layercfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_PAxCA;
  layercfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_PAxCA;
  layercfg.ImageWidth = Lcd_Ctx[0].XSize;
  layercfg.ImageHeight = Lcd_Ctx[0].YSize;

  HAL_LTDC_ConfigLayer(&hlcd_ltdc, &layercfg, LayerIndex);
}

static int32_t DSI_IO_Write(uint16_t ChannelNbr, uint16_t Reg, uint8_t *pData, uint16_t Size)
{
  int32_t ret = BSP_ERROR_NONE;

  if (Size <= 1U)
  {
    if (HAL_DSI_ShortWrite(&hlcd_dsi, ChannelNbr, DSI_DCS_SHORT_PKT_WRITE_P1, Reg, (uint32_t)pData[Size]) != HAL_OK)
    {
      ret = BSP_ERROR_BUS_FAILURE;
    }
  }
  else
  {
    if (HAL_DSI_LongWrite(&hlcd_dsi, ChannelNbr, DSI_DCS_LONG_PKT_WRITE, Size, (uint32_t)Reg, pData) != HAL_OK)
    {
      ret = BSP_ERROR_BUS_FAILURE;
    }
  }

  return ret;
}

static int32_t DSI_IO_Read(uint16_t ChannelNbr, uint16_t Reg, uint8_t *pData, uint16_t Size)
{
  int32_t ret = BSP_ERROR_NONE;

  if (HAL_DSI_Read(&hlcd_dsi, ChannelNbr, pData, Size, DSI_DCS_SHORT_PKT_READ, Reg, pData) != HAL_OK)
  {
    ret = BSP_ERROR_BUS_FAILURE;
  }

  return ret;
}

//DMA2D 整块图像拷贝
static void CopyPicture(uint32_t *pSrc, uint32_t *pDst, uint16_t x, uint16_t y, uint16_t xsize, uint16_t ysize)
{

  uint32_t destination = (uint32_t)pDst + (y * 800 + x) * 4;
  uint32_t source = (uint32_t)pSrc;

  hdma2d.Init.Mode = DMA2D_M2M;
  hdma2d.Init.ColorMode = DMA2D_OUTPUT_ARGB8888;
  hdma2d.Init.OutputOffset = 800 - xsize;
  hdma2d.Init.AlphaInverted = DMA2D_REGULAR_ALPHA;
  hdma2d.Init.RedBlueSwap = DMA2D_RB_REGULAR;     

  hdma2d.XferCpltCallback = NULL;

  hdma2d.LayerCfg[1].AlphaMode = DMA2D_NO_MODIF_ALPHA;
  hdma2d.LayerCfg[1].InputAlpha = 0xFF;
  hdma2d.LayerCfg[1].InputColorMode = DMA2D_INPUT_ARGB8888;
  hdma2d.LayerCfg[1].InputOffset = 0;
  hdma2d.LayerCfg[1].RedBlueSwap = DMA2D_RB_REGULAR;   
  hdma2d.LayerCfg[1].AlphaInverted = DMA2D_REGULAR_ALPHA; 

  hdma2d.Instance = DMA2D;

  /* DMA2D 初始化 */
  if (HAL_DMA2D_Init(&hdma2d) == HAL_OK)
  {
    if (HAL_DMA2D_ConfigLayer(&hdma2d, 1) == HAL_OK)
    {
      if (HAL_DMA2D_Start(&hdma2d, source, destination, xsize, ysize) == HAL_OK)
      {
        HAL_DMA2D_PollForTransfer(&hdma2d, 100);
      }
    }
  }
}

图片转换成ARGB888格式;

#ifndef CAT_H
#define CAT_H

#define CAT_WIDTH 800
#define CAT_HEIGHT 480
#define CAT_PIXEL_COUNT (CAT_WIDTH * CAT_HEIGHT)

// value: AARRGGBB
static const uint32_t image_800x480[CAT_PIXEL_COUNT] = {
0xFF413C30, 0xFF342E21, 0xFF332F22, 0xFF322D20, 0xFF312D20, 0xFF312C20, 0xFF312D20, 0xFF312D1F,
0xFF312C1F, 0xFF312C1F, 0xFF302B1D, 0xFF302B1D, 0xFF312B1E, 0xFF302A1E, 0xFF302B1E, 0xFF312C1E,
    .....
    .....    
        
};



四、程序烧录

1、连接USB数据线至开发板的STLINK-V3E接口;

2、分别选择 CM4 / CM7 程序,点击 Download 分别烧录程序到开发板上;



五、效果演示

LCD屏幕和原图展示的色彩效果对比;

原图

1764175140630724.png

Cat

实际效果

image-20251126233429168.png

image-20251126233429168












关键词: STM32H747I-DISCO    

共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]