第4季6:图像sensor的寄存器操作
创始人
2024-03-23 21:58:09
0

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

一、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_REGISTERdelay_ms(200); //ms 因为操作可能需要耗费一定的时间sensor_write_register( 0x301A, 0x10D8 );    // RESET_REGISTERdelay_ms(200); //ms//Linear Mode Setup//AR0130 Rev1 Linear sequencer load  8-2-2011sensor_write_register( 0x3088, 0x8000 );// SEQ_CTRL_PORTsensor_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;}
#endifreturn 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)

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

相关内容

热门资讯

流动摊贩违规添加食品添加剂,公... 极目新闻通讯员 王粲 以公开促公正、以听证赢公信,近日,湖北省团风县检察院就甄某销售不合格食品行政公...
浙江义乌首创商会退出机制 制度... 中新网义乌12月27日电 题:浙江义乌首创商会退出机制 制度化探索获全国推广 作者 董易鑫 “我们正...
《办法》:建立身份透明制度,划... 专家解读|促进人工智能拟人化互动服务有序开展引领人工智能负责任创新 人工智能技术的突破正推动人机交互...
探寻强制执行律师服务,周云卿律... 在法律纠纷中,胜诉只是第一步,真正实现权益落地,强制执行环节至关重要。那么,强制执行律师服务哪家强?...
李宏毅直播称活动因不可抗力取消... 12月25日,艺人李宏毅因与芒果娱乐的经纪合同纠纷,被法院执行约1118万元款项,同时收到限制消费令...
法援故事|法援“撑腰”!13名... 绿色通道,法援接单 春节前,农民工们多次向县住建局清欠办反映情况,在工作人员协调下,郭某某给部分人出...
山西黄河壶口瀑布旅游区推出免门... 公众号转载山西经济日报稿件,须申请授权。 山西黄河壶口瀑布旅游区日前发布消息,从12月下旬至明年2...
吉利汽车旗下公司起诉知名电池企... 欣旺达(SZ300207)子公司欣旺达动力科技股份有限公司(以下简称欣旺达动力)卷入了一场高达23....
备案审查成效显著 全国人大常委... 每经记者|李彪 每经编辑|黄博文 12月24日,全国人大常委会法工委(以下简称“法工委”)法规备案...