简介:
我们在之前适配FreeRTOS工程的基础上继续更新,添加LCD模块的显示功能验证。STM32H7S78-DK 开发板上集成了5寸的TFT 800*480 的RGB显示屏幕(RK050HR18-CTG)。LCD屏幕连接到了了MCU 的LTDC IP,通过LTDC 模块来驱动LCD显示屏,对应原理图如下。
LCD 屏幕原理图如下
以下时LTDC 的features 说明
从上述的参数可以看出LTDC 支持多种格式的格式数据的显示,ARGB888,RGB888,RGB565 等常用格式的显示,支持单独的background 显示配置,并且有两个独立可配置的layers 进行配置,并能将多层数据进行混合在一起显示,说明能比较形象的看出融合过程。
LCD 参数配置
LCD 的驱动主要是对屏幕参数的配置,以下是开发板使用的RK050HR18-CTG 模块的规格书中的参数说明。
从上述timing table 可以看出dclk 的推荐值为25Mhz,我们在cubemx 中配置为25Mhz ,对应配置如下,对应的始终来源为PLL3.R
根据上述timing 的参数表配置LCD 的水平方向的同步参数配置,我们都按照推荐的典型值来配置。
根据上述timing 的参数表配置LCD 的垂直方向的同步参数配置,我们都按照推荐的典型值来配置。
从以上的参数配置也可以看出,H方向的配置是按照DCLK 为单位,V 方向的配置单位为line。
水平方向和垂直方向信号的极性配置,从lcd 的手册中是都支持的,我们在可以配置为任意一种模式。
本次试验我们只使用一个layer 显示图片,我们配置layer1 参数如下。
LCD 点亮还需要配置背光控制GPIO
Cube 配置后生成对应的初始化代码,ltdc 的初始化及clk 代码如下
/** * @brief LTDC Initialization Function * @param None * @retval None */ static void MX_LTDC_Init(void) { /* USER CODE BEGIN LTDC_Init 0 */ /* USER CODE END LTDC_Init 0 */ LTDC_LayerCfgTypeDef pLayerCfg = {0}; /* USER CODE BEGIN LTDC_Init 1 */ /* USER CODE END LTDC_Init 1 */ hltdc.Instance = LTDC; hltdc.Init.HSPolarity = LTDC_HSPOLARITY_AH; hltdc.Init.VSPolarity = LTDC_VSPOLARITY_AH; hltdc.Init.DEPolarity = LTDC_DEPOLARITY_AL; hltdc.Init.PCPolarity = LTDC_PCPOLARITY_IPC; hltdc.Init.HorizontalSync = 3; hltdc.Init.VerticalSync = 3; hltdc.Init.AccumulatedHBP = 11; hltdc.Init.AccumulatedVBP = 11; hltdc.Init.AccumulatedActiveW = 811; hltdc.Init.AccumulatedActiveH = 491; hltdc.Init.TotalWidth = 819; hltdc.Init.TotalHeigh = 499; hltdc.Init.Backcolor.Blue = 0; hltdc.Init.Backcolor.Green = 0; hltdc.Init.Backcolor.Red = 0; if (HAL_LTDC_Init(&hltdc) != HAL_OK) { Error_Handler(); } pLayerCfg.WindowX0 = 0; pLayerCfg.WindowX1 = 799; pLayerCfg.WindowY0 = 0; pLayerCfg.WindowY1 = 479; pLayerCfg.PixelFormat = LTDC_PIXEL_FORMAT_RGB565; pLayerCfg.Alpha = 0xff; pLayerCfg.Alpha0 = 0; pLayerCfg.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA; pLayerCfg.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA; pLayerCfg.FBStartAdress = (uint32_t)&_acrgb565data; pLayerCfg.ImageWidth = 800; pLayerCfg.ImageHeight = 480; pLayerCfg.Backcolor.Blue = 0; pLayerCfg.Backcolor.Green = 0; pLayerCfg.Backcolor.Red = 0; if (HAL_LTDC_ConfigLayer(&hltdc, &pLayerCfg, 0) != HAL_OK) { Error_Handler(); } /* USER CODE BEGIN LTDC_Init 2 */ /* USER CODE END LTDC_Init 2 */ }
/** * @brief System Clock Configuration * @retval None */ void SystemClock_Config(void) { RCC_OscInitTypeDef RCC_OscInitStruct = {0}; RCC_ClkInitTypeDef RCC_ClkInitStruct = {0}; /** Configure the main internal regulator output voltage */ if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE0) != HAL_OK) { Error_Handler(); } /** Initializes the RCC Oscillators according to the specified parameters * in the RCC_OscInitTypeDef structure. */ RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI; RCC_OscInitStruct.HSIState = RCC_HSI_ON; RCC_OscInitStruct.HSIDiv = RCC_HSI_DIV1; RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT; RCC_OscInitStruct.PLL1.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL1.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL1.PLLM = 32; RCC_OscInitStruct.PLL1.PLLN = 300; RCC_OscInitStruct.PLL1.PLLP = 1; RCC_OscInitStruct.PLL1.PLLQ = 2; RCC_OscInitStruct.PLL1.PLLR = 2; RCC_OscInitStruct.PLL1.PLLS = 2; RCC_OscInitStruct.PLL1.PLLT = 2; RCC_OscInitStruct.PLL1.PLLFractional = 0; RCC_OscInitStruct.PLL2.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL2.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL2.PLLM = 4; RCC_OscInitStruct.PLL2.PLLN = 25; RCC_OscInitStruct.PLL2.PLLP = 2; RCC_OscInitStruct.PLL2.PLLQ = 2; RCC_OscInitStruct.PLL2.PLLR = 2; RCC_OscInitStruct.PLL2.PLLS = 2; RCC_OscInitStruct.PLL2.PLLT = 2; RCC_OscInitStruct.PLL2.PLLFractional = 0; RCC_OscInitStruct.PLL3.PLLState = RCC_PLL_ON; RCC_OscInitStruct.PLL3.PLLSource = RCC_PLLSOURCE_HSI; RCC_OscInitStruct.PLL3.PLLM = 4; RCC_OscInitStruct.PLL3.PLLN = 25; RCC_OscInitStruct.PLL3.PLLP = 2; RCC_OscInitStruct.PLL3.PLLQ = 2; RCC_OscInitStruct.PLL3.PLLR = 16; RCC_OscInitStruct.PLL3.PLLS = 2; RCC_OscInitStruct.PLL3.PLLT = 2; RCC_OscInitStruct.PLL3.PLLFractional = 0; if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { Error_Handler(); } /** Initializes the CPU, AHB and APB buses clocks */ RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2 |RCC_CLOCKTYPE_PCLK4|RCC_CLOCKTYPE_PCLK5; RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK; RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1; RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2; RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2; RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2; RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2; RCC_ClkInitStruct.APB5CLKDivider = RCC_APB5_DIV2; if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_7) != HAL_OK) { Error_Handler(); } }
将程序下载到板卡中运行本地配置的frame buff 中的数据已经按照预期的进行显示了,LTDC 模块已经正常工作了。
在FreeRtos 添加代码刷新显示,图片资源是直接加载flash 中的资源
void start_task1(void *pvParameters) { while(1) { printf("task2 .\r\n"); HAL_LTDC_SetAddress(&hltdc, (uint32_t)&_acrgb565data, 0); HAL_LTDC_Reload( &hltdc,LTDC_RELOAD_IMMEDIATE); vTaskDelay(1000); HAL_LTDC_SetAddress(&hltdc, (uint32_t)&eepwlogo1, 0); HAL_LTDC_Reload( &hltdc,LTDC_RELOAD_IMMEDIATE); vTaskDelay(1000); } }