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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-15 21:05
最近做项目需要用到OV7725,于是花了些时间研究。由于OV7725对于工作频率的要求较高,因此使用带FIFO的摄像头模块。代码参考自正点原子官方。
" I( {9 Y& k0 X; f3 e- e4 S7 A2 u" N, l; r( ^+ \+ Q: c: z
$ x- L/ ?4 T! |+ `
OV7725资源- c6 y8 }2 ?  D5 o& {$ n  U1 p( e' {
引脚说明
& J3 }8 U. W' g& ]以下时关于十八个引脚的说明(来自正点原子的用户手册)
* b' Z! ~5 k: p* C: C1 f
( G4 s- e! D# ]8 c5 z/ f
20200323141056716.png - `  S) p7 n& i8 U6 `0 `& N
/ J1 J: K; h, M7 b5 G+ y( [
其中,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片选信号在初始化之后就拉低,使之有效。
/ D: |1 l% t$ }2 O2 E- D% H$ V7 V" o5 b& g# Y
寄存器! m: p* R( h8 D
这是来自datasheet的寄存器描述,看手册,英文很重要:
# g: L& F5 G6 l+ x; l# {; `
) w/ A9 _' f* U) Y& U
20200323135602683.png
- K9 K( m+ A( j, ~

* d5 q1 v, [4 a4 H/ L! h/ E这些寄存器在代码里表现为一堆宏定义
  1.   /*OV7725寄存器宏定义*/
    ' S+ P2 M$ J0 i8 w$ j
  2. #define GAIN      0x00
    5 y( |- X2 D4 A' D* K
  3. #define BLUE      0x01- C4 {$ G* F' A2 V
  4. #define RED       0x02
    : z/ _- f8 |# d
  5. #define GREEN     0x03- K* C' f0 z& d: {0 J# c7 d" F
  6. #define BAVG      0x052 m5 ]" {) x) A" T; g
  7. #define GAVG      0x06
    , h) K5 S/ L" S( Y$ q1 b. |
  8. …………8 E' G! m( y8 w
复制代码

9 K( b) E4 S- [! `6 X! ~6 n模块初始化
* u0 |' N" C$ g( f' E7 [: Z引脚定义
" z- g$ i7 P! E& k/ |
  1. //D0~D7:PA0~PA7       VSYNC:PA8# g8 s. {6 B4 a- o
  2. //WRST:PB13  RRST:PB14  OE:PB5  RCLK:PB6  WEN:PB7  SDA:PB8  SCL:PB9    $ R$ v4 s, z* E1 A' \3 i
  3. #define OV7725_VSYNC    PAin(8)                        3 P7 r* Y2 m+ l( k5 K
  4. #define OV7725_WRST                PBout(13)                0 B# g' B5 A! b$ B' K# O& @
  5. #define OV7725_WREN                PBout(7)                ' J; Y, d1 Q4 `
  6. #define OV7725_RCK_H        GPIOB->BSRR=1<<6( D* N1 I: H  R+ U! t' v% V9 O
  7. #define OV7725_RCK_L        GPIOB->BRR=1<<6
    0 p3 f  [6 _4 O
  8. #define OV7725_RRST                PBout(14)         
    1 z, P5 c2 K* g# ^- ^
  9. #define OV7725_CS                PBout(5)  
    9 h, [& t" ?) _' O. r7 t
复制代码
  1. #define SCCB_SCL                    PBout(9)                 //SCL- p: V: S) _: ]2 l! D) ?
  2. #define SCCB_SDA                    PBout(8)                 //SDA         
    1 u! `2 q0 C1 r6 P" h

  3. 1 e9 s4 m. D+ o4 T" x6 U; o
  4. #define SCCB_READ_SDA            PBin(8)                  //ÊäÈëSDA   
    2 X4 c3 }5 ^! u4 _/ G0 X8 [
复制代码

. j  Y# p7 S# u7 r- H: o. l9 {  k. _  d# H% \9 M7 g
我使用的是杜邦线连接如,IO口是自己重新定义的(全使用普通IO即可),STM32F1系列的PB3,PB4,PA13,PA14,PA15用于JTAG,如果有使用到其中的引脚,需要进行特殊配置,具体可参考网上更多教程。当时使用PB3,PB4作为SCCB的引脚,出现问题才发现这个原因。
% P4 l  @% ~; b$ s' g( e8 B# Q
6 n3 C( \# B1 U$ q6 i% r+ `
初始化
9 ?0 S& u. B. z+ C% O; l* O0 Z& d2 x写寄存器的函数,寄存器的配置都是通过这个函数% x5 `6 f" t) U, u: X% j/ z% J0 @
  1. u8 SCCB_WR_Reg(u8 reg,u8 data)+ Y% b6 B% G" K% m- j. G
  2. {
    & Y) v# Z+ y# n
  3.         u8 res=0;4 H6 L) {7 Y; w! Z
  4.         SCCB_Start();                          //启动SCCB传输                 ! s7 X0 \4 y" i
  5.         if(SCCB_WR_Byte(SCCB_ID))res=1;        //写器件ID,为0x42; I" h7 n1 W) g3 ]9 l7 I' R
  6.         delay_us(100);, x# }  F4 f6 t
  7.           if(SCCB_WR_Byte(reg))res=1;                //写寄存器地址,直接写对应的寄存器地址. [* s8 M0 a7 A) j/ ^8 W- n1 n
  8.         delay_us(100);
    0 C& T8 i2 c8 H8 m1 g1 f
  9.           if(SCCB_WR_Byte(data))res=1;         //写数据,根据寄存器功能写对应数据+ z9 r  d2 @+ w* H/ l
  10.           SCCB_Stop();         
    1 p0 N  k4 i* _: Y$ ^9 ~9 b, h
  11.           return        res;" h7 v# g1 w0 K. z# u7 P
  12. }                          
    , Y( r+ L. n: n6 N# P! U
复制代码

( J* \; t' [" f* j将要配置的寄存器地址和对应的值,存在一个二维数组里边
( A5 A1 p" I; H3 [! N& S/ N, U/ D1 ?
  1. //初始化寄存器系列及其对应的值
    & |+ x. X8 K. C2 n
  2. const u8 ov7725_init_reg_tb1[][2]=   C$ B0 ]; o; l6 @+ T  ^3 C3 Q
  3. {   0 Y6 [; H$ u/ R$ ?) F6 m5 n4 |
  4.         /*输出窗口设置*/! r8 \/ q  m) L" C; J
  5.         {CLKRC,     0x00}, //clock config- n. P, f  \1 H+ ]+ w8 m; w
  6.         {COM7,      0x06}, //VGA RGB565% H- ]+ `+ B7 q6 g9 y' a) \
  7.         {HSTART,    0x3f}, //水平起始位置1 i% r% S6 D) `. Z( k% C! m$ E/ S
  8.         {HSIZE,     0x50}, //水平尺寸
    0 t; A$ M1 Q+ X( L' u- \8 w' D
  9.         {VSTRT,     0x03}, //垂直其实位置" k, ]4 D% c' L" d5 l$ i
  10.         ......2 Y1 f3 y6 v9 a# q" m$ s! A+ K
复制代码
8 I! O" B- }2 O0 d
初始化时,在循环语句调用写寄存器的函数,依次写入寄存器的地址和对应的值,即可完成寄存器的配置
0 o& F* w1 ^. J7 I  C  u' v6 g0 u
  1.   //初始化OV7725,采用QVGA分辨率(320*240)  9 s$ k4 t* f7 W/ Z+ {4 ]  a  J
  2.         for(i=0;i<sizeof(ov7725_init_reg_tb1)/sizeof(ov7725_init_reg_tb1[0]);i++)
    2 p$ _; l2 m0 I6 I- N
  3.         {                                                               
    # l0 B! Q0 o) U% `
  4.                    SCCB_WR_Reg(ov7725_init_reg_tb1[i][0],ov7725_init_reg_tb1[i][1]);
    7 m& B7 P* Y0 d# X" v
  5.          }
      c! {6 D6 u7 M* r6 @5 S
复制代码

6 j0 ^- P+ s4 E4 {3 T8 ]帧中断和数据处理
8 f6 o+ @  X; ~9 f% v: T发生帧中断时* z6 H/ U- ^6 B
  1. u8 ov_sta;        //帧中断标记% S2 I0 B% F/ h
  2. //中断处理函数
    : Y1 y8 e9 z8 G/ ^' g1 o3 `6 k4 h& w7 t
  3. void EXTI9_5_IRQHandler(void)
    7 p& a& Z& Y% `
  4. {                                 ! y. W! i& ]- w/ d- F: p
  5.         if(EXTI_GetITStatus(EXTI_Line8)==SET)//是8线的中断# t+ [! i' W4 P8 T
  6.         {      7 s4 O& [* X, v8 j( @
  7.                 if(ov_sta==0)4 N0 C' }" S0 v) k' Y
  8.                 {2 p- w, `- @6 w1 y% V( N
  9.                         OV7725_WRST=0;        //复位写指针                 , Y/ s8 K/ o7 J
  10.                         OV7725_WRST=1;       
    / z" q1 r% k  T4 _% l+ w3 B& i9 G
  11.                         OV7725_WREN=1;        //允许写入FIFO          2 G1 `* d  h/ i, L, l6 u8 }
  12.                         ov_sta++;                //帧中断加1
    " Y+ D7 \4 v" x# v0 t# P0 M
  13.                 }else OV7725_WREN=0;//禁止写入FIFO1 d0 }6 i$ q  x/ N
  14.         }0 T" J6 w7 z( [$ @% Y( P
  15.         EXTI_ClearITPendingBit(EXTI_Line8);  //清除中断标志位                                          ) \3 u, O2 P3 e; Q  _
  16. }
    : G/ f; V5 P! V9 Z5 k& K. X
复制代码

* d6 y. \; c8 m6 m( i数据处理* j2 W  l7 T# w- v2 }& I: x
  1. if(ov_sta)//判断是否有帧中断发生. m, c7 a- O+ R) w+ p
  2. {: m0 v( e8 H1 d: C. P8 p: j
  3.         OV7725_RRST=0;                  //复
    - ^5 c) h( F/ J. v
  4.         OV7725_RCK_L;         //位
    6 z. w' H6 y, ~
  5.         OV7725_RCK_H;         //读
    & a+ R* S0 o. X8 }$ N9 e, s8 I
  6.         OV7725_RCK_L;         //指
      e8 [2 j5 W5 k! P: S# v+ B
  7.         OV7725_RRST=1;                  //针9 i' K: ?" {' P, ^7 t; l- r% r
  8.         OV7725_RCK_H; & r5 a% F5 E+ B. Q. j1 b0 ~1 z8 r
  9.         for(i=0;i<OV7725_WINDOW_HEIGHT;i++)//循环语句读取FIFO的数据, \3 V' G1 I  @* q
  10.         {9 J, n. p, c4 h# P
  11.                 for(j=0;j<OV7725_WINDOW_WIDTH;j++): ^2 K/ M9 R* }5 S# Q
  12.                 {
    , A+ {4 x* z6 E& y
  13.                         //将数据填入相应缓冲区
    $ l2 }& h6 ^3 A2 B
  14.                         ......
    / d6 S$ ?& S* N/ ^
  15.                 }
    . ~# {2 k- w: O
  16.         }5 _% i( K6 T0 |. F' o1 m
  17.         ov_sta=0;  //清零帧中断标志4 d9 K% y/ B# W& z4 [
  18. }3 R  f! q' I- H" z/ ~: G) t
复制代码
, v% ]* R  [5 _
以上是对于OV7725的初步理解,还有很多不懂的地方,后续有进一步研究再补充) G: `6 e) ?7 u( H5 C& ?1 h
————————————————
% r4 G; x9 M( d! Z版权声明:hu_hong_hao. x9 |0 l  H* K) b* i" f
如有侵权请联系删除
* r9 ~: f. j. i  [, u! X/ f, b; S0 |+ k. @- l8 |, e% r5 c

7 Q$ G6 Y9 X) _, n$ C% Z- W  B/ O% C0 B( b* g6 D' u8 G; Z
赞 收藏 评论0 发布时间:2023-5-15 21:05

举报

0个回答

所属标签

相似技术帖

官网相关资源

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