|
|
  |
LTDC + ChromART в STM, Проконсультируйте, кто работал. |
|
|
|
Aug 22 2016, 20:51
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 21-08-16
Из: Москва
Пользователь №: 93 041

|
Цитата без SDRAM или SRAM нужного размера под видео буфер не имеет практического смысла запускать Необходимо выводить только примитивы в виде кнопок и текст. Хотя убийственная мысль, что на каждый пиксель экрана необходимо минимум два байта постоянно перезаписываемой памяти, всё больше проникает в мозг. Может есть какие-то уловки с FLASH или SD картой, или ещё какие-то заклинания?! Цитата Ищите где производится инициализация LTDC и смотрите где находится видеобуфер Единственное указание на видеобуфер находится в инициализации слоя 1, пока что-то делать с ним боюсь, только расширил массив до 45000,но это - мёртвому припарки. Код displayLayer1.WindowX0 = 10; displayLayer1.WindowX1 = 790; displayLayer1.WindowY0 = 10; displayLayer1.WindowY1 = 470; displayLayer1.PixelFormat = LTDC_PIXEL_FORMAT_ARGB4444; displayLayer1.Alpha = 255; displayLayer1.Alpha0 = 250; displayLayer1.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA; displayLayer1.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA; displayLayer1.FBStartAdress = (uint32_t)&aBufferResult; displayLayer1.ImageWidth = 0; displayLayer1.ImageHeight = 0; displayLayer1.Backcolor.Blue = 250; displayLayer1.Backcolor.Green = 0; displayLayer1.Backcolor.Red = 200;
HAL_LTDC_ConfigLayer(&displayTypeDef, &displayLayer1, 0);
|
|
|
|
|
Aug 23 2016, 06:54
|
Гуру
     
Группа: Свой
Сообщений: 2 712
Регистрация: 28-11-05
Из: Беларусь, Витебск, Строителей 18-4-220
Пользователь №: 11 521

|
Цитата(adrvyho @ Aug 22 2016, 23:51)  Необходимо выводить только примитивы в виде кнопок и текст. Хотя убийственная мысль, что на каждый пиксель экрана необходимо минимум два байта постоянно перезаписываемой памяти, всё больше проникает в мозг. Может есть какие-то уловки с FLASH или SD картой, или ещё какие-то заклинания?! Вы бы почитали мой пост предварительно. Тогда бы поняли что DMA2D целесообразен только в режиме 16 или 24-битного цвета. ... Давайте поясню на пальцах. В МК есть 2 совершенно независимых узла: LTDC (контроллер дисплея) и DMA2D (ускоритель, но фактически контроллер прямого доступа к памяти позволяющий работать с прямоугольными областями памяти). LTDC фактически отображает область памяти (видеобуфер) на экран. А с помощью DMA2D вы можете модифицировать ваш видеобуфер. То есть сам DMA2D к дисплею никакого отношения не имеет. Поскольку в экране у вас ничего не хранится, то видеобуфер должен быть обязательно. Там находится то, что отображается на дисплее. Самый экономный режим для вашего МК - 8 бит (L8 - 256 цветов из палитры 16 бит или аналогичный AL44 - палитра 16 цветов с 16 градациями яркости). Для реализации потребуется 800*480 = 384 кб. У Вашего контроллера лишь 256. Выхода 3. 1) Добавить память внешнюю. Но на проводах не запаяешь. Работать не будет. Придётся переразводить плату. 2) Применить дисплей с меньшим разрешением. Например 4.3" 480*272 = 130кб. Качество картинки будет описанное выше. DMA2D будет использоваться ограниченно (только копирование и заливка). 3) Применить дисплей с собственным контроллером типа 1963 или другим. Там память находится на самом дисплее. DMA2D в этом случае теряет смысл.
|
|
|
|
|
Aug 24 2016, 16:43
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 21-08-16
Из: Москва
Пользователь №: 93 041

|
Всем спасибо большое за ответ!!! Понял всю фатальность ситуации, что запуск моей платы снова отодвинут на этап создания паттернов в PCAD. Для себя на пальцах представил ОЗУ, как участок земли определённой площади, которым я обладаю (в моём случае - 256 кв. м). Видеобуфер - это полотно, которое я могу расстелить в пределах моего участка. Полотно, зараза, большое. Пиксели - это кубики с площадью основания >= 2 кв.м. И чтобы мне расстелить полотно, нужно купить участок побольше, можно и в другом районе, дабы курьерская служба DMA2D может доставить кубики-пиксели куда угодно) Уважаемый SasaVitebsk, я ведь в случае варианта 2 могу не брать другой экран, а на своём задать область размером, допустим 400х300 на слое 1? Или нужно вначале инициализировать экран конкретно под это разрешение? Пока не выходит, хотя создал uint16_t aBufferResult[95000] (больше не создаётся). Может нужно как-то по-другому задавать видеобуфер? Тут мои знания уже конкретно плывут(
|
|
|
|
|
Aug 25 2016, 09:27
|
Гуру
     
Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702

|
Цитата(adrvyho @ Aug 24 2016, 19:43)  а на своём задать область размером, допустим 400х300 на слое 1? Или нужно вначале инициализировать экран конкретно под это разрешение? Нужно проинициализировать экран со всеми таймингами под полное разрешение, но при инициализации слоев (а именно они используют видеопамять) можно указать буфера меньшего размера. Границы будут залиты цветом фона, который можно выбрать. Можно один из слоев натравить на ПЗУ, тогда будет выводится статический логотип к примеру. Можно попробовать анимировать этот логотип, перезависывая адрес начала видеобуфера синхронно с ходом луча  PS. Я так делал - работает, но при определенных соотношениях размеров.
|
|
|
|
|
Aug 25 2016, 15:00
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 21-08-16
Из: Москва
Пользователь №: 93 041

|
Цитата(adnega @ Aug 25 2016, 09:27)  Нужно проинициализировать экран со всеми таймингами под полное разрешение, но при инициализации слоев (а именно они используют видеопамять) можно указать буфера меньшего размера. Границы будут залиты цветом фона, который можно выбрать. Именно так и сделал - задал массив aBufferResult при инициализации слоя 1, сделал заполнение 2х областей. Дык, всё равно заливаются линии, а не области!  Видимо, прокладка между рулём и сиденьем износилась) Подскажите, пожалуйста, как корректно задать видеобуфер - видимо я это совсем через пень-колоду делаю.
|
|
|
|
|
Aug 25 2016, 15:38
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 21-08-16
Из: Москва
Пользователь №: 93 041

|
Цитата(adnega @ Aug 25 2016, 15:27)  Кусок кода покажете? CODE #define PIXELWIDHT 2
#define LCD_WIDTH 800 #define LCD_HEIGHT 480
#define HFP 40 #define HSYNC 48 #define HBP 40
#define VFP 13 #define VSYNC 3 #define VBP 29
#define ACTIVE_W (HSYNC + LCD_WIDTH + HBP - 1) #define ACTIVE_H (VSYNC + LCD_HEIGHT + VBP - 1) #define DISP_ACCUM_HORIZ_BACKPORCH (HSYNC + HBP - 1) #define DISP_ACCUM_VERT_BACKPORCH (VSYNC + VBP - 1) #define TOTAL_WIDTH (HSYNC + HBP + LCD_WIDTH + HFP - 1) #define TOTAL_HEIGHT (VSYNC + VBP + LCD_HEIGHT + VFP - 1)
uint16_t aBufferResult[95000];
void Screen_Init(void) { LTDC_HandleTypeDef displayTypeDef; LTDC_LayerCfgTypeDef displayLayer1; LTDC_LayerCfgTypeDef displayLayer2; GPIO_InitStruct.Pin = GPIO_PIN_4|GPIO_PIN_5| GPIO_PIN_6|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_14|GPIO_PIN_15; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH; GPIO_InitStruct.Alternate = 14; HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_10| GPIO_PIN_11; HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_0|GPIO_PIN_1| GPIO_PIN_2|GPIO_PIN_4|GPIO_PIN_5|GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_9|GPIO_PIN_10;
HAL_GPIO_Init(GPIOI, &GPIO_InitStruct); GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3| GPIO_PIN_8|GPIO_PIN_9|GPIO_PIN_10|GPIO_PIN_11|GPIO_PIN_12|GPIO_PIN_13|GPIO_PIN_1 4|GPIO_PIN_15;
HAL_GPIO_Init(GPIOH, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_12; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_NOPULL; GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
HAL_GPIO_Init(GPIOE, &GPIO_InitStruct); HAL_GPIO_WritePin(GPIOE, GPIO_PIN_12, 1); __LTDC_CLK_ENABLE(); // PLL /* LCD clock configuration */ /* PLLSAI_VCO Input = HSE_VALUE/PLL_M = 1 MHz */ /* PLLSAI_VCO Output = PLLSAI_VCO Input * PLLSAIN = 192 MHz */ /* PLLLCDCLK = PLLSAI_VCO Output/PLLSAIR = 192/5 = 38.4 MHz */ /* LTDC clock frequency = PLLLCDCLK / LTDC_PLLSAI_DIVR_4 = 38.4/4 = 9.6MHz */ PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LTDC; PeriphClkInitStruct.PLLSAI.PLLSAIN = 192; PeriphClkInitStruct.PLLSAI.PLLSAIR = 5; PeriphClkInitStruct.PLLSAIDivR = RCC_PLLSAIDIVR_4; HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct); // enable clock for LTDC RCC->APB2ENR |= RCC_APB2ENR_LTDCEN;
// LTDC HAL_LTDC_Init(&displayTypeDef); displayTypeDef.Instance = LTDC; displayTypeDef.Init.HSPolarity = LTDC_HSPOLARITY_AL; displayTypeDef.Init.VSPolarity = LTDC_VSPOLARITY_AL; displayTypeDef.Init.DEPolarity = LTDC_DEPOLARITY_AL; displayTypeDef.Init.PCPolarity = LTDC_PCPOLARITY_IPC; displayTypeDef.Init.HorizontalSync = HSYNC-1; displayTypeDef.Init.VerticalSync = VSYNC-1; displayTypeDef.Init.AccumulatedHBP = DISP_ACCUM_HORIZ_BACKPORCH; displayTypeDef.Init.AccumulatedVBP = DISP_ACCUM_VERT_BACKPORCH; displayTypeDef.Init.AccumulatedActiveW = ACTIVE_W; displayTypeDef.Init.AccumulatedActiveH = ACTIVE_H; displayTypeDef.Init.TotalWidth = TOTAL_WIDTH; displayTypeDef.Init.TotalHeigh = TOTAL_HEIGHT; displayTypeDef.Init.Backcolor.Blue = 200; displayTypeDef.Init.Backcolor.Green = 0; displayTypeDef.Init.Backcolor.Red = 200;
HAL_LTDC_Init(&displayTypeDef);
// Layer 1 displayLayer1.WindowX0 = 210; displayLayer1.WindowX1 = 590; displayLayer1.WindowY0 = 100; displayLayer1.WindowY1 = 380; displayLayer1.PixelFormat = LTDC_PIXEL_FORMAT_ARGB4444; displayLayer1.Alpha = 255; displayLayer1.Alpha0 = 250; displayLayer1.BlendingFactor1 = LTDC_BLENDING_FACTOR1_CA; displayLayer1.BlendingFactor2 = LTDC_BLENDING_FACTOR2_CA; displayLayer1.FBStartAdress = (uint32_t)&aBufferResult; displayLayer1.ImageWidth = 0; displayLayer1.ImageHeight = 0; displayLayer1.Backcolor.Blue = 250; displayLayer1.Backcolor.Green = 0; displayLayer1.Backcolor.Red = 200; HAL_LTDC_ConfigLayer(&displayTypeDef, &displayLayer1, 0); }
static void DMA2D_Config(void) { __HAL_RCC_DMA2D_CLK_ENABLE(); /* Register to memory mode with ARGB4444 as colorMode */ Dma2dHandle.Init.Mode = DMA2D_R2M; Dma2dHandle.Init.ColorMode = DMA2D_ARGB4444; Dma2dHandle.Init.OutputOffset = 0x0;
Dma2dHandle.XferCpltCallback = TransferComplete; Dma2dHandle.XferErrorCallback = TransferError; Dma2dHandle.Instance = DMA2D; /* DMA2D Initialization */ if(HAL_DMA2D_Init(&Dma2dHandle) != HAL_OK) { } }
static void _DMA_Fill(void * pDst, int xSize, int ySize, int OffLine, uint32_t ColorIndex) {
DMA2D->CR = 0x00030000UL | (1 << 9); // Register to memory and TCIE DMA2D->OCOLR = ColorIndex; // Color to be used DMA2D->OMAR = (uint32_t)pDst; // Destination address DMA2D->OOR = OffLine; // Destination line offset DMA2D->OPFCCR = 4; // Defines the number of pixels to be transfered DMA2D->NLR = ((uint32_t)xSize << 16) | ySize; // Size configuration of area to be transfered DMA2D->CR |= 1; // Start operation // // Wait until transfer is done // while (DMA2D->CR & DMA2D_CR_START) { //__WFI(); // Sleep until next interrupt } Код _DMA_Fill(aBufferResult+10, 10, 10, 0, 0x1F0A); _DMA_Fill(aBufferResult+200, 20, 2, 0, 0x1C01); _DMA_Fill(aBufferResult+300, 50, 20, 0, 0xF0F0);
Сообщение отредактировал IgorKossak - Aug 25 2016, 17:20
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!
|
|
|
|
|
Aug 25 2016, 16:56
|
Участник

Группа: Участник
Сообщений: 19
Регистрация: 21-08-16
Из: Москва
Пользователь №: 93 041

|
Цитата(adnega @ Aug 25 2016, 15:56)  Я не спец по HAL, но Код displayLayer1.ImageWidth = 0; displayLayer1.ImageHeight = 0; по-моему, не должны быть нулевыми. почему-то, когда они не нулевые, картинка вообще безобразная Пытался выставлять 380х280
|
|
|
|
|
Sep 1 2016, 07:13
|
Участник

Группа: Участник
Сообщений: 37
Регистрация: 9-04-14
Из: Черногорск Хакасия
Пользователь №: 81 299

|
Такая запись конечно же ошибка. displayLayer1.ImageWidth = 0; displayLayer1.ImageHeight = 0; Если смотреть функцию LTDC_SetConfig() то она записывает в регистр LTDC_LxCFBLR CFBP[17:0]=displayLayer1.ImageWidth*2 (для ARGB4444 ) Сolor frame buffer pitch (по смыслу длина строки в байтах смысл pitch не смог перевести ) CFBLL[12:0]= (displayLayer1.WindowX1- displayLayer1.WindowX0)*2 (для ARGB4444) Color Frame Buffer Line Length которые задают длину строки в байтах плюс 3. Короче одно другое повторяет но на 3 больше если по крестьянски сказать.
А в регистр LTDC_LxCFBLNR = displayLayer1.ImageHeight который определяет количество линий в color frame buffer. Так что .ImageWidth ImageHeight не могут быть 0 и даже больше они должны четко соответствовать и тому что задано в displayLayer1.WindowX1 displayLayer1.WindowX0 displayLayer1.WindowY1 displayLayer1.WindowY0
Делал для 480*272 экрана и эти параметры задавал такие pLayerCfg.WindowX0 = 0; pLayerCfg.WindowX1 = 480; pLayerCfg.WindowY0 = 0; pLayerCfg.WindowY1 = 272; pLayerCfg.ImageWidth = 480; pLayerCfg.ImageHeight = 272;
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|