|
V70318-114428.rar
(7.31 MB, 下载次数: 193)
硬件配制: STM32F429 + 16位SDRAM,4.3寸MCU接口屏,要实现的功能是点击某个界面图标,将摄像头实时图像显示到屏上,显示大小为474X315. 底层窗口是用emwin画的,实时显示的摄像头图像是用的DMA的方式直接显示到屏上的(不知道emwin显示摄像头数据要怎么做?),由于摄像头还要叠加文字等,实现过程是先用DMA将摄像头数据写到buf, 采用的是双缓冲模式,两个BUF循环接收摄像头数据,然后拼到一个大BUF里。一帧数据收完后,将文字,2D线等拼加到大BUF,然后再通过DMA传输到屏上显示。但有一个问题,就是图像尺寸是474X315时,左边侧总是有一条纹在抖动,画面有脱节(见附件视频)。当改成小尺寸240X240时,这种现象要好一些,但有时也会出现这种现象,不过概率要小很多。有人说是帧同步问题,我感觉是不是是显示速度不够快引起,不知道应该改哪些,请各位指教。
部分初始化代码:
static WM_HWIN CreateCameraWindow( WM_HWIN hParent )
{
/*
.........//省略部分OV5640初始化及窗体建立部分
*/
/* 输出格式: RGB565: 2Bytes */
frame_size = DOUT_WINDOWS_SIZE*2;
DCMI_Init(); //初始化DCMI,此函数会开启帧中断
//eric: 重配置外部SRAM,错位问题解决了,速度再提升200KB/S,现在处于800-900KB/S。
pCmrbuf = mymalloc(SRAMEX, frame_size);
MultiBuffer[0] = mymalloc(SRAMEX, GRAPH_SINGLE_BUF_SIZE*4);
MultiBuffer[1] = mymalloc(SRAMEX, GRAPH_SINGLE_BUF_SIZE*4);
/* 修改指针指向 */
sdramlcd_change((u16*)(pCmrbuf));
cor_inx = GUI_Color2Index(DESKTOP_BKC);//EMWIN Color->RGB565
clr_sramlcdbuf(frame_size/2, cor_inx);
/* DMA_MDATAALIGN_WORD is essential!!, correspond to DCMI->DR,
orelse, cause split screen!! */
DCMI_DMA_Init((u32)pCmrbuf, 0, 0, DMA_MDATAALIGN_WORD, DMA_MINC_ENABLE);
jpeg_data_len = jpeg_data_ok = 0;
dcmi_rx_callback = _cbGraphXferCplt;
HAL_DMAEx_MultiBufferStart(&DMADMCI_Handler, (u32)&DCMI->DR, (u32)MultiBuffer[0], (u32)MultiBuffer[1], GRAPH_SINGLE_BUF_SIZE);//开启双缓冲
__HAL_DMA_ENABLE_IT(&DMADMCI_Handler, DMA_IT_TC); //开启传输完成中断
HAL_NVIC_SetPriority(DMA2_Stream1_IRQn, 0, 0); //DMA中断优先级
HAL_NVIC_EnableIRQ(DMA2_Stream1_IRQn);
BufToLcdDMAInit();
}
static void BufToLcdDMAInit(void)
{
__HAL_RCC_DMA2_CLK_ENABLE();//DMA2时钟使能
//__HAL_LINKDMA(&UART1_Handler,hdmatx,UART1TxDMA_Handler); //将DMA与USART1联系起来(发送DMA)
while(DMA2_Stream0->CR & 0X01);//等待DMA2_Stream0可配置
__HAL_DMA_CLEAR_FLAG(&lcdDMA_Handler, DMA_FLAG_TCIF0_4|DMA_FLAG_FEIF0_4\
|DMA_FLAG_TEIF0_4|DMA_FLAG_DMEIF0_4);
/* DMA2才支持存储器到存储器模式。存储器到存储器模式,
只要你设置好了,一启动就立即传输. M2M模式,只能使用FIFO模式 */
lcdDMA_Handler.Instance = DMA2_Stream0; //DMA2数据流0
lcdDMA_Handler.Init.Channel = DMA_CHANNEL_0; //通道1
lcdDMA_Handler.Init.Direction = DMA_MEMORY_TO_MEMORY; //外设到存储器
lcdDMA_Handler.Init.PeriphInc = DMA_PINC_ENABLE; //外设增量模式,增量值为PSIZE:2(HALFWORD)!!
lcdDMA_Handler.Init.MemInc = DMA_MINC_DISABLE; //存储器非增量模式
lcdDMA_Handler.Init.PeriphDataAlignment = DMA_PDATAALIGN_HALFWORD; //外设数据长度:16位
lcdDMA_Handler.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; //存储器数据长度:16位
lcdDMA_Handler.Init.Mode = DMA_NORMAL;//DMA_CIRCULAR; //M2M模式不能使用循环模式,所以也不能用双缓冲!!
lcdDMA_Handler.Init.Priority = DMA_PRIORITY_LOW; //高优先级
lcdDMA_Handler.Init.FIFOMode = DMA_FIFOMODE_DISABLE; //M2M只能使用FIFO模式!!使能FIFO
lcdDMA_Handler.Init.FIFOThreshold = 0;//DMA_FIFO_THRESHOLD_HALFFULL; //使用1/2的FIFO
lcdDMA_Handler.Init.MemBurst = DMA_MBURST_SINGLE; //存储器突发传输
lcdDMA_Handler.Init.PeriphBurst = DMA_PBURST_SINGLE; //外设突发单次传输
HAL_DMA_DeInit(&lcdDMA_Handler); //先清除以前的设置
HAL_DMA_Init(&lcdDMA_Handler); //初始化DMA
}
void BufToLcdDMAShow(int x, int y, int xsize, int ysize)
{
u32 lcdsize = xsize*ysize;
u32 dmatransfered = 0;
u32 tx_len;
/* Is an important sentence, decide the display area!! */
LCD_Set_Window(x, y, xsize, ysize);
LCD_SetCursor(x, y);//设置光标位置
LCD_WriteRAM_Prepare(); //开始写入GRAM
while(lcdsize)
{
__HAL_DMA_DISABLE(&lcdDMA_Handler);
while(lcdDMA_Handler.Instance->CR & 0X01); //等待DMA2_Stream0可配置
//清除上次的传输完成标记
__HAL_DMA_CLEAR_FLAG(&lcdDMA_Handler, DMA_FLAG_TCIF0_4|DMA_FLAG_FEIF0_4\
|DMA_FLAG_TEIF0_4|DMA_FLAG_DMEIF0_4);
if(lcdsize > SLCD_DMA_MAX_TRANS)
{
tx_len = SLCD_DMA_MAX_TRANS;
lcdsize -= SLCD_DMA_MAX_TRANS;
}
else
{
tx_len = lcdsize;
lcdsize = 0;
}
__HAL_UNLOCK(&lcdDMA_Handler);
HAL_DMA_Start(&lcdDMA_Handler, (u32)(sramlcdbuf + dmatransfered), (u32)&LCD->LCD_RAM, tx_len);
while(__HAL_DMA_GET_FLAG(&lcdDMA_Handler, DMA_FLAG_TCIF0_4) == RESET)
{
;//pro = __HAL_DMA_GET_COUNTER(&lcdDMA_Handler);
}
dmatransfered += tx_len;
}
__HAL_DMA_DISABLE(&lcdDMA_Handler);
}
static void DispCmrImage(void)
{
u16 cor_inx = POINT_COLOR;
int cursor_x=100,cursor_y = 100;
if(jpeg_data_ok)
{
DCMI_Stop(); //停止DCMI
if(cfr > 0)
{
/* 放大倍数图标 */
usrGUI_ShowIcon(rZoom.x1+5, rZoom.y0-10, &icoZOOM, cor_inx);//zoom
usrGUI_FillRect(&rZoom, cor_inx);
usrGUI_FillRect(&rZmbar, cor_inx);
LCD_ShowString(150, 105, 190, 145, 24, zmbuf[Zm]);
/* 亮度调节图标 */
usrGUI_FillRect(&rBrt, cor_inx);
usrGUI_ShowIcon(rBrt.x0-10, rBrt.y0 + brt*20, &icoBRT, cor_inx);
/* 激光点 */
usrGUI_ShowIcon(cursor_x, cursor_y, &icoCURSOR, cor_inx);
}
//BufToLcdDMAShow(DOUT_WINDOWS_XST, 432, DOUT_WINDOWS_XSIZE, DOUT_WINDOWS_YSIZE);
BufToLcdDMAShow(DOUT_WINDOWS_XST, DOUT_WINDOWS_YST, DOUT_WINDOWS_XSIZE, DOUT_WINDOWS_YSIZE);
jpeg_data_ok = 0;
jpeg_data_len = 0;
DCMI_Start();
}
} |
|