OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 8772|回复: 15

OV2640时钟频率和帧率的计算

[复制链接]

3

主题

347

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
2082
金钱
2082
注册时间
2014-12-19
在线时间
711 小时
发表于 2016-10-11 14:55:32 | 显示全部楼层 |阅读模式
本帖最后由 lvehe 于 2016-10-11 14:56 编辑

经本人耐心搜寻和潜心研究,终于摸清了OV2640时钟频率和帧率计算的窍门。
主要依据以下2个权威资料:
《OV2640 datasheet 2.2》中图13~15分别给出UXGA、SVGA和CIF的帧时序图。
《OV2640 Camera Module Software Application Notes 1.04》中第3节“How to Adjust frame rate”中只给出了几个示例,并没有提到具体的公式。

具体来说,其中的0x3D(0xFF=0x01)会影响时钟频率,而datasheet中却是作为保留寄存器未透露任何信息。Datasheet中可查到的0x11则是影响分频系数,二者共同决定最终的时钟频率。

帧率则稍微复杂一点,帧率=时钟频率÷每行像素数÷每帧总行数÷虚拟帧数。其中 每行像素数=每行有效像素数+每行虚拟像素数。以UXGA模式为例,有效像素数为1922。虚拟像素数则为用户自定义的无效像素数。每帧总行数=每帧有效行数+每帧虚拟行数。以UXGA模式为例,每帧有效行数为1248。这里的 虚拟帧数=有效帧+虚拟帧,有效帧总为1,通常虚拟帧为0,则总的帧数为1。如果修改了0x03寄存器,一个有效帧后面可能会带上若干个无效帧,帧率就会成倍的下降。可以把虚拟像素、虚拟行数和虚拟帧认为都是用于填补行、帧之间的空隙的无效时间段。

以《OV2640 Camera Module Software Application Notes 1.04》中3.6节“UXGA Capture, 7.14fps, 24 Mhz input clock”为例:
write_SCCB(0xff, 0x01);
write_SCCB(0x11, 0x01);
write_SCCB(0x12, 0x00);
write_SCCB(0x2a, 0x00);
write_SCCB(0x2b, 0x00);
write_SCCB(0x46, 0x3f);
write_SCCB(0x47, 0x00);
write_SCCB(0x3d, 0x34);

先计算 时钟频率=24000000*(0x40-0x34)/2/2/4=18000000Hz。
再计算 帧率=18000000/(1922+0x00)/(1248+0x3f)/1=7.14fps。由于没有提到0x03寄存器的值,这里假设为默认值。


[mw_shl_code=c,true]#define  OV2640_XVCLK  24000000

uint32_t OV2640_LinePixels[3] = {1922, 595, 1190}; //UXGA, CIF, SVGA
uint32_t OV2640_FrameLines[3] = {1248, 336, 672};  //UXGA, CIF, SVGA

//获取分辨率 UXGA:0, CIF:1, SVGA:2
uint8_t OV2640_GetResMode(void)
{
        uint8_t Res;
        OV2640_WriteReg(0xFF, 0x01);
        Res = ((OV2640_ReadReg(0x12) & 0x70) >> 5);
        return Res;
}

//获取虚拟像素
uint32_t OV2640_GetDummyPixel(void)
{
        uint32_t Dummy_Pixel;
        
        OV2640_WriteReg(0xFF, 0x01);
        Dummy_Pixel = ((uint32_t)(OV2640_ReadReg(0x2A) & 0xF0) << 4) + OV2640_ReadReg(0x2B);
        return Dummy_Pixel;
}

//获取虚拟行数
uint32_t OV2640_GetDummyLines(void)
{
        uint32_t Dummy_Lines;
        
        OV2640_WriteReg(0xFF, 0x01);
        Dummy_Lines = ((uint32_t)OV2640_ReadReg(0x47) << 8) + OV2640_ReadReg(0x46);
        return Dummy_Lines;
}

//获取虚拟帧数(包括有效帧)
uint32_t OV2640_GetDummyFrame(void)
{
        uint32_t Dummy_Frame;
        
        OV2640_WriteReg(0xFF, 0x01);
        Dummy_Frame = OV2640_ReadReg(0x03) & 0xC0;
        switch (Dummy_Frame)
        {
                case 0x00:
                        Dummy_Frame = 1; //有效帧+虚拟帧
                        break;
                case 0x40:
                        Dummy_Frame = 2;
                        break;
                case 0x80:
                        Dummy_Frame = 4;
                        break;
                case 0xC0:
                        Dummy_Frame = 8;
                        break;
        }
        return Dummy_Frame;
}

// OV2640 时钟计算
// fCLK: PLL output clock
// fCLK = (0x40 - 0x3D[5:0]) * MCLK / M, where
//      M = 2 if 0x3D[7:6] = 00
//      M = 3 if 0x3D[7:6] = 01
//      M = 4 if 0x3D[7:6] = 10
//      M = 6 if 0x3D[7:6] = 11
// fINT: internal clock
// fINT = fCLK / (2 * (0x11[5:0] + 1))
// PCLK = fINT / 2
/* ---------------------------------------------------------------------------*/
float OV2640_GetPCLK(void)
{
        float PCLK;
        uint8_t  M;
        uint8_t  REG3D;
        uint8_t  Clock_Divider;
        
        OV2640_WriteReg(0xFF, 0x01);
        Clock_Divider = (OV2640_ReadReg(0x11) & 0x3F) + 1;
        
        REG3D = OV2640_ReadReg(0x3D);
        switch (REG3D & 0xC0)
        {
                case 0x00:
                        M = 2;
                        break;
                case 0x40:
                        M = 3;
                        break;
                case 0x80:
                        M = 4;
                        break;
                case 0xC0:
                        M = 6;
                        break;
        }
        
        PCLK = (float)OV2640_XVCLK * (0x40 - (REG3D & 0x3F)) / M / Clock_Divider / 4;
        return PCLK;
}

float OV2640_GetFrameRate(void)
{
        float Frame_Rate;
        uint8_t  Res;
        uint32_t Line_Pixels;
        uint32_t Frame_Lines;
        uint32_t Dummy_Frame;
        
        Res = OV2640_GetResMode();
        Line_Pixels = OV2640_LinePixels[Res] + OV2640_GetDummyPixel();
        Frame_Lines = OV2640_FrameLines[Res] + OV2640_GetDummyLines();
        Dummy_Frame = OV2640_GetDummyFrame();

        Frame_Rate = (float)OV2640_GetPCLK() / Line_Pixels / Frame_Lines / Dummy_Frame;
        return Frame_Rate;
}[/mw_shl_code]
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

14

主题

103

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
356
金钱
356
注册时间
2016-7-20
在线时间
39 小时
发表于 2017-8-2 15:04:24 | 显示全部楼层
楼主,怎么让它CIF格式输出呀?原子哥的程序没有CIF格式的
回复 支持 1 反对 0

使用道具 举报

3

主题

347

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
2082
金钱
2082
注册时间
2014-12-19
在线时间
711 小时
 楼主| 发表于 2016-10-12 23:06:34 | 显示全部楼层
没人顶
回复 支持 反对

使用道具 举报

4

主题

11

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
265
金钱
265
注册时间
2015-5-30
在线时间
85 小时
发表于 2016-11-3 10:19:49 | 显示全部楼层
谢谢!!!!!!!!!!!!!!
回复 支持 反对

使用道具 举报

4

主题

11

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
265
金钱
265
注册时间
2015-5-30
在线时间
85 小时
发表于 2016-11-3 10:33:35 | 显示全部楼层
我顶!!!!!!!!!!!!应该申请为精华帖子!!!!!!
回复 支持 反对

使用道具 举报

2

主题

7

帖子

0

精华

新手上路

积分
49
金钱
49
注册时间
2016-4-28
在线时间
16 小时
发表于 2016-11-29 09:42:32 | 显示全部楼层
谢谢楼主
回复 支持 反对

使用道具 举报

8

主题

46

帖子

0

精华

初级会员

Rank: 2

积分
178
金钱
178
注册时间
2015-6-21
在线时间
41 小时
发表于 2016-12-21 10:49:06 | 显示全部楼层
收藏一下!
回复 支持 反对

使用道具 举报

1

主题

10

帖子

0

精华

初级会员

Rank: 2

积分
100
金钱
100
注册时间
2016-12-18
在线时间
18 小时
发表于 2016-12-21 17:54:55 | 显示全部楼层
顶!谢谢楼主分享。
回复 支持 反对

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165475
金钱
165475
注册时间
2010-12-1
在线时间
2115 小时
发表于 2016-12-31 11:05:11 | 显示全部楼层
顶!d=====( ̄▽ ̄*)b
回复 支持 反对

使用道具 举报

35

主题

309

帖子

0

精华

金牌会员

Rank: 6Rank: 6

积分
2641
金钱
2641
注册时间
2016-8-10
在线时间
470 小时
发表于 2017-6-23 11:12:04 | 显示全部楼层
楼主请问2640怎么手动调整曝光,谢谢
回复 支持 反对

使用道具 举报

0

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2016-11-7
在线时间
31 小时
发表于 2017-7-4 11:08:56 | 显示全部楼层
先顶楼主,然后提一下我的问题,最终的帧率计算公式适用于XVGA和SVGA,当配置为CIF模式时,计算出的帧率应该是120.048012,但是实际输出的帧率确实60fps
回复 支持 反对

使用道具 举报

3

主题

347

帖子

3

精华

金牌会员

Rank: 6Rank: 6

积分
2082
金钱
2082
注册时间
2014-12-19
在线时间
711 小时
 楼主| 发表于 2017-7-4 15:25:38 | 显示全部楼层
lh414 发表于 2017-7-4 11:08
先顶楼主,然后提一下我的问题,最终的帧率计算公式适用于XVGA和SVGA,当配置为CIF模式时,计算出的帧率应 ...

CIF模式有点特殊,目前仍未找到最准确的计算公式。
回复 支持 反对

使用道具 举报

0

主题

9

帖子

0

精华

初级会员

Rank: 2

积分
110
金钱
110
注册时间
2016-11-7
在线时间
31 小时
发表于 2017-7-5 12:49:24 | 显示全部楼层
lvehe 发表于 2017-7-4 15:25
CIF模式有点特殊,目前仍未找到最准确的计算公式。

确实有些特殊,画面亮度也上不去,比较暗
回复 支持 反对

使用道具 举报

4

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
126
金钱
126
注册时间
2016-11-9
在线时间
30 小时
发表于 2017-10-8 22:04:06 | 显示全部楼层
帮顶帮顶
回复 支持 反对

使用道具 举报

2

主题

46

帖子

0

精华

初级会员

Rank: 2

积分
146
金钱
146
注册时间
2017-12-14
在线时间
31 小时
发表于 2018-10-9 21:15:04 | 显示全部楼层
顶上天!
回复 支持 反对

使用道具 举报

18

主题

99

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
465
金钱
465
注册时间
2016-1-20
在线时间
89 小时
发表于 2019-8-9 17:32:18 | 显示全部楼层
手册里面的 0xD3寄存器不也是分频用的吗?  但是你的计算里面为啥没有呢
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-5-8 06:00

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表