Я уже писал о работе с дисплеем ILI9341.
Частота обновления экрана при этом оставляла желать лучшего. Даже после игр с частотой SPI ничего приемлемого добиться не удалось. На этой почве бросил это дело на пол пути. А недавно увидел вот такое:
Т.е. возможно и кино крутить на этом дисплее.
Сразу подумалось о DMA. Быстренько набросал такое:
u32 pixels_left = 0; u8* p_buffer; void spi1_init_dma(u8* buffer,u32 count) { DMA_InitTypeDef DMA_InitStructure; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE); /* Deinitialize DMA Streams */ DMA_DeInit(DMA2_Stream3); //SPI1_TX_DMA_STREAM if (count > MAX_DMA_REQUEST) { pixels_left = count - MAX_DMA_REQUEST; count = MAX_DMA_REQUEST; } else { pixels_left = 0; } //tx DMA_InitStructure.DMA_Channel = DMA_Channel_3; DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR); DMA_InitStructure.DMA_Memory0BaseAddr = (uint32_t)buffer; DMA_InitStructure.DMA_DIR = DMA_DIR_MemoryToPeripheral; DMA_InitStructure.DMA_BufferSize = (uint32_t)(count); DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable; DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable; DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte; DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte; DMA_InitStructure.DMA_Mode = DMA_Mode_Normal; DMA_InitStructure.DMA_Priority = DMA_Priority_High; DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable; DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_1QuarterFull; DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single; DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single; DMA_Init(DMA2_Stream3, &DMA_InitStructure); NVIC_EnableIRQ(DMA2_Stream3_IRQn); /* Разрешаем прерывание по окончанию передачи данных */ DMA_ITConfig(DMA2_Stream3, DMA_IT_TC, ENABLE); SPI_I2S_DMACmd(SPI1, SPI_I2S_DMAReq_Tx, ENABLE); } void start_dma(u8* buffer,u32 count) { spi_transfer = 1; TFT_DC_SET; TFT_CS_RESET; p_buffer = buffer; spi1_init_dma(p_buffer, count); /* Включаем DMA */ DMA_Cmd(DMA2_Stream3, ENABLE); }
Тут есть тонкий момент. Несмотря на то, что поле BufferSize в структуре имеет 32 бита, на самом деле DMA умеет передавать только 65535 байт. А нам нужно передать 320*240*2, что несколько больше. Пришлось разбить на несколько тразакций.
//tx void DMA2_Stream3_IRQHandler() { /* Проверяем наше ли это прерывание ;) */ if(DMA_GetITStatus(DMA2_Stream3, DMA_IT_TCIF3)) { spi_transfer = 0; if (pixels_left) { p_buffer+=MAX_DMA_REQUEST; spi1_init_dma(p_buffer, pixels_left); spi_transfer = 1; DMA_Cmd(DMA2_Stream3, ENABLE); } else { TFT_CS_SET; } /* Очищаем бит обработки прерывания */ DMA_ClearITPendingBit(DMA2_Stream3, DMA_IT_TCIF3); } }
Скорость увеличилась в разы. Но все равно заметно обновление кадра. Но при обновлении части экрана должно работать отлично.
PS обнаружилась проблема. GIMP экспортирует картинку в массив. Только вот слать нужно меняя байты местами. Как это сделать с DMA пока не придумал ;(
PPS Испытал дисплей со своей малиной
Пытаюсь тоже побороть тормазнутость этого дисплея, с дма натолкнулся на грабли что нужно программно дёргать DC и CS, поэтому начал делать на прерываниях SPI, но всё равно не то пальто.
Можешь поделится проектом? ну пожааааааалуйста
я по dma слал только данные изображения
https://www.dropbox.com/s/9oj0w8yae4mfs0c/tft_lcd_spi.rar