你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

基于STM32F1的OV7725摄像头经验分享

[复制链接]
攻城狮Melo 发布时间:2023-5-15 21:05
最近做项目需要用到OV7725,于是花了些时间研究。由于OV7725对于工作频率的要求较高,因此使用带FIFO的摄像头模块。代码参考自正点原子官方。! S" ^# H4 X5 F9 W3 d6 L$ V

3 `# P0 ^/ Z  q' _, S

' S7 n0 {' h: S& ?OV7725资源# u, [% L1 k* B$ R$ P2 n, a
引脚说明
" |1 @9 }; [1 g1 |以下时关于十八个引脚的说明(来自正点原子的用户手册)
4 m( N- X) L) T) e# x  Z# u9 `  h0 _$ `, s. z7 w
20200323141056716.png
0 r! d% P; ?& I. D2 g# h2 h8 k  |

* T- d; E" N1 O* [) I% a  r其中,OV_SCL和OV_SDA组成SCCB,即串行摄像头控制总线,它的通信机制类似于IIC,有使用过IIC总线的较容易理解。OV_VSYNC为帧同步信号,该引脚产生信号时,意味着一帧数据传输完成后,下一帧数据传输即将开始(这里,从OV7725传输至FIFO)。FIFO_D[7:0] 是FIFO的数据引脚,用于数据传输。当发生帧同步信号时,复位FIFO_WRST写指针信号,使能FIFO_WEN写使能信号,则OV7725开始往FIFO写数据,并置位帧中断标志位(该标志位在读数据完成后被清零),保证FIFO的数据被读取完成之前不会被覆盖,具体见下面的中断服务程序。帧中断标志位有效时,就复位RIFO_RRST读指针信号,然后在每个FIFO_RCLK读时钟信号,使用STM32去读取FIFO_D[7:0] 的数据。FIFO_OE片选信号在初始化之后就拉低,使之有效。
' |( c& j4 h4 @3 d: N5 t3 h; m! j2 n. [# U+ s5 k! t
寄存器
( r% j; n! |3 p- [6 R这是来自datasheet的寄存器描述,看手册,英文很重要:
; {+ r' J5 N5 C, ^2 m6 y/ O! w
9 w7 `" g8 X$ a, n
20200323135602683.png 8 n% I2 ?1 O: `7 T7 a3 |
2 k! ~1 K0 `2 s7 z/ O2 X
这些寄存器在代码里表现为一堆宏定义
  1.   /*OV7725寄存器宏定义*/
    $ M& t- K7 {$ N/ ]+ a, V! H4 q+ `
  2. #define GAIN      0x00
    8 R) ]/ m- y4 i% t: S
  3. #define BLUE      0x01/ @, m4 c/ [5 |! Z% t# B" @8 x, v
  4. #define RED       0x02/ E; {- s, b, Q$ s
  5. #define GREEN     0x03
    2 x6 H# L8 I5 j" t8 L
  6. #define BAVG      0x05
    : Z3 P6 s) b7 a$ v) |& v
  7. #define GAVG      0x06; K& N3 a4 x4 L2 _1 }, v, e
  8. …………
    - f+ o( Q* D. E) ]/ C- u) i
复制代码

! E& ~8 i( q' X& ]' F" ^模块初始化
6 o. \' S8 k* z" H& {6 d引脚定义

7 o5 E7 C9 ]  `+ Z
  1. //D0~D7:PA0~PA7       VSYNC:PA80 T* ~' R6 d8 X2 n' {5 E: D
  2. //WRST:PB13  RRST:PB14  OE:PB5  RCLK:PB6  WEN:PB7  SDA:PB8  SCL:PB9    5 G4 p4 z; k) H) s0 M2 V7 n
  3. #define OV7725_VSYNC    PAin(8)                        & \) U+ [+ S: Z3 S( }& Q! t+ D2 I
  4. #define OV7725_WRST                PBout(13)               
    7 }* |* I1 o/ }" q1 c' [
  5. #define OV7725_WREN                PBout(7)                4 u  [* V8 ]% S4 `- f$ ^
  6. #define OV7725_RCK_H        GPIOB->BSRR=1<<61 m+ i& S# ^/ g# y
  7. #define OV7725_RCK_L        GPIOB->BRR=1<<6
    : L/ |* z% P0 B4 V9 K' _
  8. #define OV7725_RRST                PBout(14)         
    2 Q/ v2 p2 w- u7 N
  9. #define OV7725_CS                PBout(5)  
    3 v/ v! D1 [5 w& p
复制代码
  1. #define SCCB_SCL                    PBout(9)                 //SCL
    ' Y" i2 Y9 c% d
  2. #define SCCB_SDA                    PBout(8)                 //SDA         
      P5 p7 M+ r  d' ^+ @- I

  3. + ^, s( U' |4 V, C8 |! ?# x
  4. #define SCCB_READ_SDA            PBin(8)                  //ÊäÈëSDA   
    1 Z- U5 I+ A5 O( r0 j
复制代码
/ e7 |2 K* Q+ p, f

3 r% V0 r/ O1 P: R4 A2 _我使用的是杜邦线连接如,IO口是自己重新定义的(全使用普通IO即可),STM32F1系列的PB3,PB4,PA13,PA14,PA15用于JTAG,如果有使用到其中的引脚,需要进行特殊配置,具体可参考网上更多教程。当时使用PB3,PB4作为SCCB的引脚,出现问题才发现这个原因。4 l- K% z' I, n" Y; @
+ E, M" @/ y8 z) v+ s0 {
初始化+ R, r: y" h) b+ ]
写寄存器的函数,寄存器的配置都是通过这个函数, q3 w; m8 P; K" H
  1. u8 SCCB_WR_Reg(u8 reg,u8 data)
    1 m6 l% i* L, R. Z( |4 Z+ P5 J9 i
  2. {# a8 `8 ^' J; f9 C0 N" d  `5 Y, P5 c
  3.         u8 res=0;
    / J3 Q! M' n: x
  4.         SCCB_Start();                          //启动SCCB传输                 
    6 |0 k- ~* U+ P1 J; u& D: L- E% o2 u
  5.         if(SCCB_WR_Byte(SCCB_ID))res=1;        //写器件ID,为0x42% D! R( B+ l4 q
  6.         delay_us(100);
    - s6 K6 p) Q0 [- J1 L4 O
  7.           if(SCCB_WR_Byte(reg))res=1;                //写寄存器地址,直接写对应的寄存器地址7 o6 X* \0 D7 W  ^8 _& a! x- r
  8.         delay_us(100);. K) U" ]" a1 G! g* [  h4 ~
  9.           if(SCCB_WR_Byte(data))res=1;         //写数据,根据寄存器功能写对应数据( j7 k% z* H8 _
  10.           SCCB_Stop();         
    - U5 b+ n* C" J3 |0 F7 }2 T4 D
  11.           return        res;
    . f1 d* |4 C  v; m+ U! c  x. H& l
  12. }                          5 G% Y' o, a1 t8 F5 g: a
复制代码

- b  N+ e) I  L8 Y$ L4 l将要配置的寄存器地址和对应的值,存在一个二维数组里边& j; ^; L% M& H2 {
  1. //初始化寄存器系列及其对应的值/ e, u, s8 f  v
  2. const u8 ov7725_init_reg_tb1[][2]=
    8 q& {9 ?* |0 j
  3. {   * {: o' \3 P+ y- r9 _+ i
  4.         /*输出窗口设置*/
    & M6 [( j+ v: h. h
  5.         {CLKRC,     0x00}, //clock config
    2 o. m" R0 ]$ a; t, ?  {. z- k
  6.         {COM7,      0x06}, //VGA RGB565
    8 e& \1 a' }: O
  7.         {HSTART,    0x3f}, //水平起始位置
    ' u, o  S/ `* p  {: L% K
  8.         {HSIZE,     0x50}, //水平尺寸6 Q  ]3 u3 b; z
  9.         {VSTRT,     0x03}, //垂直其实位置
    " ~' ^; |, h8 C- W* d. M; i
  10.         ......
    : o  {. y4 d8 r: `
复制代码

" Y$ Q; s: [# H  N+ u$ A1 t初始化时,在循环语句调用写寄存器的函数,依次写入寄存器的地址和对应的值,即可完成寄存器的配置/ @+ N3 ~& \! x6 O
  1.   //初始化OV7725,采用QVGA分辨率(320*240)  
    6 I4 @; c0 s2 z* P: A, }+ E
  2.         for(i=0;i<sizeof(ov7725_init_reg_tb1)/sizeof(ov7725_init_reg_tb1[0]);i++)
    # |6 R9 v% P# ?/ H
  3.         {                                                                & s8 b/ M9 x2 h% E6 I& k2 l' f
  4.                    SCCB_WR_Reg(ov7725_init_reg_tb1[i][0],ov7725_init_reg_tb1[i][1]);1 H& U. ]+ g/ z; h% R
  5.          } ' @; \4 e6 [( k5 w" W* `+ r
复制代码

9 f- H0 X" @( \+ U3 m3 k帧中断和数据处理
, m0 M3 Q6 o. i% N$ o; [发生帧中断时
4 Y  }! \3 V8 e0 _: r
  1. u8 ov_sta;        //帧中断标记. G' C* M& h! h" j% v3 F! F* q
  2. //中断处理函数
    ; [( g. ^; f7 }* M# X8 y7 q
  3. void EXTI9_5_IRQHandler(void)4 a% |& {  E* W
  4. {                                 7 V) t2 ~2 m. {0 F$ D- Y' Z! o$ E
  5.         if(EXTI_GetITStatus(EXTI_Line8)==SET)//是8线的中断
    / G1 V$ h9 ]( ]# b, E+ [1 E
  6.         {      % p0 P3 \4 Z4 N* Q5 i! l$ J* x
  7.                 if(ov_sta==0)/ E: \" h2 {" G% I4 O
  8.                 {
    4 v/ H( K2 T- h3 ?
  9.                         OV7725_WRST=0;        //复位写指针                   E5 p; K# i$ n8 |. x2 D( m
  10.                         OV7725_WRST=1;        # \7 n& ^  X$ l, S
  11.                         OV7725_WREN=1;        //允许写入FIFO          : w) D( K  e! _/ m3 D, W1 S
  12.                         ov_sta++;                //帧中断加1
    3 \* c: e# r. K% q; {
  13.                 }else OV7725_WREN=0;//禁止写入FIFO' U+ M5 V0 c: `; H' l* ^3 b8 e
  14.         }& p2 d: X( \) N& f1 X7 I! ^
  15.         EXTI_ClearITPendingBit(EXTI_Line8);  //清除中断标志位                                          
    ; ^5 P9 ^, o* S
  16. } ( I. ]1 G4 [% A/ i0 J! B5 o6 \
复制代码
5 A+ g: V3 M$ F7 w( [$ `2 p3 q- a
数据处理& k2 q" `  \0 \" X: e. `: v1 N
  1. if(ov_sta)//判断是否有帧中断发生
      U, w+ }- }* b! L
  2. {  G$ X7 i$ n- Z) [* h5 K! x
  3.         OV7725_RRST=0;                  //复
    $ M0 i( ^0 b: ~$ h
  4.         OV7725_RCK_L;         //位
    % Y; g2 k: l$ ~0 b+ W- f: u
  5.         OV7725_RCK_H;         //读' b9 a' ^6 Y  W
  6.         OV7725_RCK_L;         //指8 a3 P# ~( L: b* S: s( D+ U
  7.         OV7725_RRST=1;                  //针
    0 D' I5 Z$ D; b
  8.         OV7725_RCK_H; 0 v2 b2 H6 E$ D0 j$ Q
  9.         for(i=0;i<OV7725_WINDOW_HEIGHT;i++)//循环语句读取FIFO的数据' m8 d7 s9 w1 M2 ?. V( v1 j3 z
  10.         {  v# [+ c: Q% i0 {0 w. F$ T5 A
  11.                 for(j=0;j<OV7725_WINDOW_WIDTH;j++)  f: t3 Y; g* i' i
  12.                 {
    9 y+ ~* j: v+ O* E1 F0 `2 T/ z/ d
  13.                         //将数据填入相应缓冲区5 S6 d: m2 `5 F: e7 y
  14.                         ......7 B! d1 P. x. ~; Q7 U# x2 D+ d5 P
  15.                 }8 j  |+ q# u1 r: o" X
  16.         }
    & ~# {. |  b9 f1 `, p/ Q% ^
  17.         ov_sta=0;  //清零帧中断标志8 v9 q% ^4 F8 I
  18. }
    2 C1 X* a' C; Q5 E
复制代码

' s- s7 T! y& u4 \& P, c  w以上是对于OV7725的初步理解,还有很多不懂的地方,后续有进一步研究再补充
+ ~$ ]+ s# \- F2 U* p9 |. A————————————————
. Y8 M1 M0 @8 _  y版权声明:hu_hong_hao
7 u7 X3 v0 S5 n2 K如有侵权请联系删除
# @5 \9 e" N8 R  m/ n8 _. J$ d' q8 _* U3 R9 k8 [5 D' c5 \
) Y+ r+ e2 s6 F* G( _

( z; C* H2 O$ ?2 O: S2 y
赞 收藏 评论0 发布时间:2023-5-15 21:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版