Я уже писал о работе с дисплеем 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