第4季6:图像sensor的寄存器操作

news2024/9/20 15:01:05

以下内容源于朱有鹏嵌入式课程的学习与整理,如有侵权请告知删除。

一、sensor_write_register函数的解析

在第4季4:图像sensor的驱动源码解析中写到,sensor_register_callback函数的调用关系如下:

sensor_register_callback                //位于ar0130_cmos.c文件文件
    cmos_init_sensor_exp_function       //位于ar0130_cmos.c文件文件
        sensor_init                     //位于ar0130_sensor_ctl.c文件
            sensor_init_720p_30fps      //位于ar0130_sensor_ctl.c文件
                sensor_write_register   //位于ar0130_sensor_ctl.c文件
                    sensor_i2c_init     //位于ar0130_sensor_ctl.c文件,只执行一次
                    ioctl               //I2C驱动提供给应用层的接口函数

我们重点关注其中的sensor_write_register函数,该函数主要完成对某个寄存器的赋值操作,比如在函数sensor_init_720p_30fps中,调用sensor_write_register函数的情形如下。

void sensor_init_720p_30fps()
{
//[720p30]

    sensor_write_register( 0x301A, 0x0001 );    // RESET_REGISTER
    delay_ms(200); //ms 因为操作可能需要耗费一定的时间
    sensor_write_register( 0x301A, 0x10D8 );    // RESET_REGISTER
    delay_ms(200); //ms
    //Linear Mode Setup
    //AR0130 Rev1 Linear sequencer load  8-2-2011
    sensor_write_register( 0x3088, 0x8000 );// SEQ_CTRL_PORT
    sensor_write_register( 0x3086, 0x0225 );// SEQ_DATA_PORT

//省略部分代码
}

我们来详细分析sensor_write_register函数的代码细节。

int sensor_write_register(int addr, int data)
{
#ifdef HI_GPIO_I2C    //可略过,因为这部分是使用GPIO模拟I2C的
    i2c_data.dev_addr = sensor_i2c_addr;
    i2c_data.reg_addr = addr;
    i2c_data.addr_byte_num = sensor_addr_byte;
    i2c_data.data = data;
    i2c_data.data_byte_num = sensor_data_byte;

    ret = ioctl(g_fd, GPIO_I2C_WRITE, &i2c_data);

    if (ret)
    {
        printf("GPIO-I2C write faild!\n");
        return ret;
    }
#else  //我们重点关注这部分
    if(flag_init == 0)//如果还没有执行过I2C的初始化
    {
    
	sensor_i2c_init();//执行初始化
	flag_init = 1;//之后不会再初始化
    }

    int idx = 0;
    int ret;
    char buf[8];//定义了8个字节长度的字符数组

    buf[idx++] = addr & 0xFF;//   buf[0]= 地址的低8位
    if (sensor_addr_byte == 2)//如果地址类型是16位的。
                              //对于AR0130,其寄存器地址就是16bit的,这个成立。
    {
        ret = ioctl(g_fd, I2C_16BIT_REG, 1);
        buf[idx++] = addr >> 8;// buf[1]= 16位地址的高8位
    }
    else
    {
        ret = ioctl(g_fd, I2C_16BIT_REG, 0);
    }

    if (ret < 0)
    {
        printf("CMD_SET_REG_WIDTH error!\n");
        return -1;
    }

    buf[idx++] = data;//buf[2]=数据的低8位?这里为何不“& 0xFF”呢?
    if (sensor_data_byte == 2)//如果数据长度是16位的。
                              //对于AR0130,寄存器的长度就是16位的,这个成立。
    {
        ret = ioctl(g_fd, I2C_16BIT_DATA, 1);
        buf[idx++] = data >> 8;//buf[3]=数据的高8位
    }
    else
    {
        ret = ioctl(g_fd, I2C_16BIT_DATA, 0);
    }

    if (ret)
    {
        printf("hi_i2c write faild!\n");
        return -1;
    }
    //至此,寄存器的地址、寄存器的数据都存储在buf数组中了。
    //接下来要调用I2C驱动提供给应用层的接口(即write函数)来进行真正的数据写入。
    ret = write(g_fd, buf, idx);
    if(ret < 0)
    {
        printf("I2C_WRITE error!\n");
        return -1;
    }
#endif
    return 0;
}

其中的sensor_i2c_init函数内容如下:

int sensor_i2c_init(void)
{
    if(g_fd >= 0)
    {
        return 0;
    }    
//省略部分代码
    int ret;

    g_fd = open("/dev/i2c-0", O_RDWR);//打开I2C驱动对应的设备文件
    if(g_fd < 0)
    {
        printf("Open /dev/i2c-0 error!\n");
        return -1;
    }
    //利用ioctl函数来将I2C强制转换为slave模式?i2c地址要查数据手册
    ret = ioctl(g_fd, I2C_SLAVE_FORCE, sensor_i2c_addr);
    if (ret < 0)
    {
        printf("CMD_SET_DEV error!\n");
        return ret;
    }

    return 0;
}

二、sensor寄存器的解析

对于sensor_write_register函数,它的参数1是sensor寄存器的地址,参数2是要写入sensor寄存器中的数值。如何查看sensor寄存器的地址以及某个寄存器的位含义?可以查看sensor的数据手册。这里以AR0130的数据手册《AR0130_RR_C》为例。

上面的sensor_init_720p_30fps函数的第一行代码如下,其中0x301A表示地址为0x301A的寄存器,0x0001表示要往该寄存器中写入的数值。根据注释,这行代码完成寄存器的复位工作(即复位AR0130)。

sensor_write_register( 0x301A, 0x0001 );    // RESET_REGISTER

我们通过查找数据手册来验证是否如此。在该数据手册的第7页前后有如下内容,从中可知寄存器的地址为16位的,寄存器的数据长度也是16位的。圈出的部分是地址为0x301A的寄存器的内容,可知它的名字是“reset_register”,猜想和寄存器复位(即复位AR0130)有关。

我们进一步找到这个寄存器的位含义表格(在第27页前后)。根据描述,bit[0]如果写1则会产生复位信号(复位的时候sensor如果正在采集数据,则会丢弃这帧数据)。上面的那行代码中的参数2为0x0001,这意味着给bit[0]写1,所以那行代码就是用来复位sensor的,就如注释写的一样。

三、sensor寄存器的操作实验

在数据手册的29页前后,有一个地址为0x3040的寄存器的描述,该寄存器用来设置图像的翻转。

(1)我们可以在mpp/component/isp/sensor/ar0130/ar0130_sensor_ctl.c文件中的sensor_init_720p_30fps函数的合适位置(大概330行处),修改代码如下。

//Enable Parallel Mode
sensor_write_register( 0x301A, 0x10D8); // RESET_REGISTER
sensor_write_register( 0x31D0, 0x0001); // HDR_COMP

//新添的内容,翻转是flip,镜像是mirror
//sensor_write_register( 0x3040, 0x0000);//第一次:未flip,未mirror
//sensor_write_register( 0x3040, 0x8000);//第二次:flip,未mirror,即仅水平翻转
//sensor_write_register( 0x3040, 0x4000);//第三次:未flip,但mirror,即仅垂直翻转
//sensor_write_register( 0x3040, 0xC000);//第四次:flip、mirror,即同时水平、垂直翻转

然后我们在mpp/component/isp下执行make(为了生成更改后的库形式的“应用层驱动”。这里不用执行make clean,因为Makefile感知到源码修改了,因此会更新(作为目标的)库文件)。

接着我们在mpp/sample_ortp_ar0130/venc目录下执行make clean再执行make(这里就需要先执行make clean,因为之前的操作,没有修改源码sample_venc.c,而只是修改了库文件,该目录下的Makefile不会感知到库文件的更新,从而不会更新sampl_venc。如果不make clean,执行make的时候将不进行任何操作),生成samp_venc这个可执行程序。

接着将sample_venc文件拷贝到虚拟机/home/xjh/iot/hisi_development/hisi_rootfs/目录中,然后将该目录挂载到板载系统的/mnt目录,在/mnt目录下执行“./sample_venc 0”,输入c。

接着在VLC播放器中,选择媒体,打开文件,选择sdp文件(提取码ms4a)(注意这文件里的设置要与实际对应)。此时可以看到实时画面,我们截图进行对比。

第一次:原来图像。 

第二次:水平翻转图像(flip)。 

 第三次:垂直翻转(mirror)

第四次:水平翻转与垂直翻转。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/68474.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

英文Paper写作怎么确实合适的介词?

Paper写作中&#xff0c;介词是非常常见的&#xff0c;介词虽是小词&#xff0c;数量也不多&#xff0c;但灵活多变&#xff0c;随处可见&#xff0c;功能强大而且难于掌握。我们不可小看这个角色&#xff0c;不可忽视它在不同句子中的作用&#xff0c;Paper写作过程中应该如何…

读取HDFS数据写入MySQL_大数据培训

读取HDFS数据写入MySQL 1&#xff09;将上个案例上传的文件改名 [atguiguhadoop102 datax]$ hadoop fs -mv /student.txt* /student.txt 2&#xff09;查看官方模板 [atguiguhadoop102 datax]$ python bin/datax.py -r hdfsreader -w mysqlwriter { “job”: { “content”…

高阶测试开发必备技能: k8s入门

现在稍微有点规模公司都是基于docker容器化部署技巧&#xff0c;K8s现在主流&#xff0c;应用最广的容器集群管理技术。 k8s全称kubernetes&#xff08;首字母为 k、首字母与尾字母之间有 8 个字符、尾字母为 s&#xff0c;所以简称 k8s&#xff09;&#xff0c;基于Docker容器…

微服务架构10个最重要的设计模式,带你了解,完全熟悉

自从软件开发的早期(1960年代)以来&#xff0c;解决大型软件系统中的复杂性一直是一项艰巨的任务。多年来&#xff0c;软件工程师和架构师为解决软件系统的复杂性进行了许多尝试&#xff1a;David Parnas的模块化和信息隐藏(1972)&#xff0c;Edsger W. Dijkstra的关注分离(197…

关于ElasticSearch日期格式不一致的异常,可以这么解决

最近壹哥的一个学生&#xff0c;在利用spring-data-elasticsearch访问ElasticSearch(ES)时&#xff0c;遇到了一个关于日期类型的BUG&#xff0c;困扰了很久。然后他就找壹哥给他解决&#xff0c;接下来壹哥就把解决的过程给大家复现一下&#xff0c;希望本文可以给遇到同样问题…

构建灵活订单系统,B2B撮合管理系统提升光伏企业订单管理效率

光伏系统是利用半导体光生伏特效应将太阳能转化为电能的发电系统。过去20年&#xff0c;我国光伏制造业快速发展&#xff0c;由弱变强。经过20年高速发展&#xff0c;我国在硅片、电池片、组件制造等多领域处于世界领先水平&#xff0c;我国已经成为全球第一大光伏生产国、消费…

深度学习Week9-YOLOv5-C3模块实现(Pytorch)

&#x1f368; 本文为&#x1f517;365天深度学习训练营 中的学习记录博客&#x1f366; 参考文章&#xff1a;Pytorch实战 | 第P8天&#xff1a;YOLOv5-C3模块实现(训练营内部成员可读)&#x1f356; 原作者&#xff1a;K同学啊|接辅导、项目定制了解C3的结构&#xff0c;方便…

前端Gitee + Jenkins自动化实战(转)

# 前端Gitee Jenkins自动化实战 当我们熟悉了Jenkins 的使用后&#xff0c;接下来我们来配置一个基于 vue-element-admin 的实战项目&#xff0c;来感受一下自动化流程带给我们的优势。 首先我们需要创建一个 git 项目&#xff0c;至于代码仓库可以自选&#xff0c;这里为了…

RocketMq: Windows环境-单机部署和多种主从集群场景部署

关于默认端口 broker的默认端口有3个,10911, 10912, 10909。 10911是remotingServer使用的监听端口,remotingServer主要处理以下三类消息: producer发送的消息 conumser在消费失败或者消费超时发送的消息 consumer拉取消息10912是主broker用于监听从broker请求…

HTML学生个人网站作业设计:公益专题扫黑除恶(HTML+CSS)

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

扩散模型Diffusion轻松入门

如果要问最近模型领域什么东西最火&#xff0c;应该非扩散模型莫属&#xff0c;火得我觉得不系统学习一下都不行&#xff01; 本文是我的学习笔记&#xff0c;只能叫入门文章&#xff0c;因为扩散模型的严谨数学推导公式很多&#xff0c;还没有研究透彻&#xff0c;不敢说一文…

c语言:关键字(二)

关键字一.声明的关键词—extern二.最名不符实的关键字—static一.声明的关键词—extern 首先这里问两个问题 1.变量可以跨文件访问吗&#xff1f; 2.函数可以跨文件访问吗&#xff1f; 答案是都可以 那么什么是跨文件呢&#xff1f; 我在game.c里定义show函数&#xff0c;但…

Vue2基础篇-01-Vue2 入门概述

1. 概述 该教程站在小白的角度&#xff0c;去帮助理解和使用&#xff0c;达到入门的效果&#xff1b;该教程覆盖面比较浅&#xff0c;更多详情请查阅 Vue2文档 &#xff0c;目前最新是Vue3文档&#xff0c;但是Vue2是公司目前大多数使用的&#xff1b;欢迎大家一起指正并下方留…

Unity 符号表

目录 前言 关于Unity符号表 正文 程序crash日志&#xff1a; 解析 后记 记一次 Bugly 崩溃查找过程 unity-il2cpp&#xff1a; 前言 关于Unity符号表 关于项目真机调试时的崩溃问题&#xff0c;一般可以 logcat 或 xcode 看到相关的crash日志&#xff0c;拿到崩溃时的堆…

Python均匀分布和三角形分布

文章目录均匀分布三角形分布均匀分布和三角形分布之间的关系函数备注triangular(left, mode, right)三角形分布uniform([low, high])均匀分布 均匀分布 所谓均匀分布&#xff0c;就是在事件空间中&#xff0c;所有事件的概率都是相等的连续分布&#xff0c;其概率密度为 f(x)1…

麻省理工人工智能实验室新研究!有远见的机器学习方法:能预知未来行为的AI智能体

原创/文 BFT机器人 近日&#xff0c;麻省理工学院的研究人员开发出一种新技术&#xff0c;让AI智能体能够思考更远的未来&#xff0c;寻找更合适的合作与竞争长期解决方案。 想象一个游戏规则&#xff1a;两支足球队在球场上PK&#xff0c;玩家们可以选择相互合作合作来实现目…

[附源码]Python计算机毕业设计Django学生宿舍管理系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

web前端期末大作业:云南旅游网页主题网站设计——云南城市旅游5页HTML+CSS+JavaScript

&#x1f468;‍&#x1f393;静态网站的编写主要是用 HTML DⅣV CSSJS等来完成页面的排版设计&#x1f469;‍&#x1f393;&#xff0c;一般的网页作业需要融入以下知识点&#xff1a;div布局、浮动定位、高级css、表格、表单及验证、js轮播图、音频视频Fash的应用、uli、下拉…

c + linux + cmake + arm + MQTT

先给你们看个最终代码结构吧,因为我改过的代码会加密,所以我只能放一部分源码,另外一部分源码我会直接贴在博客,具体使用我会在博客里面说明! 1.MQTTPacket源码库(MQTTPacket源码地址) 2.MQTTClient.c /*********************************************************************…

Linux中线程池的制作

一.介绍 1.1概念 一种线程使用模式。线程过多会带来调度开销&#xff0c;进而影响缓存局部性和整体性能。线程池维护着多个线程&#xff0c;等待着监督管理者分配可并发执行的任务。这避免了在处理短时间任务时创建与销毁线程的代价。线程池不仅能够保证内核的充分利用&#x…