RK3568驱动OV13850摄像头模组调试过程
摄像头介绍
品牌:Omnivision
型号:CMK-OV13850
接口:MIPI
像素:1320W

OV13850彩色图像传感器是一款低电压、高性能1/3.06英寸1320万像素CMOS图像传感器,使用OmniBSI+?技术提供了单-1320万像素(4224×3136)摄像头的功能。通过串行摄像头控制总线(SCCB)接口的控制,它提供了全帧、下采样、开窗的10位MIPI图像。
OV13850拥有一个能够在10位1320万像素分辨率下以每秒24帧(fps)的速度运行的图像阵列,用户可以完全控制图像质量、格式和输出数据传输。所有需要的图像处理功能,包括曝光控制、白平衡、缺陷像素消除等,都可以通过SCCB接口进行编程。


此外,OmniBSI图像传感器使用专有的传感器技术,通过减少或消除固定图案噪声、污迹等常见的图像污染光源来提高图像质量,从而产生干净、完全稳定的彩色图像。
为了提供定制信息,OV13850包括一个单编程(OPT)存储器。OV13850拥有最多4车道的MIPI接口。
硬件连接方式如下图:摄像头的I2C接口使用RK3568的I2C4引脚,RESET, PWRDOWN使用普通IO口,三路电源供电使用LDO,LDO由普通IO来控制使能,用于控制上电时序。图像传输接口使用CSI2, 4lan MIPI接口。

RK3568设备树修改
OV13850的设备树修改可以参考其他芯片的设备树,在RK3568 Linux SDK中可以搜索到很多,主要是就是配置OV13850使用的复位控制引脚,I2C通信引脚,PWDNB引脚,三路电源上电控制引脚,CIF_CLK时钟引脚,如下面的I2C部分的设备树,调试OV13850时应首先从I2C调试开始,I2C通了后才会加载MIPI部分的驱动。
&i2c4 {status = "okay";clock-frequency = <400000>;ov13850: ov13850@10 {compatible = "ovti,ov13850";status = "okay";reg = <0x10>;clocks = <&cru CLK_CIF_OUT>;clock-names = "xvclk";power-domains = <&power RK3568_PD_VI>;pinctrl-names = "rockchip,camera_default","rockchip,camera_sleep";pinctrl-0 = <&cif_clk>;pinctrl-1 = <&cam0_sleep_pins>;//pinctrl-2 = <&cif_clk>;avdd-supply = <&avdd_2v8_camera_power>; /* 2.8v */dvdd-supply = <&dvdd_1v2_camera_power>; /* 1.2v */dovdd-supply = <&dovdd_1v8_camera_power>; /* 1.8v *//* reset and pwdn */reset-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>;pwdn-gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;rockchip,camera-module-index = <0>;rockchip,camera-module-facing = "back";rockchip,camera-module-name = "CMK-CT0116";rockchip,camera-module-lens-name = "Largan-50013A1";lens-focus = <&vm149c>;port {ov13850_out0: endpoint {remote-endpoint = <&mipi_in_ucam0>;data-lanes = <1 2 3 4>;};};};vm149c: vm149c@0c {compatible = "silicon touch,vm149c";status = "okay";reg = <0x0c>;rockchip,camera-module-index = <0>;rockchip,camera-module-facing = "back";rockchip,vcm-start-current = <20>; // 马达的启动电流rockchip,vcm-rated-current = <80>; // 马达的额定电流rockchip,vcm-step-mode = <13>; // 马达驱动 ic 的电流输出模式};};/*camera avdd 2.8V LDO poweren*/avdd_2v8_camera_power:avdd-2v8-camera-regulator {compatible = "regulator-fixed";regulator-name = "avdd_2v8_camera_power";enable-active-high;gpio = <&gpio3 RK_PA7 GPIO_ACTIVE_HIGH>;pinctrl-names = "default";pinctrl-0 = <&avdd2v8_camera_en_pin>;//regulator-always-on;};/*camera dvdd 1.2V LDO poweren*/dvdd_1v2_camera_power:dvdd-1v2-camera-regulator {compatible = "regulator-fixed";regulator-name = "dvdd_1v2_camera_power";enable-active-high;gpio = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;pinctrl-names = "default";pinctrl-0 = <&dvdd1v2_camera_en_pin>;//regulator-always-on;};/*camera dovdd 1.8V LDO poweren*/dovdd_1v8_camera_power:dovdd-1v8-camera_regulator {compatible = "regulator-fixed";regulator-name = "dovdd_1v8_camera_power";enable-active-high;gpio = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;pinctrl-names = "default";pinctrl-0 = <&dovdd1v8_camera_en_pin>;//regulator-always-on;};
MIPI部分的设备树可以参考原来开发板上提供的XC7160摄像头来修改,使用full mode ,即4lan CSI2接口,最后修改的如下。
&csi2_dphy_hw {status = "okay";
};&csi2_dphy0 {status = "okay";ports {#address-cells = <1>;#size-cells = <0>;port@0 {reg = <0>;#address-cells = <1>;#size-cells = <0>;mipi_in_ucam0: endpoint@0 {reg = <0>;remote-endpoint = <&ov13850_out0>;data-lanes = <1 2 3 4>;};};port@1 {reg = <1>;#address-cells = <1>;#size-cells = <0>;csidphy_out: endpoint@0 {reg = <0>;remote-endpoint = <&isp0_in>;};};};
};&rkisp_vir0 {status = "okay";port {#address-cells = <1>;#size-cells = <0>;isp0_in: endpoint@0 {reg = <0>;remote-endpoint = <&csidphy_out>;};};
};&rkisp_vir1 {status = "disabled";
};&csi2_dphy1 {status = "disabled";/** dphy1 only used for split mode,* can be used concurrently with dphy2* full mode and split mode are mutually exclusive*/
};&csi2_dphy2 {status = "disabled";/** dphy2 only used for split mode,* can be used concurrently with dphy1* full mode and split mode are mutually exclusive*/
};&rkisp {status = "okay";
};&rkisp_mmu {status = "okay";
};
硬件由于是公司第一次做,驱动第一次调,所以调试过程中肯定会遇到问题。果不然,设备树改好后,上电I2C通信不上,即无法使用0x10的地址来识别摄像头。而且识别的摄像头I2C从机地址是0x0b,0x0C,其中0x0C是摄像头内的一个芯片AD5823, 对应的驱动程序就是设备树中的vm149c。
经过使用 sudo i2ctransfer -f -y 4 w2@0x0c 0x30 0x0a r2 读取摄像头ID寄存器0x300A 测试,发现摄像头返回的是0x30 0x0A,总结出来的规律就是读任何寄存器,都返回的是寄存器的地址。


由于一时找不到软件的问题,就让硬件使用示波器测试了一下,三路电源上电的时序是avdd先上,之后是dovdd和dvdd,根据手册上电之间的延时大于0ns即可,如下图。示波器测量显示上电顺序是按照avdd,dovdd,dvdd的顺序,之间的延时为50us, 这个延时就是程序执行先后打开各路电源的运行时间。


之后又测量了I2C的时钟,数据线也未发现问题,测量了一下CIF_CLKOUT信号,这个信号是由RK3568输出给摄像头的,时钟频率是24M,由于摄像头I2C初始读取ID失败后,会关闭电源与时钟,所以24M的时钟只是在初始化时有,一会就没有了。
硬件测试也没有找到问题,那看来还得接着找软件的问题,当然看了不少csdn文章,之后又研究了一下ov13850的驱动程序,ov13850.c,重点看了一下__ov13850_power_on函数,这个函数。
static const char * const ov13850_supply_names[] = {"avdd", /* Analog power */"dovdd", /* Digital I/O power */"dvdd", /* Digital core power */
};static int __ov13850_power_on(struct ov13850 *ov13850)
{int ret;u32 delay_us;struct device *dev = &ov13850->client->dev;//硬件设计中摄像头的三路电源全是分别控制的,所以此power_gpio没有引脚对应,也没有设备树if (!IS_ERR(ov13850->power_gpio))gpiod_set_value_cansleep(ov13850->power_gpio, 1);usleep_range(1000, 2000);//pins_default对应设备树中的cif_clk,用于初始RK3568输出的24M时钟,此程序用于配置时钟引脚的为时钟输出功能if (!IS_ERR_OR_NULL(ov13850->pins_default)) {ret = pinctrl_select_state(ov13850->pinctrl,ov13850->pins_default);if (ret < 0)dev_err(dev, "could not set pins\n");}//设置xvclk时钟为24Mret = clk_set_rate(ov13850->xvclk, OV13850_XVCLK_FREQ);if (ret < 0)dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");if (clk_get_rate(ov13850->xvclk) != OV13850_XVCLK_FREQ)dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");ret = clk_prepare_enable(ov13850->xvclk);if (ret < 0) {dev_err(dev, "Failed to enable xvclk\n");return ret;}if (!IS_ERR(ov13850->reset_gpio))//复位信号输出为无效,即如果设备树中reset-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>,此时输出的电源就是低电平gpiod_set_value_cansleep(ov13850->reset_gpio, 0);//打开摄像头供电的三路电源,电源的打开的顺序按照ov13850_supply_names数组中定义的顺序,由于设备树中使用的regulaor来控制电源,所以这部分代码有效ret = regulator_bulk_enable(OV13850_NUM_SUPPLIES, ov13850->supplies);if (ret < 0) {dev_err(dev, "Failed to enable regulators\n");goto disable_clk;}if (!IS_ERR(ov13850->reset_gpio))//复位信号输出为有效,即如果设备树中reset-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>,此时输出的电源就是高电平gpiod_set_value_cansleep(ov13850->reset_gpio, 1);usleep_range(500, 1000);if (!IS_ERR(ov13850->pwdn_gpio))//pwdn_gpio信号输出为有效,即如果设备树中pwdn-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>,此时输出的电源就是高电平gpiod_set_value_cansleep(ov13850->pwdn_gpio, 1);/* 8192 cycles prior to first SCCB transaction */delay_us = ov13850_cal_delay(8192);usleep_range(delay_us, delay_us * 2);return 0;disable_clk:clk_disable_unprepare(ov13850->xvclk);return ret;
}
上面的程序看懂了,下面开始使用万用表来测量reset,pwdn这两个引脚的状态,由于摄像头初始化失败后会进行power_off操作,所以为了测量上电时电平是否正常,把__ov13850_power_off函数中代码关闭,使之一直保持在上电状态。
程序改好后,下载,测量,果然发现pwdn这个信号电平不对,这个信号串联了一个22欧姆的电阻,测量这两个电阻两边的电压一端是0V, 一端是1.8V,电阻坏了,换一个新的,同时检查了一下其他电阻有也坏的,一起更换。换好后,发现电平信号是低电平,电阻两端都是低电平,对着上电时序一下,上电后应该为高电平才对,修改设备树pwdn-gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_LOW>; -->pwdn-gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;同样对比了一个reset管脚,也是设备树的配置成低电平了。编译程序,开机,摄像头驱动成功加载了,能够识别到摄像头芯片的ID, 加载了视频驱动设备video0-video8, media0。

总结调试遇到的问题,硬件问题与软件问题都有,所以一定要2方面都去查找。硬件问题就是电阻坏了。软件问题是开始设备树写的并不对,先后调整了很多次最后才调试出来的。其他要说的一点就是OV13850驱动程序的reset,pwrdn引脚的有效电平问题与其他芯片驱动的有效电平的意思正好相反,reset信号是在低电平时复位,pwrdn信号是在低电平时有效,所以原来设备树中写成GPIO_ACTIVE_LOW的方式是符合常理的,是驱动程序中把电平的高低有效用反了,实际最应该修改驱动程序ov13850.c中的程序的reset, pwrdn信号的控制电平。
显示效果
显示效果如下,此时摄像头只能显示天花板上面的灯,其他物体无法成像,只有在强光照射下才能成像,因此还需要做进一步的调试。

特别鸣谢
在调试摄像头的过程中,参考了很多csdn朋友写的文章,感谢各位的分享,我也以分享的方式回馈大家。具体参考链接如下:
RK3566调试GC2053_火柴棍mcu的博客-CSDN博客
(24条消息) 摄像头ov13850移植笔记_布道师Peter的博客-CSDN博客
(7条消息) 关于RK3399平台OV13850摄像头调试的问题_ov13850摄像头好吗_溯之源的博客-CSDN博客
相关文章:

RK3568驱动OV13850摄像头模组调试过程
摄像头介绍品牌:Omnivision型号:CMK-OV13850接口:MIPI像素:1320WOV13850彩色图像传感器是一款低电压、高性能1/3.06英寸1320万像素CMOS图像传感器,使用OmniBSI?技术提供了单-1320万像素(42243136)摄像头的…...

Go项目的目录结构基本布局
前言 随着项目的代码量在不断地增长,不同的开发人员按自己意愿随意布局和创建目录结构,项目维护性就很差,代码也非常凌乱。良好的目录与文件结构十分重要,尤其是团队合作的时候,良好的目录与文件结构可以减少很多不必要…...

CHAPTER 1 Linux Filesystem Management
Linux Filesystem Management1 文件系统是什么2 文件系统的组成3 inode详解1. inode到底是什么2. inode的内容3. inode的大小4. inode的号码5. 硬链接6. 软链接4 存储区域5 常见文件系统的类型1. 根文件系统2. 虚拟文件系统3. 真文件系统4. 伪文件系统5. 网络文件系统1 文件系统…...
RocketMQ架构篇 - 读写队列与生产者如何选择队列
读、写队列 创建主题时,可以指定 writeQueueNums(写队列的个数)、readQueueNums(读队列的个数)。生产者发送消息时,使用写队列的个数返回路由信息;消费者消费消息时,使用读队列的个…...
华为OD机试真题Python实现【通信误码】真题+解题思路+代码(20222023)
通信误码 题目 信号传播过程中会出现一些误码,不同的数字表示不同的误码 ID,取值范围为 1~65535,用一个数组记录误码出现的情况,每个误码出现的次数代表误码频度,请找出记录中包含频度最高误码的最小子数组长度。 🔥🔥🔥🔥🔥👉👉👉👉👉👉 华为OD…...

【单目3D目标检测】MonoDDE论文精读与代码解析
文章目录PrefacePros and ConsAbstractContributionsPreliminaryDirect depth estimationDepth from heightPespective-n-point(PnP)PipelineDiverse Depth EstimationsRobust Depth CombinationOutput distributionSelecting and combining reliable de…...

复习 Kotlin 从小白到大牛 第二版 笔记要点
4.2.2 常量和只读变量 常量和只读变量一旦初始化就不能再被修改。在kotlin中,声明常量是在标识符的前面加上val或const val 关键字。 1. val 声明的是运行时变量,在运行时进行初始化 2.const val 声明的是编译时常量,在编译时初始化 val …...

X264简介-Android使用(二)
X264简介-Android使用(二) 4、Ubuntu上安装ffmpeg: 检查更新本地软件包(如果未更新,reboot Vmware): sudo apt update sudo apt upgrade官网下载的source文件安装: http://ffmpe…...
【独家】华为OD机试 - 统计差异值大于相似值二元组个数(C 语言解题)
最近更新的博客 华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧文章目录 最近更新的博客使用说明本期…...

掌握好Framework 才是王道~
现在面试对Android开发者的要求越来越高了!从最开始的阿里、头条、腾讯等大厂,到现在的互联网车企,面试总喜欢问道 Framework底层原理的相关问题 Android Framework的三大核心功能: 1、View.java:View工作原理,实现包…...
Codeforces Round 856 (Div. 2) A — C
Codeforces Round 856 (Div. 2) 文章目录A. Prefix and Suffix Array题目大意题目分析codeB. Not Dividing题目大意题目分析codeC. Scoring Subsequences题目大意题目分析codeA. Prefix and Suffix Array 题目大意 给出一个字符串所有的非空前后缀,判断原字符串是…...

2022年MathorCup数学建模B题无人仓的搬运机器人调度问题解题全过程文档加程序
2022年第十二届MathorCup高校数学建模 B题 无人仓的搬运机器人调度问题 原题再现 本题考虑在无人仓内的仓库管理问题之一,搬运机器人 AGV 的调度问题。更多的背景介绍请参看附件-背景介绍。对于无人仓来说,仓库的地图模型可以简化为图的数据结构。 仓库…...

开源项目的演进会遇到哪些“坑”?KubeVela 从发起到晋级 CNCF 孵化的全程回顾
作者:孙健波、曾庆国 点击查看:「开源人说」第五期《KubeVela:一场向应用交付标准的冲锋》 2023 年 2 月,**KubeVela [ 1] ** 经过全体 ToC 投票成功进入 CNCF Incubation,是云原生领域首个晋级孵化的面向应用的交付…...

MSDP实验配置
目录 配置MSDP 配置PIM SM协议 配置各PIM SM域内的静态RP 配置MSDP对等体 配置域内的MSDP对等体 AR8和AR9建立EBGP邻居 配置域间的MSDP对等体 进行实验验证 什么是MSDP MSDP(Multicast Source Discovery Protocol)组播源发现协议的简称 用来传递…...

惊!初中生也来卷了……
大家好,我是良许。 前两天在抖音直播的时候,突然来了一位不速之客…… 他自称是初中生,一开始我还有点不太相信,直到跟他连麦,听到他还略带一些稚嫩的声音,我才知道,他没有骗我…… 他说他想学…...
kafka相关配置介绍
kafka默认配置 每个kafka broker中配置文件server.properties默认必须配置的属性如下: broker.id0 num.network.threads2 num.io.threads8 socket.send.buffer.bytes1048576 socket.receive.buffer.bytes1048576 socket.request.max.bytes104857600 log.dirs/tmp/…...

【PyTorch】教程:torch.nn.Hardtanh
torch.nn.Hardtanh 原型 CLASS torch.nn.Hardtanh(min_val- 1.0, max_val1.0, inplaceFalse, min_valueNone, max_valueNone) 参数 min_val ([float]) – 线性区域的最小值,默认为 -1max_val ([float]) – 线性区域的最大值,默认为 1inplace ([bool]) …...

神垕古镇景区5A级十年都没有实现的三大主因
钧 瓷 内 参 第40期(总第371期) 2023年3月5日 神垕古镇景区5A级十年都没有实现的三大主因 这是2013年,禹州市市政府第一次提出创建5A级景区到今年三月份整整十年啊! 目前神垕古镇景区是4A级景区,5A级一直进行中&a…...
react函数组件常用的几个钩子函数useState、useEffect、useRef、useCallback
react框架react框架包括包括两大类:类组件函数组件。类组件构成:constructor自定义方法。调用方法通过this.方法名()。constructor(superstate)构造器里面必有super字段。render()方法里面写页面布局。函数组件构成:各种钩子函数return()方法…...

4N60-ASEMI高压MOS管4N60
编辑-Z 4N60在TO-220封装里的静态漏极源导通电阻(RDS(ON))为2.5Ω,是一款N沟道高压MOS管。4N60的最大脉冲正向电流ISM为16A,零栅极电压漏极电流(IDSS)为1uA,其工作时耐温度范围为-55~150摄氏度。4N60功耗(…...

SCAU期末笔记 - 数据分析与数据挖掘题库解析
这门怎么题库答案不全啊日 来简单学一下子来 一、选择题(可多选) 将原始数据进行集成、变换、维度规约、数值规约是在以下哪个步骤的任务?(C) A. 频繁模式挖掘 B.分类和预测 C.数据预处理 D.数据流挖掘 A. 频繁模式挖掘:专注于发现数据中…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
Linux简单的操作
ls ls 查看当前目录 ll 查看详细内容 ls -a 查看所有的内容 ls --help 查看方法文档 pwd pwd 查看当前路径 cd cd 转路径 cd .. 转上一级路径 cd 名 转换路径 …...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...

前端开发面试题总结-JavaScript篇(一)
文章目录 JavaScript高频问答一、作用域与闭包1.什么是闭包(Closure)?闭包有什么应用场景和潜在问题?2.解释 JavaScript 的作用域链(Scope Chain) 二、原型与继承3.原型链是什么?如何实现继承&a…...
【碎碎念】宝可梦 Mesh GO : 基于MESH网络的口袋妖怪 宝可梦GO游戏自组网系统
目录 游戏说明《宝可梦 Mesh GO》 —— 局域宝可梦探索Pokmon GO 类游戏核心理念应用场景Mesh 特性 宝可梦玩法融合设计游戏构想要素1. 地图探索(基于物理空间 广播范围)2. 野生宝可梦生成与广播3. 对战系统4. 道具与通信5. 延伸玩法 安全性设计 技术选…...

springboot整合VUE之在线教育管理系统简介
可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生,小白用户,想学习知识的 有点基础,想要通过项…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...