GD32450i-EVAL学习笔记 17 - 数字摄像头接口(DCI)

2023-10-08 19:20

本文主要是介绍GD32450i-EVAL学习笔记 17 - 数字摄像头接口(DCI),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1 IO初始化

2 初始化DCI

2.1 使能DCI和DMA1

2.2 配置寄存器DCI_CTL

2.2.1 快照模式SNAP

2.2.2 时钟极性选择CKS

2.2.3 水平同步极性选择HPS

2.2.4 垂直同步极性选择VPS

2.2.5 数据格式DCIF

2.2.6 帧频率FR

2.3 配置DMA

3. 使能DCI

4. 初始化OV2640

5. 设置OV2640的像素大小

6. 初始化摄像头


数字摄像头接口是一个同步并行接口,可以从数字摄像头捕获视频和图像信息。它支持不同的
颜色空间图像,例如YUV/RGB,另外支持压缩数据的JPEG格式图像。

1 IO初始化

 DCI一般选择8bit接口,另外OV2640需要I2C接口设置寄存器。

2 初始化DCI

2.1 使能DCI和DMA1

RCU_AHB2EN |= ((uint32_t)1 << 0);  //Enable DCI
RCU_AHB1EN |= ((uint32_t)1 << 22);  //Enable DMA1

一般使用DCI都会使用DMA功能,DCI对应DMA1的通道1或通道7,这里用到的是通道7.

2.2 配置寄存器DCI_CTL

2.2.1 快照模式SNAP

0:连续捕获模式 - 连续捕获摄像头数据

1:快照模式 - 只捕获单帧,收到完整的第一帧后, 将自动禁止摄像头接口

2.2.2 时钟极性选择CKS

0:下降沿捕获

1:上升沿捕获

2.2.3 水平同步极性选择HPS

0:消隐期间低电平

1:消隐期间高电平

2.2.4 垂直同步极性选择VPS

0:消隐期间低电平

1:消隐期间高电平

2.2.5 数据格式DCIF

00:每个像素时钟捕获 8 位数据

01:每个像素时钟捕获 10 位数据

10:每个像素时钟捕获 12 位数据

11:每个像素时钟捕获 14 位数据

一般设置为8位数据

2.2.6 帧频率FR

在连续捕获模式,FR 定义帧捕获频率

00:捕获所有帧

01:每隔一帧捕获一次

10:每隔三帧捕获一次

11:保留

2.3 配置DMA

有2个DMA通道可以用于DCI,即DMA1的通道1和通道7

    DMA_CHFCTL(DMA1, CAMERA_DMA_CH) = 0;DMA_CHCTL(DMA1, CAMERA_DMA_CH) = 0;DMA_CHFCTL(DMA1, CAMERA_DMA_CH) &= ~((uint32_t)1 << 2); //Disable Multi Data ModeDMA_CHPADDR(DMA1, CAMERA_DMA_CH) = (uint32_t)&DCI_DATA;DMA_CHM0ADDR(DMA1, CAMERA_DMA_CH) = ramAddr;DMA_CHCNT(DMA1, CAMERA_DMA_CH) = (uint32_t)CAMERA_SIZE_W * CAMERA_SIZE_H * stride / 4;value = DMA_CHCTL(DMA1, CAMERA_DMA_CH);//bit6-7: channel transfer mode//bit11-12: transfer data width of peripheral//bit13-14: transfer data width of memory//bit16-17: channel priority levelvalue &= ~((uint32_t)0x03 << 11 | ((uint32_t)3 << 13) | ((uint32_t)3 << 16) | ((uint32_t)3 << 6));value |= (((uint32_t)2 << 11) | ((uint32_t)2 << 13) | ((uint32_t)2 << 16) | ((uint32_t)0 << 6));//bit9: next address generation algorithm of peripheralvalue &= ~((uint32_t)1 << 9); //Disable Peripheral's Address Auto Increasing.//bit10: next address generation algorithm of memoryvalue |= ((uint32_t)1 << 10);        //Enable Memory's Address Auto Increasing.//bit8: DMA circular modevalue |= ((uint32_t)1 << 8);        //Enable DMA Circular Mode//bit25-27: peripheral enablevalue &= ~((uint32_t)0x7 << 25);value |= ((uint32_t)0x1 << 25); //Peripheral 1(DCI is 1) is enable.DMA_CHCTL(DMA1, CAMERA_DMA_CH) = value;

ramAddr是MCU中分配给DCI的RAM空间,例如这里是分配一个数组

#define CAMERA_SIZE_W                   320
#define CAMERA_SIZE_H                   240
EXTERN uint16_t gCameraBuf[CAMERA_SIZE_W * CAMERA_SIZE_H];

摄像头采用RGB565格式,一个像素对应2个字节,所以这里用uint16_t定义这个数组变量,对应stride = 2(即RGB565是2个字节)。

2.4 配置时钟输出

    reg = RCU_CFG0;#if (PIN_DCI_XCLK == 8)/* reset the CKOUT0SRC, CKOUT0DIV and set according to ckout0_src and ckout0_div */reg &= ~(RCU_CFG0_CKOUT0SEL | RCU_CFG0_CKOUT0DIV);RCU_CFG0 = (reg | RCU_CKOUT0SRC_HXTAL | RCU_CKOUT0_DIV3);#elsereg &= ~(RCU_CFG0_CKOUT1SEL | RCU_CFG0_CKOUT1DIV);RCU_CFG0 = (reg | RCU_CKOUT1SRC_HXTAL | RCU_CKOUT1_DIV3);#endif

3. 使能DCI

void dciEnable(void)
{DMA_CHCTL(DMA1, CAMERA_DMA_CH) |= ((uint32_t)1 << 0 | ((uint32_t)0x1 << 4)); //DMA_ENABLEDCI_CTL |= ((uint32_t)1 << 14);    //DCI enableDCI_CTL |= ((uint32_t)1 << 0);            //DCI capture enable
}

主要是使能DMA和DCI。

4. 初始化OV2640

void ov2640Init(void)
{uint8_t buf[1];uint16_t i;bool_t status = 0;/* OV2640 reset */buf[0] = 0x01;status = i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0xff, buf, 1);if(status == FALSE){OV2640_INFO(Printf("ov2640 init fail 1\n"));}buf[0] = 0x80;status = i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0x12, buf, 1);if(status == FALSE){OV2640_INFO(Printf("ov2640 init fail 2\n"));}delayms(10);for(i = 0; i < sizeof(ov2640_svga_init_reg_tbl) / 2; i++){status = i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, ov2640_svga_init_reg_tbl[i][0], (uint8_t *)&(ov2640_svga_init_reg_tbl[i][1]), 1);if(status == FALSE){OV2640_INFO(Printf("ov2640 init fail 3:%d\n", i));break;}}delayms(100);for(i = 0; i < sizeof(ov2640_rgb565_reg_tbl)/2; i++){status = i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, ov2640_rgb565_reg_tbl[i][0], (uint8_t *)&(ov2640_rgb565_reg_tbl[i][1]), 1);if(status == FALSE){OV2640_INFO(Printf("ov2640 init fail 4:%d\n", i));break;}}delayms(100);
}

5. 设置OV2640的像素大小

OV2640的像素大小必须是4个倍数

void ov2640SetSize(uint16_t w, uint16_t h)
{uint16_t outh;uint16_t outw;uint8_t buf[1];if((w % 4) > 0)return;if((h % 4) > 0)return;outw = w / 4;outh = h / 4;buf[0] = 0x00;  i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0xff, buf, 1);buf[0] = 0x04;  i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0xE0, buf, 1);buf[0] = outw & 0xFF;  i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0x5A, buf, 1);buf[0] = outh & 0xFF;  i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0x5B, buf, 1);buf[0] = (outw >> 8) & 0x03;buf[0] |= (outh >> 6) & 0x04;i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0x5C, buf, 1); buf[0] = 0x00;  i2cWrite(I2C_CAMERA, OV2640_ADDRESS, 8, 0xE0, buf, 1);
}

6. 初始化摄像头

最终摄像头的内容显示到TFT屏,所以这里需要把数据丢到TLI上显示出来。

    tliLayer_t layer;ov2640Init();Printf("OV2640 ID:%x\n", ov2640GetID());ov2640SetSize(CAMERA_SIZE_W, CAMERA_SIZE_H);dciEnable();delayms(100);layer.alpha = 0xFF;layer.bufAddr = (uint32_t)gCameraBuf;//(uint32_t)0xC0000000;layer.defalutColor = 0x00FFFFFF;layer.format = FORMAT_RGB565;layer.x = 0;layer.y = 0;layer.w = CAMERA_SIZE_W;layer.h = CAMERA_SIZE_H;tliLayerInit(0, layer, 1);

这篇关于GD32450i-EVAL学习笔记 17 - 数字摄像头接口(DCI)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/167495

相关文章

利用Python快速搭建Markdown笔记发布系统

《利用Python快速搭建Markdown笔记发布系统》这篇文章主要为大家详细介绍了使用Python生态的成熟工具,在30分钟内搭建一个支持Markdown渲染、分类标签、全文搜索的私有化知识发布系统... 目录引言:为什么要自建知识博客一、技术选型:极简主义开发栈二、系统架构设计三、核心代码实现(分步解析

go中空接口的具体使用

《go中空接口的具体使用》空接口是一种特殊的接口类型,它不包含任何方法,本文主要介绍了go中空接口的具体使用,具有一定的参考价值,感兴趣的可以了解一下... 目录接口-空接口1. 什么是空接口?2. 如何使用空接口?第一,第二,第三,3. 空接口几个要注意的坑坑1:坑2:坑3:接口-空接口1. 什么是空接

使用PyTorch实现手写数字识别功能

《使用PyTorch实现手写数字识别功能》在人工智能的世界里,计算机视觉是最具魅力的领域之一,通过PyTorch这一强大的深度学习框架,我们将在经典的MNIST数据集上,见证一个神经网络从零开始学会识... 目录当计算机学会“看”数字搭建开发环境MNIST数据集解析1. 认识手写数字数据库2. 数据预处理的

java字符串数字补齐位数详解

《java字符串数字补齐位数详解》:本文主要介绍java字符串数字补齐位数,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录Java字符串数字补齐位数一、使用String.format()方法二、Apache Commons Lang库方法三、Java 11+的St

Vue 调用摄像头扫描条码功能实现代码

《Vue调用摄像头扫描条码功能实现代码》本文介绍了如何使用Vue.js和jsQR库来实现调用摄像头并扫描条码的功能,通过安装依赖、获取摄像头视频流、解析条码等步骤,实现了从开始扫描到停止扫描的完整流... 目录实现步骤:代码实现1. 安装依赖2. vue 页面代码功能说明注意事项以下是一个基于 Vue.js

Java进阶学习之如何开启远程调式

《Java进阶学习之如何开启远程调式》Java开发中的远程调试是一项至关重要的技能,特别是在处理生产环境的问题或者协作开发时,:本文主要介绍Java进阶学习之如何开启远程调式的相关资料,需要的朋友... 目录概述Java远程调试的开启与底层原理开启Java远程调试底层原理JVM参数总结&nbsMbKKXJx

如何用java对接微信小程序下单后的发货接口

《如何用java对接微信小程序下单后的发货接口》:本文主要介绍在微信小程序后台实现发货通知的步骤,包括获取Access_token、使用RestTemplate调用发货接口、处理AccessTok... 目录配置参数 调用代码获取Access_token调用发货的接口类注意点总结配置参数 首先需要获取Ac

讯飞webapi语音识别接口调用示例代码(python)

《讯飞webapi语音识别接口调用示例代码(python)》:本文主要介绍如何使用Python3调用讯飞WebAPI语音识别接口,重点解决了在处理语音识别结果时判断是否为最后一帧的问题,通过运行代... 目录前言一、环境二、引入库三、代码实例四、运行结果五、总结前言基于python3 讯飞webAPI语音

MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析

《MyBatis-Plus中Service接口的lambdaUpdate用法及实例分析》本文将详细讲解MyBatis-Plus中的lambdaUpdate用法,并提供丰富的案例来帮助读者更好地理解和应... 目录深入探索MyBATis-Plus中Service接口的lambdaUpdate用法及示例案例背景

Java8需要知道的4个函数式接口简单教程

《Java8需要知道的4个函数式接口简单教程》:本文主要介绍Java8中引入的函数式接口,包括Consumer、Supplier、Predicate和Function,以及它们的用法和特点,文中... 目录什么是函数是接口?Consumer接口定义核心特点注意事项常见用法1.基本用法2.结合andThen链