|
如题,板子是407,屏幕是8bits的并口屏,fsmc通讯,在使用fsmc打点/区域填充刷新时效果如图二,使用dma后反正失真了,如图一,请求下这是问什么?头文件:#define LCD_DRI_FSMC 1
#if LCD_DRI_FSMC
#define LCD_DRI_FSMC_DMA 1
#define FSMC_DMA_STREAM_IRQ DMA2_Stream7_IRQn
#define FSMC_DMA_STREAM_IRQFun DMA2_Stream7_IRQHandler
#endif
/*
说明:ST77916驱动接口为8080时序,采用FSMC+DMA实现
2^26 =0X0400 0000 = 64MB,每个 BANK 有4*64MB = 256MB
64MB:FSMC_Bank1_NORSRAM1:0X6000 0000 ~ 0X63FF FFFF
64MB:FSMC_Bank1_NORSRAM2:0X6400 0000 ~ 0X67FF FFFF
64MB:FSMC_Bank1_NORSRAM3:0X6800 0000 ~ 0X6BFF FFFF
64MB:FSMC_Bank1_NORSRAM4:0X6C00 0000 ~ 0X6FFF FFFF
选择BANK1-BORSRAM4 连接 TFT,地址范围为0X6C00 0000 ~ 0X6FFF FFFF
使用FSMC地址线的A18 接LCD的DC(即Rs引脚,命令/数据选择)脚
寄存器基地址 = 0X6C00 0000
16位数据时: 16bits ==>> FSMC[24:0] == HADDR[25:1]
8位数据时: 8bits ==>> FSMC[25:0] == HADDR[25:0]
16位数据FSMC_A18>> RAM BASE = 0x6C00 0000 + 2^18*2 = 0x6C080000
8位数据FSMC_A18>> RAM BASE = 0x6C00 0000 + 2^18 = 0x6C040000
当选择不同的地址线时,地址要重新计算
*/
/**************** ST77916 显示屏的 FSMC 参数定义 **********/
#define FSMC_BANK1_NORSRAMX (0x6C000000)
#define FSMC_ST77916_BASE ((uint32)(FSMC_BANK1_NORSRAMX | 0x00000000))
//FSMC_Bank4_NORSRAM用于LCD命令操作的地址
#define FSMC_Addr_ST77916_CMD (FSMC_ST77916_BASE)
//FSMC_Bank1_NORSRAM用于LCD数据操作的地址
#define FSMC_Addr_ST77916_DATA ((FSMC_ST77916_BASE + (1 <<18))) c文件dma配置:static void ST77916_DmaTranCfg(void)
{
__HAL_RCC_DMA2_CLK_ENABLE();
/* Configure DMA request hdma_memtomem_dma2_stream7 on DMA2_Stream7 */
hdma_memtomem_dma2_stream7.Instance = DMA2_Stream7;
hdma_memtomem_dma2_stream7.Init.Channel = DMA_CHANNEL_0;
hdma_memtomem_dma2_stream7.Init.Direction = DMA_MEMORY_TO_MEMORY;
hdma_memtomem_dma2_stream7.Init.PeriphInc = DMA_PINC_ENABLE;
hdma_memtomem_dma2_stream7.Init.MemInc = DMA_MINC_ENABLE;
hdma_memtomem_dma2_stream7.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD;
hdma_memtomem_dma2_stream7.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD;
hdma_memtomem_dma2_stream7.Init.Mode = DMA_NORMAL;
hdma_memtomem_dma2_stream7.Init.Priority = DMA_PRIORITY_LOW;
hdma_memtomem_dma2_stream7.Init.FIFOMode = DMA_FIFOMODE_DISABLE;
hdma_memtomem_dma2_stream7.Init.FIFOThreshold = DMA_FIFO_THRESHOLD_FULL;
hdma_memtomem_dma2_stream7.Init.MemBurst = DMA_MBURST_INC8;
hdma_memtomem_dma2_stream7.Init.PeriphBurst = DMA_PBURST_INC8;
if (HAL_DMA_Init(&hdma_memtomem_dma2_stream7) != HAL_OK)
{
ERR_HANDLER();
}
/* DMA2_Stream7_IRQn interrupt configuration */
HAL_NVIC_SetPriority(FSMC_DMA_STREAM_IRQ, FSMC_DMA_MAIN_PRIO, FSMC_DMA_SUB_PRIO);
HAL_NVIC_EnableIRQ(FSMC_DMA_STREAM_IRQ);
/* 注册DMA传输完成中断 */
HAL_DMA_RegisterCallback(&hdma_memtomem_dma2_stream7, HAL_DMA_XFER_CPLT_CB_ID, lv_FsmcDmaCallBack);
}
/**
* @brief LCD DMA传输完成中断函数
* @param 无
* @retval 无
*/
void FSMC_DMA_STREAM_IRQFun(void)
{
HAL_DMA_IRQHandler(&hdma_memtomem_dma2_stream7);
}void ST77916_DispFill(uint16 usX1, uint16 usY1, uint16 usX2, uint16 usY2,const uint16 *pData)
{
#if LCD_DRI_FSMC_DMA
uint32 temp = ((usX2 +1 -usX1) * (usY2 +1 -usY1));
ST77916_WriteCmd(CMD_SetCoordinateX);
ST77916_WriteData(usX1 >> 8);
ST77916_WriteData(usX1 & 0xFF);
ST77916_WriteData(usX2 >>8);
ST77916_WriteData(usX2 & 0xFF);
ST77916_WriteCmd(CMD_SetCoordinateY);
ST77916_WriteData(usY1 >> 8);
ST77916_WriteData(usY1 & 0xFF);
ST77916_WriteData(usY2 >> 8);
ST77916_WriteData(usY2 & 0xFF);
ST77916_WriteCmd(CMD_SetPixel);
HAL_DMA_Start_IT(&hdma_memtomem_dma2_stream7, (uint32)pData, FSMC_Addr_ST77916_DATA, temp);
#else
for (uint16 y_start = usY1;y_start <=usY2;y_start++) // 逐行显示
{
ST77916_WriteCmd(CMD_SetCoordinateX);
ST77916_WriteData(usX1 >> 8);
ST77916_WriteData(usX1 & 0xFF);
ST77916_WriteCmd(CMD_SetCoordinateY);
ST77916_WriteData(y_start >> 8);
ST77916_WriteData(y_start & 0xFF);
ST77916_WriteCmd(CMD_SetPixel);
for (uint16 x_start = usX1; x_start <= usX2; x_start++) //1行中从左到右逐个像素
{
ST77916_WriteData((*pData) >> 0x08);
ST77916_WriteData((*pData) & 0xFF);
pData++;
}
}
#endif
}static void disp_flush(lv_disp_drv_t * disp_drv, const lv_area_t * area, lv_color_t * color_p)
{
if(disp_flush_enabled) {
/*The most simple case (but also the slowest) to put all pixels to the screen one-by-one*/
#if 0 // 打点
int32_t x;
int32_t y;
for(y = area->y1; y <= area->y2; y++) {
for(x = area->x1; x <= area->x2; x++) {
/*Put a pixel to the display. For example:*/
/*put_px(x, y, *color_p)*/
ST77916_DrawPoint(x,y,color_p->full);
color_p++;
}
}
#else // 区域填充
ST77916_DispFill(area->x1,area->y1,area->x2,area->y2,(uint16 *)color_p);
#endif
}
/*IMPORTANT!!!
*Inform the graphics library that you are ready with the flushing*/
#if !LCD_DRI_FSMC_DMA
lv_disp_flush_ready(disp_drv);
#endif
}
#if LCD_DRI_FSMC_DMA
/* DMA 传输完成中断回调函数 */
void lv_FsmcDmaCallBack(DMA_HandleTypeDef *_Hdma)
{
//lv_disp_flush_ready(&disp_drv);
lv_disp_flush_ready(lv_disp_get_default()->driver);
}
#endif
|
-
使用fsmc+DMA刷新
-
使用fsmc刷新
|