DVP 是摄像头接口模块,支持把摄像头输入图像数据转发给 AI 模块或者内存。
DVP 模块具有以下功能:
• 支持 RGB565、RGB422 与单通道 Y 灰度输入模式
• 支持设置帧中断
• 支持设置传输地址
• 支持同时向两个地址写数据(输出格式分别是 RGB888 与 RGB565)
• 支持丢弃不需要处理的帧
在我前面一篇博客里面简述了代码如何下载以及使用。https://blog.csdn.net/weixin_45488643/article/details/109990336如有需要自行查看。
选择dvp_ov(摄像头):
和上次一样的操作,自己先创建一个新的工程文件,然后将dvp_ov文件夹下面的代码复制到:
安装依赖库文件:
比较重要的一点,开启控制:
打开board_config.h 我自己使用的是Maix bit 开发板,所以选择如下配置文件,根据需要选择自己的开发板硬件配置。
1、 DVP初始化:
void dvp_init(uint8_t reg_len)
2、 设置 xclk 的速率。
DVP(数字摄像头接口)的时钟频率
uint32_t dvp_set_xclk_rate(uint32_t xclk_rate)
3、禁用突发传输模式
void dvp_enable_burst(void)
4、设置输出模式使能或禁用
void dvp_set_output_enable(dvp_output_mode_t index, int enable)
void dvp_set_image_format(uint32_t format)
6、设置图像接收模式,RGB 或 YUV
7、设置 DVP 图像采集尺寸
void dvp_set_image_size(uint32_t width, uint32_t height)
8、设置 AI 存放图像的地址
设置 AI 存放图像的地址,供 AI 模块进行算法处理
void dvp_set_ai_addr(uint32_t r_addr, uint32_t g_addr, uint32_t b_addr)
9、采集图像地址
设置采集图像在内存中的存放地址,可以用来显示
void dvp_set_ai_addr(uint32_t r_addr, uint32_t g_addr, uint32_t b_addr)
10、配置 DVP 中断类型
设置图像开始和结束中断状态,使能或禁用
void dvp_config_interrupt(uint32_t interrupt, uint8_t enable)
void dvp_disable_auto(void)
12、清除中断
void dvp_clear_interrupt(uint32_t interrupt)
#include
#include
#include "board_config.h"
#include "dvp.h"
#include "fpioa.h"
#include "iomem.h"
#include "lcd.h"
#include "nt35310.h"
#include "ov2640.h"
#include "ov5640.h"
#include "plic.h"
#include "sysctl.h"
#include "uarths.h"
#include "unistd.h"
static uint32_t *g_lcd_gram0;
static uint32_t *g_lcd_gram1;
volatile uint8_t g_dvp_finish_flag;
volatile uint8_t g_ram_mux;
// DVP 中断回调
static int on_irq_dvp(void *ctx) {
if (dvp_get_interrupt(DVP_STS_FRAME_FINISH)) {
/* switch gram */
dvp_set_display_addr(g_ram_mux ? (uint32_t)g_lcd_gram0
: (uint32_t)g_lcd_gram1);
dvp_clear_interrupt(DVP_STS_FRAME_FINISH);
g_dvp_finish_flag = 1;
} else {
if (g_dvp_finish_flag == 0) dvp_start_convert();
dvp_clear_interrupt(DVP_STS_FRAME_START);
}
return 0;
}
//初始化设备,使用宏定义区分board,详情修改 board_config.h
static void io_mux_init(void) {
#if BOARD_LICHEEDAN
/* Init DVP IO map and function settings */ /*初始化DVP输入输出映射和功能设置*/
fpioa_set_function(42, FUNC_CMOS_RST);
fpioa_set_function(44, FUNC_CMOS_PWDN);
fpioa_set_function(46, FUNC_CMOS_XCLK);
fpioa_set_function(43, FUNC_CMOS_VSYNC);
fpioa_set_function(45, FUNC_CMOS_HREF);
fpioa_set_function(47, FUNC_CMOS_PCLK);
fpioa_set_function(41, FUNC_SCCB_SCLK);
fpioa_set_function(40, FUNC_SCCB_SDA);
/* Init SPI IO map and function settings */ /*初始化串行接口输入输出映射和功能设置*/
fpioa_set_function(38, FUNC_GPIOHS0 + DCX_GPIONUM);
fpioa_set_function(36, FUNC_SPI0_SS3);
fpioa_set_function(39, FUNC_SPI0_SCLK);
fpioa_set_function(37, FUNC_GPIOHS0 + RST_GPIONUM);
sysctl_set_spi0_dvp_data(1);
#else
/* Init DVP IO map and function settings */ /*初始化DVP输入输出映射和功能设置*/
fpioa_set_function(11, FUNC_CMOS_RST);
fpioa_set_function(13, FUNC_CMOS_PWDN);
fpioa_set_function(14, FUNC_CMOS_XCLK);
fpioa_set_function(12, FUNC_CMOS_VSYNC);
fpioa_set_function(17, FUNC_CMOS_HREF);
fpioa_set_function(15, FUNC_CMOS_PCLK);
fpioa_set_function(10, FUNC_SCCB_SCLK);
fpioa_set_function(9, FUNC_SCCB_SDA);
/* Init SPI IO map and function settings */ /*初始化串行接口输入输出映射和功能设置*/
fpioa_set_function(8, FUNC_GPIOHS0 + DCX_GPIONUM);
fpioa_set_function(6, FUNC_SPI0_SS3);
fpioa_set_function(7, FUNC_SPI0_SCLK);
sysctl_set_spi0_dvp_data(1);
#endif
}
//初始化DVP PWOER
static void io_set_power(void) {
#if BOARD_LICHEEDAN
/* Set dvp and spi pin to 1.8V */ /*将dvp和spi引脚设为1.8V */
sysctl_set_power_mode(SYSCTL_POWER_BANK6, SYSCTL_POWER_V18);
sysctl_set_power_mode(SYSCTL_POWER_BANK7, SYSCTL_POWER_V18);
#else
/* Set dvp and spi pin to 1.8V */ /*将dvp和spi引脚设为1.8V */
sysctl_set_power_mode(SYSCTL_POWER_BANK1, SYSCTL_POWER_V18);
sysctl_set_power_mode(SYSCTL_POWER_BANK2, SYSCTL_POWER_V18);
#endif
}
int main(void) {
/* Set CPU and dvp clk */ /*设置CPU DVP时钟*/
sysctl_pll_set_freq(SYSCTL_PLL0, 800000000UL);
sysctl_pll_set_freq(SYSCTL_PLL1, 160000000UL);
sysctl_pll_set_freq(SYSCTL_PLL2, 45158400UL);
uarths_init();
io_mux_init(); //初始化DVP输入输出映射和功能设置
io_set_power(); //初始化DVP POWER
plic_init(); //初始化为外部中断
/* LCD init */
printf("LCD init\n");
/* LCD 初始化 */
lcd_init();
lcd_clear(BLACK);
lcd_draw_string(136, 70, "QingYeMuRong",
WHITE); //初始化LCD液晶显示屏,并显示黑底白字:QingYeMuRong
#if BOARD_LICHEEDAN
/*设置LCD显示方向*/
lcd_set_direction(DIR_YX_RLDU); //DIR_YX_LRDU 摄像头LCD方向自行调整
#else
lcd_set_direction(DIR_YX_RLUD);
#endif
lcd_clear(BLACK);
g_lcd_gram0 = (uint32_t *)iomem_malloc(320 * 240 * 2);
g_lcd_gram1 = (uint32_t *)iomem_malloc(320 * 240 * 2);
/* DVP init */
printf("DVP init\n");
#if OV5640
dvp_init(16);
dvp_set_xclk_rate(50000000);
dvp_enable_burst();
dvp_set_output_enable(0, 1);
dvp_set_output_enable(1, 1);
dvp_set_image_format(DVP_CFG_RGB_FORMAT);
dvp_set_image_size(320, 240);
ov5640_init();
#if 0
// OV5640_Focus_Init();
OV5640_Light_Mode(2); //set auto
OV5640_Color_Saturation(6); //default
OV5640_Brightness(8); //default
OV5640_Contrast(3); //default
// OV5640_Sharpness(33); //set auto
// OV5640_Auto_Focus();
#endif
// 初始化摄像头
#else
dvp_init(8); //初始化DVP,设置sccb寄存器长度为8
dvp_set_xclk_rate(24000000); //摄像头时钟频率
dvp_enable_burst(); //使能突发传输模式
dvp_set_output_enable(0, 1); //使能输出模式,并设置图像输出至内存
dvp_set_output_enable(1, 1); //使能输出模式,并设置图像输出至AI
dvp_set_image_format(DVP_CFG_RGB_FORMAT); //设置接收图像模式模式为RGB
dvp_set_image_size(320, 240); //设置DVP 图像采集尺寸为320*240
ov2640_init(); //初始化摄像头
#endif
//设置AI 存放图像的地址,供AI 模块进行算法处理。
//分别是红色分量地址、绿色分量地址、蓝色分量地址
dvp_set_ai_addr((uint32_t)0x40600000, (uint32_t)0x40612C00,
(uint32_t)0x40625800);
//设置采集图像在内存中的存放地址,可以用来显示。
dvp_set_display_addr((uint32_t)g_lcd_gram0);
//禁止图像开始采集中断、结束采集中断
dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 0);
dvp_disable_auto(); //禁用自动接收图像模式
/* DVP interrupt config */ /*DVP中断控制 */
printf("DVP interrupt config\n");
// 设置摄像头的中断 IRQN_DVP_INTERRUPT是数字摄像头(DVP)中断号
plic_set_priority(IRQN_DVP_INTERRUPT, 1);
plic_irq_register(
IRQN_DVP_INTERRUPT, on_irq_dvp,
NULL); // plic_irq_register注册外部中断函数,on_irq_dvp是中断回调函数
plic_irq_enable(IRQN_DVP_INTERRUPT);
/* enable global interrupt */ /*使能全局中断*/
sysctl_enable_irq();
/* system start */
printf("system start\n");
g_ram_mux = 0;
g_dvp_finish_flag = 0;
dvp_clear_interrupt(DVP_STS_FRAME_START | DVP_STS_FRAME_FINISH);
dvp_config_interrupt(DVP_CFG_START_INT_ENABLE | DVP_CFG_FINISH_INT_ENABLE, 1);
while (1) {
/* ai cal finish*/
while (g_dvp_finish_flag == 0)
;
g_dvp_finish_flag = 0;
/* display pic*/
g_ram_mux ^= 0x01;
lcd_draw_picture(0, 0, 320, 240, g_ram_mux ? g_lcd_gram0 : g_lcd_gram1);
}
iomem_free(g_lcd_gram0);
iomem_free(g_lcd_gram1);
return 0;
}