|
本帖最后由 lyw851230 于 2019-10-16 14:56 编辑
main函数里用WM_SetCreateFlags(WM_CF_MEMDEV);图像非常清晰,实际仿真未进入 case LCD_X_SHOWBUFFER:,证明没有用到多级缓冲(尽管有GUI_ALLOC_AssignMemory((void *)GUI_BUF_ADDR, GUI_NUMBYTES);和GUI_MULTIBUF_Config(GUI_BUFFERS);)。
当屏蔽WM_SetCreateFlags(WM_CF_MEMDEV);,加入WM_MULTIBUF_Enable(1);后,图像变得不清晰。
仿真时,进入APP_LCDIF_IRQHandler,且执行GUI_MULTIBUF_Confirm(s_LCDpendingBuffer);函数,后显示出不清晰的图像,程序进入等待状态,无法进入 case LCD_X_SHOWBUFFER:
若是在任意一个控件上点击一下,进入 case LCD_X_SHOWBUFFER:程序,图像变得非常清晰。
感觉是绘图的时候没有调用 LCD_X_DisplayDriver(),请大家给支支招,怎么解决
下面是程序:
#define GUI_NUMBYTES 1000000U//设为1000K
#define GUI_BUFFERS 3
#define LCD_BUFFERS 3
#define GUI_BLOCKSIZE 0X80 //块大小
#define LCD_DIRECTION 1 //横屏
#define LCD_BITS_PER_PIXEL 16
#define LCD_BYTES_PER_PIXEL (LCD_BITS_PER_PIXEL / 8)
#define VRAM_SIZE (LCD_PIXEL_HEIGHT * LCD_PIXEL_WIDTH * LCD_BYTES_PER_PIXEL)
#define COLOR_CONVERSION GUICC_M565
#define DISPLAY_DRIVER GUIDRV_LIN_16
#define GUI_BUF_ADDR 0x80600000 //emwin动态内存
#define VRAM_ADDR 0x80700000//显存
#define USE_EXRAM 1 //使用外部RAM
static const U32 _aBufferPTR[] =
{
0x80700000,
0x80700000+VRAM_SIZE,
0x80700000+VRAM_SIZE*2
};
//__align(64) uint32_t gui_buf[2][LCD_PIXEL_HEIGHT][LCD_PIXEL_WIDTH] __attribute__((at(GUI_BUF_ADDR)));
static uint32_t lutData[ELCDIF_LUT_ENTRY_NUM];
static volatile int32_t s_LCDpendingBuffer = -1;
void GUI_X_Config(void) {
if(USE_EXRAM) //使用外部RAM
{
GUI_ALLOC_AssignMemory((void *)GUI_BUF_ADDR, GUI_NUMBYTES);
//GUI_ALLOC_SetAvBlockSize(GUI_BLOCKSIZE);
//
GUI_SetDefaultFont(GUI_FONT_6X8);
}else //使用内部RAM
{
}
}
/*******************************************************************************
* Implementation of PortAPI for emWin LCD driver
******************************************************************************/
/* Enable interrupt. */
void BOARD_EnableLcdInterrupt(void)
{
EnableIRQ(LCDIF_IRQn);
}
//三缓冲时用的中断处理函数
void APP_LCDIF_IRQHandler(void)
{
uint32_t addr;
uint32_t intStatus;
intStatus = ELCDIF_GetInterruptStatus(LCDIF);//获得中断状态,响应中断
ELCDIF_ClearInterruptStatus(LCDIF,intStatus);//清中断状态
if (intStatus & kELCDIF_CurFrameDone)
{
if (s_LCDpendingBuffer >= 0)
{
addr = VRAM_ADDR + VRAM_SIZE * s_LCDpendingBuffer;//此处的地址应该是显示的地址,显存地址会随着 s_LCDpendingBuffer变化
ELCDIF_SetNextBufferAddr(LCDIF, addr);//将显存中的数据显示出来
/* Send a confirmation that the given buffer is visible */
GUI_MULTIBUF_Confirm(s_LCDpendingBuffer);//应在挂起的前置缓冲器成为可见之后立即调用
s_LCDpendingBuffer = -1;
}
}
__DSB();
}
void LCDIF_IRQHandler(void)
{
APP_LCDIF_IRQHandler();
}
void APP_ELCDIF_Init(void)
{
const elcdif_rgb_mode_config_t lcdConfig = {
.panelWidth = LCD_PIXEL_WIDTH,
.panelHeight = LCD_PIXEL_HEIGHT,
.hsw = LCD_HSW,
.hfp = LCD_HFP,
.hbp = LCD_HBP,
.vsw = LCD_VSW,
.vfp = LCD_VFP,
.vbp = LCD_VBP,
.polarityFlags = LCD_POLARITY_FLAGS,
//.bufferAddr = (uint32_t)s_psBufferLcd[0],
.bufferAddr = VRAM_ADDR,
.pixelFormat = kELCDIF_PixelFormatRGB565,
.dataBus = kELCDIF_DataBus16Bit
};
ELCDIF_RgbModeInit(LCDIF, &lcdConfig);//初始化
BOARD_EnableLcdInterrupt();
ELCDIF_EnableInterrupts(LCDIF, kELCDIF_CurFrameDoneInterruptEnable);
NVIC_EnableIRQ(LCDIF_IRQn);
ELCDIF_RgbModeStart(LCDIF);
}
static void _CopyBuffer(int LayerIndex, int IndexSrc, int IndexDst)
{
unsigned long AddrSrc, AddrDst;
AddrSrc = VRAM_ADDR + VRAM_SIZE * IndexSrc;
AddrDst = VRAM_ADDR + VRAM_SIZE * IndexDst; //AddrDst地址也会
memcpy((void *)AddrDst, (void *)AddrSrc, VRAM_SIZE);
}
/*******************************************************************************
* Application implemented functions required by emWin library
******************************************************************************/
void LCD_X_Config(void)
{
//.......................配置开始.....................................
GUI_MULTIBUF_Config(GUI_BUFFERS);//设置3缓冲区
GUI_DEVICE_CreateAndLink(DISPLAY_DRIVER, COLOR_CONVERSION, 0, 0);//创建显示驱动器件,并关联将使用的颜色转换程序。
if(LCD_DIRECTION==0)//竖屏
{
LCD_SetSizeEx(0,LCD_PIXEL_HEIGHT,LCD_PIXEL_WIDTH); //设置可见区尺寸
LCD_SetVSizeEx(0,LCD_PIXEL_HEIGHT,LCD_PIXEL_WIDTH); //设置虚拟显示区尺寸
GUI_SetOrientation(GUI_SWAP_XY|GUI_MIRROR_Y); //设置为竖屏
}else //横屏
{
LCD_SetSizeEx(0,LCD_PIXEL_WIDTH,LCD_PIXEL_HEIGHT);
LCD_SetVSizeEx(0,LCD_PIXEL_WIDTH,LCD_PIXEL_HEIGHT);
}
//LCD_SetVRAMAddrEx(0, (void *)VRAM_ADDR);//0表示图层1,若是图层2则第一个参数为1,设置视频视频RAM的地址。仅当使用配备线性映射视频RAM的显示驱动时才需要 此函数。
LCD_SetBufferPtr((void *)_aBufferPTR);
LCD_SetDevFunc(0, LCD_DEVFUNC_COPYBUFFER, (void (*)())_CopyBuffer); //如果使用的显示控制器包括能执行复制 操作的 BitBLT 引擎,则可以利用该引擎来执行复制操作。否则,应当使用基于 DMA 的函数来完成复制 操作。
}
int LCD_X_DisplayDriver(unsigned LayerIndex, unsigned Cmd, void *pData)//显示驱动的回调函数
{
//uint32_t addr;
#if (LCD_BITS_PER_PIXEL == 16)
uint16_t colorR, colorG, colorB;
uint32_t color;
#endif
int result = 0;
switch (Cmd)
{
case LCD_X_INITCONTROLLER:
{
APP_ELCDIF_Init();//使能LCD中断、RGB mode开启
break;
}
case LCD_X_SHOWBUFFER:
{
LCD_X_SHOWBUFFER_INFO *_pData;
_pData = (LCD_X_SHOWBUFFER_INFO *)pData;
s_LCDpendingBuffer = _pData->Index;
while (s_LCDpendingBuffer >= 0)
;
return 0;
}
case LCD_X_SETLUTENTRY:
{
//
// Required for setting a lookup table entry which is passed in the 'Pos' and 'Color' element of p
//
LCD_X_SETLUTENTRY_INFO *_pData;
_pData = (LCD_X_SETLUTENTRY_INFO *)pData;
//
// Call hardware routine to write a LUT entry to the controller
//
color = _pData->Color;
colorB = (color & 0xFF0000) >> 16;
colorG = (color & 0x00FF00) >> 8;
colorR = (color & 0x0000FF);
/* 16-bit bus */
lutData[_pData->Pos] = (colorR << 11) | (colorG << 5) | (colorB);
return 0;
}
default:
result = -1;//通过返回不同值区别buffer内是否有图片或数据
break;
}
return result;
}
|
|