ART-PI开发记录----1、STM32CUBEMX创建LTDC显示工程

一、前述

             ART-PI是RTT官方退出的STM32H7系列的开发板,照理说用RTT开发即可,简洁易上手(如果已经熟悉RTT)。但也可基于STM32CUBEMX开发,生成带FreeRTOS以及FATFS文件系统的工程。相对来说,用ST官方工具生成的代码用起来跟原汁原味一些,但RTT则具有更多的中间件,代码使用起来也更加简洁。个人习惯于使用STM32CUBEMX,所以先记录一下基于CUBE的开发方式,后续会加入RTT。

 

二、硬件配置

             如图的ART-PI + LCD转接板 + 野火5寸RGB屏

             

三、STM32CUBEMX的配置

             进入正题,创建一个LTDC的显示工程。需要用到以下几个基本外设,FMC、MPU、DMA2D、LTDC。FMC用于驱动SDRAM,作为LTDC的缓存。如果是480*272的RGB显示屏,也可使用内部的AXI-SRAM以获得更大的数据带宽。但AXI-SRAM只有512KB,最多作双FB缓冲。有的GUI如AWTK需要作三FB缓冲才可流畅显示而不产生撕裂画面。MPU,字面上意思是用于保护内存单元。但实际上,MPU是用来协调芯片内部的I-Cashe、D-Cashe与存储设备的一个外设。具体自行搜索:“STM32F7 MPU Cache浅析”。具体作用就是可加速RAM、ROM数据的读写速度,当然,加速也是存在一定的局限性的。DMA2D与LTDC就不赘述了。
 

(1)时钟树

         内核倍频到480M,LTDC时钟如下图红框,20M。FMC,则采用48M的HSI倍频到240M。所以SDRAM时钟频率是240M/2 = 120M

                               

                           图3.1.1 时钟树的配置

 

(2)GPIO的配置

         ART-PI还是进行了不少的GPIO映射的,估计是为了画板走线方便吧。LTDC的IO都进行了大量的映射,这里还需要注意背光控制引脚的初始化。

                                                                                                    

                               图3.2.1 GPIO的配置

(3)MPU的配置

         如下图,配置了AXI-SRAM以及SDRAM的缓冲模式。SDRAM为读缓冲,写不缓冲。而AXI-SRAM则是读写缓冲。

             

                                                                                                        

                              图3.3.1 MPU的配置

 

(4)FMC的配置

         SDRAM是使用FMC驱动的,我们找到SDRAM1处进行配置。具体的时序参考SDRAM的数据手册。ART-PI使用的是:W9825G6KH-6。

                                                                                                       

                        图 3.4.1 FMC配置

                                                                                                                

                      图 3.4.2 SDRAM时序

 

(5)LTDC的配置

         我使用的是野火的800*480-5寸电容触摸显示模组,LTDC驱动RGB屏的参数也应自行参考屏的数据手册。

                                                                                                     

                            图 3.5.1 LTDC配置1

 

                                                                                                     

                             图 3.5.2 LTDC配置2

 

(6)DMA2D的配置

         这个只需要在CUBE里面勾选这个选项就好,这样“main.h”就会包含DMA2D库的头文件。因为后续在使用DMA2D的时候,会先对DMA2D进行配置再使用,所以在CUBE里面的配置无意义。

 

四、代码

         用stm32cubemx生成代码后,并不能直接烧录到ART-PI运行。还需要添加一些代码。

        (1)SDRAM的初始化,参考了安富莱的教程。


#define SDRAM_TIMEOUT                    ((uint32_t)0xFFFF)
#define REFRESH_COUNT                    ((uint32_t)917)    /* SDRAM ReFlash Count */  


#define SDRAM_MODEREG_BURST_LENGTH_1             ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_LENGTH_2             ((uint16_t)0x0001)
#define SDRAM_MODEREG_BURST_LENGTH_4             ((uint16_t)0x0002)
#define SDRAM_MODEREG_BURST_LENGTH_8             ((uint16_t)0x0004)
#define SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL      ((uint16_t)0x0000)
#define SDRAM_MODEREG_BURST_TYPE_INTERLEAVED     ((uint16_t)0x0008)
#define SDRAM_MODEREG_CAS_LATENCY_2              ((uint16_t)0x0020)
#define SDRAM_MODEREG_CAS_LATENCY_3              ((uint16_t)0x0030)
#define SDRAM_MODEREG_OPERATING_MODE_STANDARD    ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_PROGRAMMED ((uint16_t)0x0000)
#define SDRAM_MODEREG_WRITEBURST_MODE_SINGLE     ((uint16_t)0x0200)



/* This function is used to initialize SDRAM */
void SDRAM_Initialization_Sequence(SDRAM_HandleTypeDef *hsdram)
{
	__IO uint32_t tmpmrd =0;
	FMC_SDRAM_CommandTypeDef command1 = {0},*Command = &command1;
 
	
    /*##-1- Clock enable command ##################################################*/
	Command->CommandMode = FMC_SDRAM_CMD_CLK_ENABLE;
	Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;;
	Command->AutoRefreshNumber = 1;
	Command->ModeRegisterDefinition = 0;

	/* SendCommand */
	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);

    /*##-2- delay ##################################################*/
	HAL_Delay(1);

    /*##-3- SDRAM pre charging(precharge all) #############################*/
	Command->CommandMode = FMC_SDRAM_CMD_PALL;
	Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
	Command->AutoRefreshNumber = 1;
	Command->ModeRegisterDefinition = 0;

	/* SendCommand */
	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);

    /*##-4- Auto refresh command ##################################################*/
	Command->CommandMode = FMC_SDRAM_CMD_AUTOREFRESH_MODE;
	Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
	Command->AutoRefreshNumber = 8;
	Command->ModeRegisterDefinition = 0;

	/* SendCommand */
	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);

    /*##-5- Configure SDRAM mode register ######################################*/
	tmpmrd = (uint32_t)SDRAM_MODEREG_BURST_LENGTH_1          |
					 SDRAM_MODEREG_BURST_TYPE_SEQUENTIAL   |
					 SDRAM_MODEREG_CAS_LATENCY_3           |
					 SDRAM_MODEREG_OPERATING_MODE_STANDARD |
					 SDRAM_MODEREG_WRITEBURST_MODE_SINGLE;

	Command->CommandMode = FMC_SDRAM_CMD_LOAD_MODE;
	Command->CommandTarget = FMC_SDRAM_CMD_TARGET_BANK1;
	Command->AutoRefreshNumber = 1;
	Command->ModeRegisterDefinition = tmpmrd;

	/* SendCommand */
	HAL_SDRAM_SendCommand(hsdram, Command, SDRAM_TIMEOUT);

    /*##-6- Set self refresh rate ############################################*/
    /*
      = 64ms / 8192 *120MHz*1000 - 20
      = 917
    */
	HAL_SDRAM_ProgramRefreshRate(hsdram, REFRESH_COUNT); 
}

(2)DMA2D功能代码,这部分代码来自安富莱的教程


/*
*********************************************************************************************************
*	函 数 名: _DMA2D_Fill
*	功能说明: DMA2D颜色填充功能
*	形    参: pDst          颜色数据目的地址
*             xSize         色块X轴大小,即每行像素数
*             ySize         色块Y轴大小,即行数
*             OffLine       前景层图像的行偏移
*             ColorIndex    色块颜色值
*             PixelFormat   目标区颜色格式
*	返 回 值: 无
*********************************************************************************************************
*/
void _DMA2D_Fill(void * pDst, 
    			uint32_t xSize, 
				uint32_t ySize, 
				uint32_t OffLine, 
				uint32_t ColorIndex, 
				uint32_t PixelFormat) 
{
	
	/* DMA2D采用寄存器到存储器模式, 这种模式用不到前景层和背景层 */  
	DMA2D->CR      = 0x00030000UL | (1 << 9);
	DMA2D->OCOLR   = ColorIndex;
	DMA2D->OMAR    = (uint32_t)pDst;
	DMA2D->OOR     = OffLine;
	DMA2D->OPFCCR  = PixelFormat;
	DMA2D->NLR     = (uint32_t)(xSize << 16) | (uint16_t)ySize;

	/* 启动传输 */
	DMA2D->CR   |= DMA2D_CR_START;   

	/* 等待DMA2D传输完成 */
	while (DMA2D->CR & DMA2D_CR_START) {} 
}

/*
*********************************************************************************************************
*	函 数 名: _DMA2D_Copy
*	功能说明: 通过DMA2D从前景层复制指定区域的颜色数据到目标区域
*	形    参: pSrc          颜色数据源地址
*             pDst          颜色数据目的地址
*             xSize         目的区域的X轴大小,即每行像素数
*             ySize         目的区域的Y轴大小,即行数
*             OffLineSrc    前景层图像的行偏移
*             OffLineDst    输出的行偏移
*             PixelFormat   目标区颜色格式
*	返 回 值: 无
*********************************************************************************************************
*/
void _DMA2D_Copy(void * pSrc, 
				void * pDst, 
				uint32_t xSize, 
				uint32_t ySize, 
				uint32_t OffLineSrc, 
				uint32_t OffLineDst, 
				uint32_t PixelFormat) 
{

	/* DMA2D采用存储器到存储器模式, 这种模式是前景层作为DMA2D输入 */  
	DMA2D->CR      = 0x00000000UL | (1 << 9);
	DMA2D->FGMAR   = (uint32_t)pSrc;
	DMA2D->OMAR    = (uint32_t)pDst;
	DMA2D->FGOR    = OffLineSrc;
	DMA2D->OOR     = OffLineDst;
	
	/* 前景层和输出区域都采用的RGB565颜色格式 */
	DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_RGB565;
	DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_RGB565;
	
	DMA2D->NLR     = (uint32_t)(xSize << 16) | (uint16_t)ySize;

	/* 启动传输 */
	DMA2D->CR   |= DMA2D_CR_START;   

	/* 等待DMA2D传输完成 */
	while (DMA2D->CR & DMA2D_CR_START) {} 
}

/*
*********************************************************************************************************
*	函 数 名: _DMA2D_MixColorsBulk
*	功能说明: 前景层和目标区域的颜色混合
*	形    参: pColorFG      前景层数据源地址
*             OffLineSrcFG  前景层图像的行偏移
*             pColorDst     目标区数据地址
*             OffLineDst    目标区的行偏移
*             xSize         目的区域的X轴大小,即每行像素数
*             ySize         目的区域的Y轴大小,即行数
*             Intens        设置前景层的透明度,255表示完全不透明,0表示完全透明
*	返 回 值: 无
*********************************************************************************************************
*/
 void _DMA2D_MixColorsBulk(uint32_t * pColorFG,  
							uint32_t OffLineSrcFG,
							uint32_t * pColorDst, 
							uint32_t OffLineDst,
							uint32_t xSize, 
							uint32_t ySize, 
							uint8_t Intens)
{
	/* DMA2D采用存储器到存储器模式, 这种模式前景层和背景层作为DMA2D输入,且支持颜色格式转换和颜色混合 */  
	DMA2D->CR      = 0x00020000UL | (1 << 9);
	DMA2D->FGMAR   = (uint32_t)pColorFG;
	DMA2D->BGMAR   = (uint32_t)pColorDst;
	DMA2D->OMAR    = (uint32_t)pColorDst;
	DMA2D->FGOR    = OffLineSrcFG;
	DMA2D->BGOR    = OffLineDst;
	DMA2D->OOR     = OffLineDst;

	/* 前景层,背景层和输出区都是用的RGB565格式 */
	DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_RGB565
				 | (1UL << 16)
				 | ((uint32_t)Intens << 24);
	DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_RGB565;
	DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_RGB565;

	DMA2D->NLR     = (uint32_t)(xSize << 16) | (uint16_t)ySize;
  
	/* 启动传输 */
	DMA2D->CR   |= DMA2D_CR_START;   

	/* 等待DMA2D传输完成 */
	while (DMA2D->CR & DMA2D_CR_START) {} 
}

/*
*********************************************************************************************************
*	函 数 名: _DMA2D_AlphaBlendingBulk
*	功能说明: 前景层和背景层的颜色混合
*	形    参: pColorFG      前景层源数据地址
*             OffLineSrcFG  前景层源数据行偏移
*             pColorBG      背景层源数据地址
*             OffLineSrcBG  背景层源数据行偏移
*             pColorDst     目标区地址
*             OffLineDst    目标区行偏移
*             xSize         目标区域的X轴大小,即每行像素数
*             ySize         目标区域的Y轴大小,即行数
*	返 回 值: 无
*********************************************************************************************************
*/
void _DMA2D_AlphaBlendingBulk(uint32_t * pColorFG,  
								uint32_t OffLineSrcFG,
								uint32_t * pColorBG,  
								uint32_t OffLineSrcBG,
								uint32_t * pColorDst, 
								uint32_t OffLineDst,
								uint32_t xSize, 
								uint32_t ySize) 
{  
	/* DMA2D采用存储器到存储器模式, 这种模式前景层和背景层作为DMA2D输入,且支持颜色格式转换和颜色混合 */  
	DMA2D->CR      = 0x00020000UL | (1 << 9);
	DMA2D->FGMAR   = (uint32_t)pColorFG;
	DMA2D->BGMAR   = (uint32_t)pColorBG;
	DMA2D->OMAR    = (uint32_t)pColorDst;
	DMA2D->FGOR    = OffLineSrcFG;
	DMA2D->BGOR    = OffLineSrcBG;
	DMA2D->OOR     = OffLineDst;

	/* 前景层,背景层采用ARGB8888格式,输出区采用RGB565格式 */
	DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
	DMA2D->BGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
	DMA2D->OPFCCR  = LTDC_PIXEL_FORMAT_RGB565;
	DMA2D->NLR     = (uint32_t)(xSize << 16) | (uint16_t)ySize;

	/* 启动传输 */
	DMA2D->CR   |= DMA2D_CR_START;   

	/* 等待DMA2D传输完成 */
	while (DMA2D->CR & DMA2D_CR_START) {} 
}

/*
*********************************************************************************************************
*	函 数 名: _DMA2D_DrawAlphaBitmap
*	功能说明: ARGB8888格式位图显示
*	形    参: pDst        目标区地址
*             pSrc        源数据地址,即位图首地址
*             xSize       目标区域的X轴大小,即每行像素数
*             ySize       目标区域的Y轴大小,即行数
*             OffLineSrc  源数据行偏移
*             OffLineDst  目标区行偏移
*             PixelFormat 目标区颜色格式
*	返 回 值: 无
*********************************************************************************************************
*/
 void _DMA2D_DrawAlphaBitmap(void  * pDst, 
								void  * pSrc, 
								uint32_t xSize, 
								uint32_t ySize, 
								uint32_t OffLineSrc, 
								uint32_t OffLineDst, 
								uint32_t PixelFormat) 
{
	/* DMA2D采用存储器到存储器模式, 这种模式前景层和背景层作为DMA2D输入,且支持颜色格式转换和颜色混合 */  
	DMA2D->CR      = 0x00020000UL | (1 << 9);
	DMA2D->FGMAR   = (uint32_t)pSrc;
	DMA2D->BGMAR   = (uint32_t)pDst;
	DMA2D->OMAR    = (uint32_t)pDst;
	DMA2D->FGOR    = OffLineSrc;
	DMA2D->BGOR    = OffLineDst;
	DMA2D->OOR     = OffLineDst;
	
	/* 前景层颜色格式是LTDC_PIXEL_FORMAT_ARGB8888,即位图的颜色格式,背景层和输出区颜色格式可配置 */
	DMA2D->FGPFCCR = LTDC_PIXEL_FORMAT_ARGB8888;
	DMA2D->BGPFCCR = PixelFormat;
	DMA2D->OPFCCR  = PixelFormat;
	DMA2D->NLR     = (uint32_t)(xSize << 16) | (uint16_t)ySize;

	/* 启动传输 */
	DMA2D->CR   |= DMA2D_CR_START;   

	/* 等待DMA2D传输完成 */
	while (DMA2D->CR & DMA2D_CR_START) {} 
}

(3)主函数

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MPU Configuration--------------------------------------------------------*/
  MPU_Config();

  /* Enable I-Cache---------------------------------------------------------*/
  SCB_EnableICache();

  /* Enable D-Cache---------------------------------------------------------*/
  SCB_EnableDCache();

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_FMC_Init();
  MX_LPUART1_UART_Init();
  MX_TIM6_Init();
  MX_LTDC_Init();
  MX_DMA2D_Init();
  /* USER CODE BEGIN 2 */
  SDRAM_Initialization_Sequence(&hsdram1);
	
 _DMA2D_Fill((uint16_t*)0xc0000000, 
    		    800, 
				480, 
				0, 
				0x07e0, 
				LTDC_PIXEL_FORMAT_RGB565) ;	
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

 

五、效果展示

         (1) 主函数中使用DMA2D刷了全屏的绿色,显存位置如LTDC的设置,地址为:0xC0000000。这里屏幕没亮的话注意检查一下背光是否有打开。

        (2)移植了LittleVGL7.9版本到板子上,并跑了一个例程。需要代码的可自行去下载:https://download.csdn.net/download/a3748622/14039358

(3)LittleVGL双帧缓冲代码

上述工程里默认是使用AXI RAM做240ROW的缓冲区。也可以使用SDRAM作双帧缓冲,通过“lv_port_disp.c”的一个宏定义更改:

#define TWO_SCREEN_SIZE   0

 

评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值