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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-15 21:05
最近做项目需要用到OV7725,于是花了些时间研究。由于OV7725对于工作频率的要求较高,因此使用带FIFO的摄像头模块。代码参考自正点原子官方。
; c" Z5 K* U# Z4 O/ B% S4 |% Z1 p0 n# a4 ?

; F5 {4 y0 [2 U) x; r0 }* yOV7725资源& o( ^* N6 l0 C
引脚说明
' S- m( e* T2 n以下时关于十八个引脚的说明(来自正点原子的用户手册). r$ B7 B" |$ r6 e
9 j* V# i  o! O) j
20200323141056716.png 0 E  h  L$ u+ h6 b5 b: M. d& R2 W0 V

# l' x) y) S: F其中,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片选信号在初始化之后就拉低,使之有效。7 \, [2 x5 G1 _% d9 W

3 v  k* B& n' P寄存器
3 e4 C" r+ t7 e9 O% z这是来自datasheet的寄存器描述,看手册,英文很重要:$ j6 H6 p4 |/ R. `# }, l! X
2 e0 y% @- l  y+ F$ s8 D
20200323135602683.png , F* e, O$ b3 P  v( N

$ U; o* M+ T5 P  r3 _6 \这些寄存器在代码里表现为一堆宏定义
  1.   /*OV7725寄存器宏定义*/7 V+ f4 p: k; w1 ]  \+ f
  2. #define GAIN      0x004 X; y5 z% d) H* w6 z0 {& X' A
  3. #define BLUE      0x01
    7 s  s9 }" A/ ^
  4. #define RED       0x02
    7 @# `8 e; B% A, T6 c
  5. #define GREEN     0x031 V. g  A% R+ f4 [
  6. #define BAVG      0x053 r8 t8 e7 T6 Z
  7. #define GAVG      0x06
    7 F9 e# e; i# y! y% E. G0 c  |  x
  8. …………
    # I4 H) @! j5 ~1 q. c$ K2 R
复制代码
3 D% }7 h. z' }6 P8 v& V% j
模块初始化$ W) L0 p1 r+ g/ U6 U- e0 y
引脚定义
1 C; C1 g$ P! E& L
  1. //D0~D7:PA0~PA7       VSYNC:PA89 V3 i4 J* c. Z% V% _$ [
  2. //WRST:PB13  RRST:PB14  OE:PB5  RCLK:PB6  WEN:PB7  SDA:PB8  SCL:PB9   
    1 j' A; |; {( k/ }( t
  3. #define OV7725_VSYNC    PAin(8)                        $ [* S4 b% h; S. V; q
  4. #define OV7725_WRST                PBout(13)               
      V/ f$ W6 U. ~, e. q; F7 K6 ?
  5. #define OV7725_WREN                PBout(7)               
    ! w; l- j2 @) Q9 n- d
  6. #define OV7725_RCK_H        GPIOB->BSRR=1<<6  q7 D, T# o: ^
  7. #define OV7725_RCK_L        GPIOB->BRR=1<<6  K+ M3 ?; K/ Y$ `
  8. #define OV7725_RRST                PBout(14)          - @+ h8 S3 ?4 e: q  _+ u4 \
  9. #define OV7725_CS                PBout(5)  
    . [: t. O* |: E2 z  r% V- J
复制代码
  1. #define SCCB_SCL                    PBout(9)                 //SCL( K" M0 q" n3 n
  2. #define SCCB_SDA                    PBout(8)                 //SDA         
    ( I! r0 A5 A6 o
  3. $ }$ m4 D2 _/ _) Y! w
  4. #define SCCB_READ_SDA            PBin(8)                  //ÊäÈëSDA   
    : t/ ]1 C) S6 Y
复制代码

0 m4 L2 m. G3 I3 ]% B- U, F# h: m6 ]( _& N. d
我使用的是杜邦线连接如,IO口是自己重新定义的(全使用普通IO即可),STM32F1系列的PB3,PB4,PA13,PA14,PA15用于JTAG,如果有使用到其中的引脚,需要进行特殊配置,具体可参考网上更多教程。当时使用PB3,PB4作为SCCB的引脚,出现问题才发现这个原因。
0 w! |# N/ y: |  S
' G- G/ }( c" v, z
初始化
4 O5 D  o. s6 l' U0 T- y写寄存器的函数,寄存器的配置都是通过这个函数
$ e5 @* c) v- J; a+ g
  1. u8 SCCB_WR_Reg(u8 reg,u8 data)
    # Z, G: q# j4 U% D- q) y
  2. {+ S3 c, U& e. }# F) }( _8 o# R
  3.         u8 res=0;  v) D8 r  X; F
  4.         SCCB_Start();                          //启动SCCB传输                 
    1 o+ O0 N- `; y% G/ }' [5 c; e# E
  5.         if(SCCB_WR_Byte(SCCB_ID))res=1;        //写器件ID,为0x42
    " O1 ^+ z: l: J2 N2 A# Q
  6.         delay_us(100);- s0 ^8 k6 I6 j6 q6 |
  7.           if(SCCB_WR_Byte(reg))res=1;                //写寄存器地址,直接写对应的寄存器地址+ m6 f  {  l% D/ o% T; r
  8.         delay_us(100);
    5 F+ C/ [! n3 V1 F3 H, J6 y  d) I; K
  9.           if(SCCB_WR_Byte(data))res=1;         //写数据,根据寄存器功能写对应数据1 A5 O# h9 \$ x
  10.           SCCB_Stop();         
    / M7 |: |$ w+ O$ C- N
  11.           return        res;
    4 P/ P9 F3 ?0 X5 x) N
  12. }                          ' Y5 ~+ ^" a$ m  g5 S
复制代码
6 ~. x' M/ i! v4 J4 d; x- Z+ W1 Y2 v
将要配置的寄存器地址和对应的值,存在一个二维数组里边- m) z! `! p7 Q
  1. //初始化寄存器系列及其对应的值, J4 f# _7 k& a, t; X+ G
  2. const u8 ov7725_init_reg_tb1[][2]= * O8 F+ M; d6 K: W& [
  3. {   
    7 Z$ r9 P3 j( \
  4.         /*输出窗口设置*/
    3 u* ~( K9 Z, q; K* p3 h
  5.         {CLKRC,     0x00}, //clock config
    " _5 {, h6 B4 ~/ m
  6.         {COM7,      0x06}, //VGA RGB565
    * R# k4 I. ~9 z7 M* F
  7.         {HSTART,    0x3f}, //水平起始位置
    2 G! _, Q9 f4 O" }
  8.         {HSIZE,     0x50}, //水平尺寸. K6 L7 J6 v4 _$ H6 S- U
  9.         {VSTRT,     0x03}, //垂直其实位置+ C. ~) f$ V7 r  O: c
  10.         ......
    4 G3 b, h: E# f( n
复制代码
+ [# j3 |1 P! k4 {
初始化时,在循环语句调用写寄存器的函数,依次写入寄存器的地址和对应的值,即可完成寄存器的配置
7 ?3 @* Y4 G! G" v- _5 Y7 q
  1.   //初始化OV7725,采用QVGA分辨率(320*240)  
    , q0 c6 d0 \* {, n% y2 k, J
  2.         for(i=0;i<sizeof(ov7725_init_reg_tb1)/sizeof(ov7725_init_reg_tb1[0]);i++)( r; a2 |% b) Q9 ]1 ^- E
  3.         {                                                                6 P/ i) A' z! k( P( j8 \" W
  4.                    SCCB_WR_Reg(ov7725_init_reg_tb1[i][0],ov7725_init_reg_tb1[i][1]);
    # q5 R7 F3 f" V( h
  5.          }   p- Q! T) I# U% T
复制代码

, ~9 [( l; m  c) O1 v+ K帧中断和数据处理; n& `9 h2 q2 ~7 a) h& t- Y
发生帧中断时2 i2 M- I% }7 I8 w! B- T
  1. u8 ov_sta;        //帧中断标记; ?; _" V/ [4 P: o/ }0 R1 T
  2. //中断处理函数
    $ a' p+ Q9 X& T! k
  3. void EXTI9_5_IRQHandler(void)
    ; n  K' g; t2 C- K5 b
  4. {                                 1 G  S% y6 e2 ^8 ]. o4 i
  5.         if(EXTI_GetITStatus(EXTI_Line8)==SET)//是8线的中断$ K/ `* E) o1 l+ W! g" X
  6.         {      
    & Z9 ]8 N1 |- R
  7.                 if(ov_sta==0)
    : Q; W0 n2 K. X) t. {2 u
  8.                 {6 O: s" N" q" S; a
  9.                         OV7725_WRST=0;        //复位写指针                 9 H( j2 s0 D: D7 B$ x
  10.                         OV7725_WRST=1;        5 X# `6 p4 v8 h
  11.                         OV7725_WREN=1;        //允许写入FIFO          / q- M" y, J( u) `, b8 {, q1 ~1 T! z
  12.                         ov_sta++;                //帧中断加1
    ! h: }0 m1 u7 @% L4 I! G
  13.                 }else OV7725_WREN=0;//禁止写入FIFO8 q  \7 f$ B5 t) b0 G- P
  14.         }
    : @" x: Z; \) Q# I
  15.         EXTI_ClearITPendingBit(EXTI_Line8);  //清除中断标志位                                          / B) m# _+ I# y5 u: a$ J
  16. }
    : i  s/ [* x# B
复制代码

: M; |+ m* ^0 T数据处理
* a$ K% J! a- F; d
  1. if(ov_sta)//判断是否有帧中断发生
    1 i% J/ d, Y% w- F' ?& t. A
  2. {
    9 ?1 m" |6 K5 E6 c) I
  3.         OV7725_RRST=0;                  //复0 d3 B% y7 g  E7 X6 O8 [3 R- B
  4.         OV7725_RCK_L;         //位
    " S9 s- U7 V, p8 W5 l- I% ~2 @0 M
  5.         OV7725_RCK_H;         //读3 ?% m" n$ N, J. z% A* q- k- H, p
  6.         OV7725_RCK_L;         //指
    ( j- f  w4 w3 j3 y' e
  7.         OV7725_RRST=1;                  //针5 M9 R+ H* z: y$ j: P
  8.         OV7725_RCK_H; 5 O& j. z' u6 x/ W) ]2 C
  9.         for(i=0;i<OV7725_WINDOW_HEIGHT;i++)//循环语句读取FIFO的数据
    ( y% ~* Y" k+ M5 T" i  y; |& x
  10.         {
    & l& ~  K. P: l+ }
  11.                 for(j=0;j<OV7725_WINDOW_WIDTH;j++)
    , ^' g; x( N$ S3 r  e; l, X
  12.                 {
    ) D  C) Y# s9 z/ c- D) W+ n
  13.                         //将数据填入相应缓冲区( e# Z7 Q4 I/ L& o" L+ J$ E+ w
  14.                         ......
    4 P7 z& x/ S/ c
  15.                 }
    4 x  M) y4 d, V5 G
  16.         }) A9 h" I. h1 w9 u) j7 V' g1 E
  17.         ov_sta=0;  //清零帧中断标志
    6 T2 j. {: z( `1 g: P# O
  18. }
    ) _. O& B& u" h7 c" x8 l
复制代码
; h. {* i4 T" x, A
以上是对于OV7725的初步理解,还有很多不懂的地方,后续有进一步研究再补充
4 k$ [+ q; `! G; K3 d- h2 q. n————————————————6 t$ d2 L: Y# R" j1 ~
版权声明:hu_hong_hao/ d9 y4 c& P9 R' ^: t
如有侵权请联系删除
7 z9 p4 ^/ D8 {. `0 b4 L: ?, T, x3 |
7 F- w! t+ u- J) j  t# \
! o% k% X1 W" g" V% r# ?* v! W. c$ G' m- h/ x# E! h# J( [
赞 收藏 评论0 发布时间:2023-5-15 21:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

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