- 九.国民技术MCU开发之 DVP模块之外接GC0308 SENSOR 并且在LCD显示图像
- 0.总体功能概述
- 1.相关开发环境
- 2. MCU DVP 硬件原理图
- 2.1 MCU DVP PIN 安排
- 3.MCU XFMC 连接LCD,参考LCD案例
- 4.GC0308配置输出648*488分辨率数据
- 5.MCU DVP相关设置
- 5.1 DVP初始化
- 5.1.1 DVP_InitInterface
- 5.2 DMA DMA配置 获取sensor输出数据
- 6.DVP获取图像数据
- 7.LCD显示MCU 获取sensor图像数据
- 7.1 SENSOR 显示帧率计算
1.通过DVP接口从摄像头采集数据,并在TFT_LCD上实时显示。
2、支持单色和彩色模式,通过DVP_demo.h中的宏 DVP_IMAGE_FORMAT 来选择
DVP_IMAGE_FORMAT = DVP_IMAGE_FORMAT_GRAY: 单色
DVP_IMAGE_FORMAT = DVP_IMAGE_FORMAT_RGB565:彩色
备注:
psram 与DVP不能共用哦,所以MCU RAM只能用内部的,不能外扩。重新设计硬件可能可行。
1.相关开发环境硬件版本:N32G457QEL_EVB V1.1
软件SDK版本 Nationstech.N32G45x_Library.1.1.1
开发软件:KEIL
2、MCU:N32G457QEL7
3、摄像头:GC0308(640*480)
4、TFT_LCD(320*240 驱动:ILI9341)
2. MCU DVP 硬件原理图
3、DMA:DMA2通道8
4、MCO:PA8
5、DVP端口:PE2:HSYNC PE3:VSYNC PE4:PCLK
PE5:D0 PE6:D1 PC0:D2 PB2:D3
PF12:D4 PF13:D5 PF14:D6 PF15:D7
6、摄像头控制端口:PA8:MCLK PG9:RESET PB7:PWDN PB8:SCL PB9:SDA
2.1 MCU DVP PIN 安排
根据实际硬件原理图以及数据手册,可知 DVP用的是重映射1
#define DVP_REMAP_MODE (GPIO_RMP1_DVP)
3.MCU XFMC 连接LCD,参考LCD案例本文省略
4.GC0308配置输出648*488分辨率数据 {0x09, 0x01}, // Window height 488
{0x0A, 0xE8},
{0x0B, 0x02}, // Window width 648
{0x0C, 0x88},
5.MCU DVP相关设置
支持DVP硬件接口,DMA获取SENSOR数据
5.1 DVP初始化
void DVPDemo_Init(void)
{
DVPDemo_InitDMA();
DVP_InitPort();
DVP_InitInterface();
DVP_InitCamera();
DVP_ConfigDma(ENABLE);
DelayUs(1000);
}
5.1.1 DVP_InitInterface
static void DVP_InitInterface(void)
{
DVP_InitType DVP_InitStruct;
RCC_EnableAPB2PeriphClk(RCC_APB2_PERIPH_DVP, ENABLE);
DVP_DeInit();
DVP_InitStruct.FifoWatermark = DVP_WATER_MARK_1;
DVP_InitStruct.LineCapture = DVP_LINE_CAPTURE_ALL;
DVP_InitStruct.ByteCapture = DVP_BYTE_CAPTURE_ALL;
DVP_InitStruct.DataInvert = DVP_DATA_NOTINVERT;
DVP_InitStruct.PixelClkPolarity = DVP_PIXEL_POLARITY_FALLING;
DVP_InitStruct.VsyncPolarity = DVP_VSYNC_POLARITY_LOW;
DVP_InitStruct.HsyncPolarity = DVP_HSYNC_POLARITY_HIGH;
DVP_InitStruct.CaptureMode = DVP_CAPTURE_MODE_SINGLE;
DVP_InitStruct.RowStart = 0;
DVP_InitStruct.ColumnStart = 0;
DVP_InitStruct.ImageHeight = DVP_IMAGE_HEIGHT;
DVP_InitStruct.ImageWidth = DVP_IMAGE_SIZE/DVP_IMAGE_HEIGHT;
DVP_Init(&DVP_InitStruct);
}
DVP_InitStruct.ImageHeight = DVP_IMAGE_HEIGHT; DVP_InitStruct.ImageWidth = DVP_IMAGE_SIZE/DVP_IMAGE_HEIGHT;
与DMA的大小一致,sensor多余输出的数据,丢弃。从这里看出MCU DVP 硬件接口接收数据的优势,可以根据RAM随意配置,不需要重新修改sensor输出
5.2 DMA DMA配置 获取sensor输出数据
static void DVPDemo_InitDMA(void)
{
DMA_InitType DMA_InitStructure;
RCC_EnableAHBPeriphClk(RCC_AHB_PERIPH_DMA2, ENABLE);
DMA_DeInit(DMA2_CH8);
DMA_InitStructure.MemAddr = (uint32_t)&DVP_Image;
DMA_InitStructure.PeriphAddr = (uint32_t) & (DVP->FIFO);
DMA_InitStructure.Direction = DMA_DIR_PERIPH_SRC;
DMA_InitStructure.BufSize = DVP_IMAGE_BUFF_SIZE;
DMA_InitStructure.PeriphInc = DMA_PERIPH_INC_DISABLE;
DMA_InitStructure.DMA_MemoryInc = DMA_MEM_INC_ENABLE;
DMA_InitStructure.PeriphDataSize = DMA_PERIPH_DATA_SIZE_WORD;
DMA_InitStructure.MemDataSize = DMA_MemoryDataSize_Word;
DMA_InitStructure.CircularMode = DMA_MODE_CIRCULAR;
DMA_InitStructure.Priority = DMA_PRIORITY_HIGH;
DMA_InitStructure.Mem2Mem = DMA_M2M_DISABLE;
DMA_Init(DMA2_CH8, &DMA_InitStructure);
DMA_EnableChannel(DMA2_CH8, ENABLE);
}
DMA_InitStructure.MemAddr = (uint32_t)&DVP_Image;
DMA_InitStructure.BufSize = DVP_IMAGE_BUFF_SIZE;
其中DVP_IMAGE_BUFF_SIZE的相关设置如下:
uint32_t DVP_Image[DVP_IMAGE_BUFF_SIZE] = {0};
#define DVP_IMAGE_FORMAT_GRAY (1)
#define DVP_IMAGE_FORMAT_RGB565 (2)
#define DVP_IMAGE_FORMAT (DVP_IMAGE_FORMAT_RGB565)
#define DVP_IMAGE_PIXEL_SIZE (DVP_IMAGE_FORMAT)
#if (DVP_IMAGE_FORMAT == DVP_IMAGE_FORMAT_GRAY)
#define DVP_IMAGE_WIDTH ((uint16_t)320)
#define DVP_IMAGE_HEIGHT ((uint16_t)240)
#else
#define DVP_IMAGE_WIDTH ((uint16_t)274)
#define DVP_IMAGE_HEIGHT ((uint16_t)206)
// #define DVP_IMAGE_WIDTH ((uint16_t)200)
// #define DVP_IMAGE_HEIGHT ((uint16_t)100)
#endif
#define DVP_IMAGE_SIZE (DVP_IMAGE_WIDTH * DVP_IMAGE_HEIGHT * DVP_IMAGE_PIXEL_SIZE)
#define DVP_IMAGE_BUFF_SIZE ((DVP_IMAGE_SIZE+3)/4)
DVP_IMAGE_BUFF_SIZE 只能用下面这么大,不然RAM超过了MCU 总RAM
#define DVP_IMAGE_WIDTH ((uint16_t)274) #define DVP_IMAGE_HEIGHT ((uint16_t)206)6.DVP获取图像数据
DVPDemo_Capture(); /Capture a picture/
void DVPDemo_Capture(void)
{
DVP_ResetFifo();
__DVP_ClrFlag(DVP_CLEAR_FLAG_FME);
// __DVP_EnableDMA();
__DVP_StartCapture();
while(__DVP_FlagIsNotSet(DVP_FLAG_FME));
__DVP_StopCapture();
// __DVP_DisableDMA();
}
手头触发获取图像数据 并保存在DVP_Image数组RAM中
7.LCD显示MCU 获取sensor图像数据由于获取的LCD W=274大于LCD 240,所以需要做横 竖转换显示
LCD 驱动芯片//mode 0
//mode 0
lcd_draw_rgbimage_rotate((LCD_WIDTH-DVP_IMAGE_HEIGHT)/2,
(LCD_HEIGHT-DVP_IMAGE_WIDTH)/2,
DVP_IMAGE_HEIGHT ,//DVP_IMAGE_HEIGHT,
DVP_IMAGE_WIDTH,//DVP_IMAGE_WIDTH,
(uint16_t *)DVP_Image);
LCD 驱动芯片//mode 5
mode 5 // lcd_draw_rgbimage((LCD_WIDTH-DVP_IMAGE_HEIGHT)/2, // (LCD_HEIGHT-DVP_IMAGE_WIDTH)/2, // DVP_IMAGE_WIDTH ,//DVP_IMAGE_HEIGHT, // DVP_IMAGE_HEIGHT,//DVP_IMAGE_WIDTH, // (uint16_t *)DVP_Image);7.1 SENSOR 显示帧率计算
while (1)
{
start_time=get_curtime();
DVPDemo_Capture();
end_time=get_curtime();
//printf("fps time is %d %drn",start_time,end_time);
#if (DVP_IMAGE_FORMAT == DVP_IMAGE_FORMAT_GRAY)
lcd_draw_image_rotate( (LCD_WIDTH-DVP_IMAGE_HEIGHT)/2,
(LCD_HEIGHT-DVP_IMAGE_WIDTH)/2,
DVP_IMAGE_HEIGHT,
DVP_IMAGE_WIDTH,
(uint8_t *)DVP_Image);
#else
//mode 0
lcd_draw_rgbimage_rotate((LCD_WIDTH-DVP_IMAGE_HEIGHT)/2,
(LCD_HEIGHT-DVP_IMAGE_WIDTH)/2,
DVP_IMAGE_HEIGHT ,//DVP_IMAGE_HEIGHT,
DVP_IMAGE_WIDTH,//DVP_IMAGE_WIDTH,
(uint16_t *)DVP_Image);
// lcd_draw_rgbimage((LCD_WIDTH-DVP_IMAGE_WIDTH)/2,
// (LCD_HEIGHT-DVP_IMAGE_HEIGHT)/2,
// DVP_IMAGE_WIDTH ,//DVP_IMAGE_HEIGHT,
// DVP_IMAGE_HEIGHT,//DVP_IMAGE_WIDTH,
// (uint16_t *)DVP_Image);
mode 5
// lcd_draw_rgbimage((LCD_WIDTH-DVP_IMAGE_HEIGHT)/2,
// (LCD_HEIGHT-DVP_IMAGE_WIDTH)/2,
// DVP_IMAGE_WIDTH ,//DVP_IMAGE_HEIGHT,
// DVP_IMAGE_HEIGHT,//DVP_IMAGE_WIDTH,
// (uint16_t *)DVP_Image);
end2_time=get_curtime();
#endif
printf("fps time is %d %d %d fps=%frn",start_time,end_time,end2_time,1000.0/(end2_time-start_time));
}
}
DVP_IMAGE_HEIGHT,//DVP_IMAGE_WIDTH,
// (uint16_t *)DVP_Image);
end2_time=get_curtime();
#endif
printf(“fps time is %d %d %d fps=%frn”,start_time,end_time,end2_time,1000.0/(end2_time-start_time));
}
}
根据1000.0/(end2_time-start_time)); 可计算当前的刷新帧率



