使用CubeMX设置STM32F429的LTDC+DMA2D显示,以及JPG图片软件解码,以及文件系统

硬件环境

开发板:阿波罗开发板->429核心板
RGB屏:正点原子4.3  800*480显示屏

1.根据硬件接口配置STM32的引脚

使用CubeMX设置STM32F429的LTDC+DMA2D显示,以及JPG图片软件解码,以及文件系统_第1张图片
首先看整点原子开发板的RGB屏的接口,它是一个RGB565的接口,以及DMA2D使用了外部SDRAM。然后根据引脚来配置CubeMX的设置

LTDC配置

使用CubeMX设置STM32F429的LTDC+DMA2D显示,以及JPG图片软件解码,以及文件系统_第2张图片
注意:如果你直接设置RGB565会自动配置图形界面的IO口,其实他是和正点原子原理图的IO不一致的,所以还是要先去设置IO口,再去使能这个LTDC模块。
2:这个0xC000 0000这个地址是STM32的FMC功能块5的外部SRAM拓展的地址,具体可以查STM32F4拓展章节的FMC章
使用CubeMX设置STM32F429的LTDC+DMA2D显示,以及JPG图片软件解码,以及文件系统_第3张图片
使用CubeMX设置STM32F429的LTDC+DMA2D显示,以及JPG图片软件解码,以及文件系统_第4张图片
所以它在这里的地址是0XC000 0000 ,而开发板的SDRAM的大小是32M,所以 从0xC000 0000到多少自己可以计算一下
使用CubeMX设置STM32F429的LTDC+DMA2D显示,以及JPG图片软件解码,以及文件系统_第5张图片
还有这个IO口的速度要设置为最快,我用的CubeMX版本,当时默认给我配置的是最低速,我调了半天也不现实画面,搞得我很无语。

FMC

使用CubeMX设置STM32F429的LTDC+DMA2D显示,以及JPG图片软件解码,以及文件系统_第6张图片
这里同样IO口的速度要配置为最快,然后就是SDRAM的时钟,这个我没有查过这款SDRAM的数据手册,直接按照原子代码里面的设置来设置的。拿来主义嘛,呵呵。

DMA2D

使用CubeMX设置STM32F429的LTDC+DMA2D显示,以及JPG图片软件解码,以及文件系统_第7张图片

初始化代码

这些都配置完了,以后,生成一个MDK5的工程 然后准备开始移植LTDC驱动代码。这里我看了原子的代码,它兼容了屏幕,代码写的繁琐,我又看了一下微雪的代码,感觉微雪的代码写的不错,然后就将微雪的代码移植过来了。
微雪的工程可以到他们的官网下载
移植他们这部分代码

使用CubeMX设置STM32F429的LTDC+DMA2D显示,以及JPG图片软件解码,以及文件系统_第8张图片

使用CubeMX设置STM32F429的LTDC+DMA2D显示,以及JPG图片软件解码,以及文件系统_第9张图片
可以看到他们的代码驱动部分都在这个BSP_LCD_Init();函数部分。

uint8_t BSP_LCD_Init(void)
{
       
  /* Initialize the SDRAM */
  BSP_SDRAM_Init();
	BSP_LCD_SelectLayer(1);
  /* Clear the LCD Foreground layer */
  BSP_LCD_SetLayerVisible(1, DISABLE);
  /* Set Foreground Layer */
  BSP_LCD_SelectLayer(0);	
  BSP_LCD_SetLayerWindow(0,0,0,LCD_WIDTH,LCD_HEIGHT);
	

  return LCD_OK;
}

这里就是对SDRAM进一步初始化,这些和原子的代码大致相似。也就是对时钟刷新频率去编程。
当然还有对LTDC选择层。我还添加了这一段 BSP_LCD_SetLayerWindow(0,0,0,LCD_WIDTH,LCD_HEIGHT);代码,微雪的源码没有对layer的层设置也就是 第几层,起始坐标和终点坐标。
接下就需要打开背光灯这个IO口 在输入下面这段代码就可以显示了

	Paint_NewImage(LCD_WIDTH, LCD_HEIGHT, ROTATE_0, WHITE);
	Paint_Clear(WHITE);
	Paint_DrawString_EN(10, 230, "1234567890", &Font24, 0x000f, 0xfff0);
	Paint_DrawString_EN(10, 260, "ABCDEFGHIJ", &Font24, BLUE, CYAN);
	Paint_DrawString_CN(10, 290, "微雪电子", &Font24CN, BLUE, CYAN);

	Paint_DrawRectangle(200, 230, 300, 330, RED,DRAW_FILL_EMPTY, DOT_PIXEL_2X2 );
	Paint_DrawLine(200, 230, 300, 330, MAGENTA, LINE_STYLE_SOLID, DOT_PIXEL_2X2);
	Paint_DrawLine(300, 230, 200, 330, MAGENTA, LINE_STYLE_SOLID, DOT_PIXEL_2X2);
	Paint_DrawCircle(250, 280, 45, GREEN, DRAW_FILL_EMPTY, DOT_PIXEL_2X2);
	Paint_DrawImage(gImage_800X221, 0, 0, 800, 221);
	Paint_DrawString_EN(715, 0, "clear", &Font24, BLUE, CYAN);/*每个字符占17个x坐标 24个Y坐标*/

微雪的代码方便在可以设置屏幕旋转的方向。以及很多画点画线函数,字库这些。

触摸屏芯片的驱动移植

这部分其实就是IIC通讯,我用多个也是微雪的代码。但是他用的触摸芯片和正点原子触摸屏的驱动芯片不一样,所以我照着原子触摸屏初始化顺序照抄一边。

/******************************************************************************
function:GT9147芯片初始化
******************************************************************************/
void GT911_Init(void)
{
     
	uint8_t temp = 0;
	uint8_t Config_Version = 0;
	
	printf("GT911_Init\r\n");
	
	/*设置触摸屏的类型*/
	Dev_Now.touchtype = 1;
	
	/*触摸驱动芯片复位*/
	GT911_Reset();
	
	/*读取触摸芯片ID,返回触摸芯片配置版本*/
	Config_Version = GT911_Read_ID();
	
	/*软件复位GT9147,*/
	temp=0X02;	
	GT911_WR_Reg(GT911_COMMAND_REG,	(uint8_t *)&temp,1);//软复位GT9147
	
	/*是否需要冲新配置GT9147*/
	if(Config_Version<0x60)//默认版本比较低,需要更新flash配置
	{
     
		printf("Default Ver:%d\r\n",Config_Version);
		GT9147_Send_Cfg(1);//更新并保存配置
	}	
	
	/*结束复位 */ 
	HAL_Delay(10);	
	temp=0X00;	 
	GT911_WR_Reg(GT911_COMMAND_REG,(uint8_t *)&temp,1);

}

其实就是对寄存器的读写。初始化完了再移植一下触摸屏的扫描函数

const uint16_t POINT_COLOR_TBL[10]={
     RED,GREEN,BLUE,BROWN,GRED,BRED,GBLUE,LIGHTBLUE,BRRED,GRAY}; 

void ctp_test(void)
{
     
	uint8_t t=0;  	    
 	uint16_t lastpos[10][2];		//最后一次的数据 
	uint8_t maxp=5;
	while(1)
	{
     
		GT911_Scan(0);
		for(t=0;t<maxp;t++)
		{
     
			if((Dev_Now.Touch)&(1<<t))
			{
     
				if(Dev_Now.X[t]<LCD_WIDTH&&Dev_Now.Y[t]<LCD_HEIGHT)
				{
     
					if(lastpos[t][0]==0XFFFF)
					{
     
						lastpos[t][0] = Dev_Now.X[t];
						lastpos[t][1] = Dev_Now.Y[t];
					}
					Paint_DrawLine(lastpos[t][0],lastpos[t][1],Dev_Now.X[t],Dev_Now.Y[t], POINT_COLOR_TBL[t], LINE_STYLE_SOLID, DOT_PIXEL_2X2);
					lastpos[t][0]=Dev_Now.X[t];
					lastpos[t][1]=Dev_Now.Y[t];
					if(Dev_Now.X[t]>(715)&&Dev_Now.Y[t]<24)
					{
     
						Paint_NewImage(LCD_WIDTH, LCD_HEIGHT, ROTATE_0, WHITE);
						Paint_Clear(WHITE);
						Paint_DrawString_EN(715, 0, "clear", &Font24, BLUE, CYAN);/*每个字符占17个x坐标 24个Y坐标*/
					}
				}
			}else lastpos[t][0]=0XFFFF;
		} 
		
		HAL_Delay(5);
	}
}

这里就需要把原子的,清屏函数和画线函数改成微雪的两个代码就行了
Paint_DrawString_EN
Paint_DrawLine
Paint_NewImage
Paint_Clear
也就是这几个
这样就可以愉快的在屏幕上画画了
下面我会贴出源码地址,因为代码里面改动很多,所以不可能说的面面俱到,我也是经过了很多次仿真才移植成功。

FATFS文件系统

我们后面要显示图片,总是用解码好的。c文件,也太不帅了,当然是要用SD卡,然后对里面的jpg文件解码。然后来显示图片,现在写的时候ENWin还没有开始做,老是转码图片然后,存起来,太麻烦。话说回来,还是CubeMX里面设置
使用CubeMX设置STM32F429的LTDC+DMA2D显示,以及JPG图片软件解码,以及文件系统_第10张图片
这个设置比较简单,只需要使能中文那个和长文件名的设置就可以了。实在不行可以看CUBE库里面对FATFS的移植,配置好了,我们来看一下工程,

 /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_LTDC_Init();
  MX_FMC_Init();
  MX_DMA2D_Init();
  MX_USART1_UART_Init();
  MX_DMA_Init();
  MX_SDIO_SD_Init();
//  MX_FATFS_Init();
  /* USER CODE BEGIN 2 */
	
	/*LCD初始化*/
	BSP_LCD_Init();
	
	/*打开背光*/
	HAL_GPIO_WritePin(GPIOB,GPIO_PIN_5,GPIO_PIN_SET);
	
/*malloc.c中初始化内存池*/
	my_mem_init(SRAMIN);		    //初始化内部内存池
	my_mem_init(SRAMEX);		    //初始化外部内存池
	my_mem_init(SRAMCCM);		    //初始化CCM内存池 
	
/*USMART调试工具初始化*/
	usmart_dev.init(90);
	

	/*使能串口1接受中断*/
	__HAL_UART_ENABLE_IT(&huart1,UART_IT_RXNE); 
	
	/*为fatfs相关变量申请内存	*/
	exfuns_init();
	
	/*FATFS文件系统初始化,初始化SD卡并挂载SD卡*/
	if(FATFS_LinkDriver(&SD_Driver, SDPath) == 0)
		{
     
			/*##-2- Register the file system object to the FatFs module ##############*/
			if(f_mount(&SDFatFS, (TCHAR const*)SDPath, 0) != FR_OK)
			{
     
				/* FatFs Initialization Error */
				Error_Handler();
				Debug("挂载失败\r\n");
			}
			else
			{
     
				/*##-3- Create a FAT file system (format) on the logical drive #########*/
				/* WARNING: Formatting the uSD card will delete all content on the device */
				if(disk_initialize(0) != 0)//在这一步进行了SD卡初始化   f_mkfs((TCHAR const*)SDPath, FM_ANY, 0, buffer, sizeof(buffer)) != FR_OK  disk_initialize(0) != 0
				{
     
					/* FatFs Format Error */
					Error_Handler();
					Debug("SD卡初始化失败\r\n");
				}
				else
				{
            
					/*##-4- Create and Open a new text file object with write access #####*/
//					if(f_open(&SDFile, "STM32.TXT", FA_CREATE_ALWAYS | FA_WRITE) != FR_OK)
//					{
     
//						/* 'STM32.TXT' file Open for write Error */
//						Error_Handler();
//						Debug("创建文件失败\r\n");
//					}
//					else
//					{
     
//						/*##-5- Write data to the text file ################################*/
//						res = f_write(&SDFile, wtext, sizeof(wtext), (void *)&byteswritten);

//						/*##-6- Close the open text file #################################*/
//						if (f_close(&SDFile) != FR_OK )
//						{
     
//							Error_Handler();
//							Debug("关闭文件失败\r\n");
//						}
//						
//						if((byteswritten == 0) || (res != FR_OK))
//						{
     
//							/* 'STM32.TXT' file Write or EOF Error */
//							Error_Handler();
//							Debug("写文件信息失败\r\n");
//						}
//						else
//						{      
//							/*##-7- Open the text file object with read access ###############*/
//							if(f_open(&SDFile, "STM32.TXT", FA_READ) != FR_OK)
//							{
     
//								/* 'STM32.TXT' file Open for read Error */
//								Error_Handler();
//								Debug("文件打开失败\r\n");
//							}
//							else
//							{
     
//								/*##-8- Read data from the text file ###########################*/
//								res = f_read(&SDFile, rtext, sizeof(rtext), (UINT*)&bytesread);
//								
//								if((bytesread == 0) || (res != FR_OK))
//								{
     
//									/* 'STM32.TXT' file Read or EOF Error */
//									Error_Handler();
//									Debug("文件读取失败或EOF错误\r\n");
//								}
//								else
//								{
     
//									/*##-9- Close the open text file #############################*/
//									f_close(&SDFile);
//									
//									/*##-10- Compare read data with the expected data ############*/
//									if((bytesread != byteswritten))
//									{                
//										/* Read data is different from the expected data */
//										Error_Handler();
//										Debug("读数据不同\r\n");
//									}
//									else
//									{
     
										/* Success of the demo: no error occurrence */
										Debug("SD卡挂载并写入成功\r\n");
//									}
//								}
//							}
//						}
//					}
				}
			}
		}
		else
		{
     
			/* Read data is different from the expected data */
			Error_Handler();
			Debug("FATFS文件系统链接失败r\n");		
		}
		

这一段比较长,我是看了,cube的官方的移植例程,复制过来的,
// MX_FATFS_Init();我屏蔽了这一段,因为if(FATFS_LinkDriver(&SD_Driver, SDPath) == 0)这段代码调用了这个函数,初始化调用两次,就会导致disk.nbr大于文件磁盘数量。
然后挂在SD卡,就要初始化SD卡驱动,但是官方调用的,f_mkfs这个函数,这个函数对SD卡进行了初始化,但是他也把SD卡格式化了,里面的文件全部丢失,这也是我后面为什么解码时,打开图片一直失败的原因,所以这个函数也不调用了,这个函数也是最后调用了disk_initialize完成了初始化。
这里SD卡初始化需要注意,刚开始他的时钟是不能太快的,所以SDIO数据位设置位1,然后再初始化为4位,如果你使用的DMA读写SD卡,还需要修改
使用CubeMX设置STM32F429的LTDC+DMA2D显示,以及JPG图片软件解码,以及文件系统_第11张图片
这部分的函数改成
BSP_SD_ReadBlocks_DMA这个函数。其实就是去掉后面的超时时间就要了,最后再电脑串口上看到,SD卡初始化成功的信息就说明成功啦,、

先到这里,后面再贴JPG文件解码的移植,软件解码的速度真的一言难尽。

工程代码
https://download.csdn.net/download/weixin_42783751/12717911

你可能感兴趣的:(学习笔记,嵌入式,stm32)