【前言】
前面的TouchGFX的LCD数据发送是使用阻塞式的发送,虽然画面比较流畅了,但是今天我成功的切换到了gpdma进行数据传送,经调试好后,画面切换以及拖动,相比以前有了非常大的提升,可谓经典丝滑,现将我的优化记录如下。
在touchGFX中主要的接口是在TouchGFXHAL.cpp中的flushFrameBuffer函数。他负责将touchGFX生成的图像,通过spi发送给LCD屏。
刷新后生成的数据块为对象rect,rect对象在定义中是如下描述的:
/**
* Initializes a new instance of the Rect class.
*
* @param rectX The x coordinate.
* @param rectY The y coordinate.
* @param rectWidth The width.
* @param rectHeight The height.
*/
里面包含了起始坐标,图像的长与宽。我们拿到这块数据的内存地址,然后通过spi发送给LCD屏。
【优化前的代码】
TouchGFXGeneratedHAL::flushFrameBuffer(rect);
volatile uint16_t* buffer = getClientFrameBuffer()+(rect.y*LCD_WIDTH)+rect.x;
lcd_set_address(rect.x, rect.y, rect.x+rect.width-1, rect.y+rect.height-1);
lcd_write_ram();
hspi1.Init.DataSize = SPI_DATASIZE_16BIT; //转换为16位工作模式
HAL_SPI_Init(&hspi1);
LCD_CS(0);
LCD_WR(1);
for(uint32_t i=0; i<rect.height; i++)
{
HAL_SPI_Transmit(&hspi1,(uint8_t *)buffer,rect.width,100);
buffer += LCD_WIDTH;
}
hspi1.Init.DataSize = SPI_DATASIZE_8BIT; //切换回8位
HAL_SPI_Init(&hspi1);
在这里我是使用HAL_SPI_Transmit来发送的。
【优化后代码】
在切换为spi_dma之前,需要在stm32cubeMX中配置GPDMA,配置如下图所示:

配置好后,还需要在spi中打开中断。

然后修改发送代码如下:
TouchGFXGeneratedHAL::flushFrameBuffer(rect);
volatile uint16_t* buffer = getClientFrameBuffer()+(rect.y*LCD_WIDTH)+rect.x;
uint32_t lenght ;
lcd_set_address(rect.x, rect.y, rect.x+rect.width-1, rect.y+rect.height-1);
lcd_write_ram();
hspi1.Init.DataSize = SPI_DATASIZE_16BIT; //修改为16位带宽
HAL_SPI_Init(&hspi1);
LCD_CS(0);
LCD_WR(1);
for(uint32_t i=0; i<rect.height; i++)
{
HAL_SPI_Transmit_DMA(&hspi1, (uint8_t *)buffer, rect.width);
while(HAL_SPI_GetState(&hspi1) != HAL_SPI_STATE_READY)
{
//osDelay(1); // 使用RTOS延迟代替空循环
}
buffer += LCD_WIDTH;
}
hspi1.Init.DataSize = SPI_DATASIZE_8BIT; //切换回8位
HAL_SPI_Init(&hspi1);
最后还需要添加两个中断回调函数:

【测试效果】
下载后,改善的效果是非常明显的,为了可视化的观察,我特意在发送前与发送后,通获取系统的tick数,执行完后,再获取,相减后通过串口打印出来。

阻塞式使用的tick数:

使用dma+16bit传递的tick:

可以看到通过优化后,提升的效果是非常之明显的。 |