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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-15 21:05
最近做项目需要用到OV7725,于是花了些时间研究。由于OV7725对于工作频率的要求较高,因此使用带FIFO的摄像头模块。代码参考自正点原子官方。- V0 L3 p( z7 f7 |9 [0 W( R

  n4 J' u) l: m
" T% x+ ~$ e+ N2 p& M
OV7725资源. D: I! `# G: {9 f1 O4 h' s
引脚说明
  B1 q+ M8 E( z3 t$ ~以下时关于十八个引脚的说明(来自正点原子的用户手册)
" g3 t. Q; O: j9 S$ J" k# [: A/ s7 p& a8 w+ j( z$ V
20200323141056716.png # S/ H* B3 l' o4 E8 ?* v
6 w/ m, ?# P' ^, M3 }
其中,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片选信号在初始化之后就拉低,使之有效。
/ \; |) i" Q8 M: X$ `
' B$ ?- F) ?; o+ i& H寄存器
! V. D4 C9 f1 k  n, ]/ t8 {) J这是来自datasheet的寄存器描述,看手册,英文很重要:- \9 Q+ @: O; F6 Q+ [/ Z: @
) K* s4 l' Z9 W! ~
20200323135602683.png
6 U  e2 w0 B1 O8 H, I

. z% N+ Q1 y+ S- |5 W这些寄存器在代码里表现为一堆宏定义
  1.   /*OV7725寄存器宏定义*/
    ; O9 V7 P2 q6 R3 F
  2. #define GAIN      0x006 x9 f% J' _5 ~  x; g
  3. #define BLUE      0x01
    6 s+ |6 ~4 m' _8 C! K
  4. #define RED       0x02
    * Q1 s3 _: ^- C  Y+ g
  5. #define GREEN     0x03
    * a4 r! I: s* M) v- |
  6. #define BAVG      0x059 S0 `& {0 b' r7 q) G9 z2 h6 @/ f
  7. #define GAVG      0x06& o( l8 T0 }8 a$ E, A0 j' |
  8. …………
    + Y, }4 ]! P; n  \0 [, S
复制代码

" Q" V" _6 K2 K& T- E3 i6 M模块初始化
* K" z" |$ q# V  A引脚定义

0 V1 A$ a3 l# u9 a/ J; W
  1. //D0~D7:PA0~PA7       VSYNC:PA8! E( X' ^& B" ~9 W* ]* @- y; ]
  2. //WRST:PB13  RRST:PB14  OE:PB5  RCLK:PB6  WEN:PB7  SDA:PB8  SCL:PB9   
    , Y  E: _- m( e4 X- u- D
  3. #define OV7725_VSYNC    PAin(8)                        
    3 O: O. p8 i1 f0 y& _
  4. #define OV7725_WRST                PBout(13)               
    . C) V# h3 z! _+ `
  5. #define OV7725_WREN                PBout(7)                / E$ R/ X; D) ~
  6. #define OV7725_RCK_H        GPIOB->BSRR=1<<66 _( m4 m7 P. `7 Y) t% m! g0 f* g
  7. #define OV7725_RCK_L        GPIOB->BRR=1<<6
    2 ~9 k7 N: |* W/ f* u2 r% m
  8. #define OV7725_RRST                PBout(14)         
    / N+ }. H% Z  [. g* ]* `* v
  9. #define OV7725_CS                PBout(5)  . J7 q' m# b  u- ]: c* _9 [0 ^. {
复制代码
  1. #define SCCB_SCL                    PBout(9)                 //SCL
    + B' N  u- V6 L! ^4 d$ E& Q" Q
  2. #define SCCB_SDA                    PBout(8)                 //SDA         4 i; O% L1 A* b! i

  3. 8 t( ~& m, A4 I& }% W2 @7 X
  4. #define SCCB_READ_SDA            PBin(8)                  //ÊäÈëSDA   % T7 e3 T9 N8 R0 }/ X. X) e- I
复制代码

0 L* Q' A6 F5 Y6 t! |: d6 y+ R1 z: y6 e$ |2 @
我使用的是杜邦线连接如,IO口是自己重新定义的(全使用普通IO即可),STM32F1系列的PB3,PB4,PA13,PA14,PA15用于JTAG,如果有使用到其中的引脚,需要进行特殊配置,具体可参考网上更多教程。当时使用PB3,PB4作为SCCB的引脚,出现问题才发现这个原因。
# b7 B5 k' u, x

6 q) U: }9 r$ n# Y+ }/ \初始化
0 t' i1 X' x* P- W( c写寄存器的函数,寄存器的配置都是通过这个函数3 A& G6 K& ~6 `
  1. u8 SCCB_WR_Reg(u8 reg,u8 data)1 W- n3 o! P' y
  2. {
    , N, m, ?1 I9 \- s$ _
  3.         u8 res=0;* L8 ?' c% u+ E8 q& f7 N5 _
  4.         SCCB_Start();                          //启动SCCB传输                 
    5 W. a5 T& [" v# N
  5.         if(SCCB_WR_Byte(SCCB_ID))res=1;        //写器件ID,为0x42) h; J! _3 l8 r2 ?5 T$ V2 ^
  6.         delay_us(100);
    ) M! f. h# z4 {# @
  7.           if(SCCB_WR_Byte(reg))res=1;                //写寄存器地址,直接写对应的寄存器地址4 i- j4 G& O8 a  B& [
  8.         delay_us(100);- D$ F( r8 r' m5 l3 u" t* L* C% }. o
  9.           if(SCCB_WR_Byte(data))res=1;         //写数据,根据寄存器功能写对应数据& j+ @) M% |8 T
  10.           SCCB_Stop();          5 ^. E4 A( e. N1 h: [7 I
  11.           return        res;, Y! I* @9 h$ ~* k  Y& I) V0 @
  12. }                          0 X9 m% N6 D. g. G* A  q0 s
复制代码

. f% m& ?" v4 x将要配置的寄存器地址和对应的值,存在一个二维数组里边  N6 f7 v6 u4 z" l$ A) H
  1. //初始化寄存器系列及其对应的值
    4 l! X, ?8 G! `5 ?! E
  2. const u8 ov7725_init_reg_tb1[][2]=
    ; n1 o+ y. [5 W- w/ x
  3. {   
    8 o9 X; M/ U# a- S
  4.         /*输出窗口设置*/
    ! j+ Z0 ^( o( N% ]
  5.         {CLKRC,     0x00}, //clock config
    + U) d) I- j- z% U( e
  6.         {COM7,      0x06}, //VGA RGB565$ H3 A; A0 T- \* T
  7.         {HSTART,    0x3f}, //水平起始位置
    3 U2 x  i1 M3 x3 Z+ e4 }
  8.         {HSIZE,     0x50}, //水平尺寸
    8 v7 B0 h4 c2 C" q. q& g: o
  9.         {VSTRT,     0x03}, //垂直其实位置8 M6 }8 I; e/ z% N4 Q) ~  J2 n; K5 n
  10.         ......: G1 \6 \. @% R6 S8 D
复制代码

, s+ Z- j. k' x; f; m; z% y初始化时,在循环语句调用写寄存器的函数,依次写入寄存器的地址和对应的值,即可完成寄存器的配置
. s  y' N8 N8 e- a
  1.   //初始化OV7725,采用QVGA分辨率(320*240)  
    ; h2 g, R- H3 a2 ]. b
  2.         for(i=0;i<sizeof(ov7725_init_reg_tb1)/sizeof(ov7725_init_reg_tb1[0]);i++)
    ' p( p; @0 z2 n& q
  3.         {                                                               
    0 C: ]7 e' v* s
  4.                    SCCB_WR_Reg(ov7725_init_reg_tb1[i][0],ov7725_init_reg_tb1[i][1]);% s" X1 c2 C5 D! t- o. q: d
  5.          }
    ! k  {! B0 O: m& {6 ~! H
复制代码
( G% B/ r2 H" i; e4 S3 E" |
帧中断和数据处理
; J; ^( D" D0 v, R2 D, d7 ?发生帧中断时0 Z( J' ~4 D# Q+ g1 ]& w
  1. u8 ov_sta;        //帧中断标记
    ' J3 J( [, I; r; [; _8 f4 ]9 N" c
  2. //中断处理函数
    % m/ S: b$ H1 c1 c4 i
  3. void EXTI9_5_IRQHandler(void)
    ) Z8 M, Q( c8 Q& T7 r- f
  4. {                                 , r& e$ d6 {! [; d% ]2 v
  5.         if(EXTI_GetITStatus(EXTI_Line8)==SET)//是8线的中断
    ( Y  A9 T6 Z# Z2 a6 B( t
  6.         {        F- T) Y* K& n
  7.                 if(ov_sta==0). ?7 u# x/ ?1 p; ?0 z. D
  8.                 {( e; Y) ?9 u- V
  9.                         OV7725_WRST=0;        //复位写指针                 5 ^3 z  }5 H' m; W& L9 M
  10.                         OV7725_WRST=1;        # h" \* Q2 z" ~4 N1 K% F, Q6 t
  11.                         OV7725_WREN=1;        //允许写入FIFO          / P6 _, R0 G% ~% c
  12.                         ov_sta++;                //帧中断加1
    ( Q) n0 X7 g% I; J, S
  13.                 }else OV7725_WREN=0;//禁止写入FIFO2 k' {7 n: L. \6 T0 k3 {! }
  14.         }
    $ [+ x8 n6 \* m9 A- S) d: o% t
  15.         EXTI_ClearITPendingBit(EXTI_Line8);  //清除中断标志位                                          
    7 A1 P' S1 u" u* i/ T
  16. }
    " A$ T. c* g9 O
复制代码
- o( o1 B' E, R3 s9 e, m
数据处理! T& D/ c9 \# O! Z3 o; V
  1. if(ov_sta)//判断是否有帧中断发生7 a' F# l1 m9 q: e6 x) M" V
  2. {
    " K0 |9 {* i0 B' U
  3.         OV7725_RRST=0;                  //复9 x2 ~, t1 J& g; I. R& }
  4.         OV7725_RCK_L;         //位
    ! J1 l- n/ F4 Y! S8 F5 }
  5.         OV7725_RCK_H;         //读
    ; e$ z$ \. [* y' O- c$ B" |
  6.         OV7725_RCK_L;         //指
    / ?! X: A, z$ k5 G2 _
  7.         OV7725_RRST=1;                  //针
    " e/ e/ O9 y  B2 C( I/ w1 g. U  z
  8.         OV7725_RCK_H;
    & Q+ q- [1 F: J4 I
  9.         for(i=0;i<OV7725_WINDOW_HEIGHT;i++)//循环语句读取FIFO的数据9 ^: i0 }0 |' F% J
  10.         {
    8 c' b$ X* ~! t3 h, h7 d, ~% Q4 F7 F
  11.                 for(j=0;j<OV7725_WINDOW_WIDTH;j++)8 D) ]) L9 Z: o! r# `9 b. M- f4 z
  12.                 {! o) P9 x- q! l, l* A
  13.                         //将数据填入相应缓冲区
    6 d/ N0 E& }/ l2 U
  14.                         ......  i, @6 `' g8 {' }6 v3 ?7 ]* K: n
  15.                 }
    9 @5 F6 ]( f0 ]- Z$ K
  16.         }' K/ z$ C7 M4 n- B7 I0 z% }/ y
  17.         ov_sta=0;  //清零帧中断标志7 ]$ K+ @' e9 q2 m5 u
  18. }% K- \3 b! m5 m' x1 \
复制代码

4 Y+ X# Y/ q0 q3 {以上是对于OV7725的初步理解,还有很多不懂的地方,后续有进一步研究再补充
2 B. K# Z8 m# {/ X' `+ V( l————————————————
! C% n4 R7 |7 B* i# `版权声明:hu_hong_hao
1 R* B1 c* B3 t. j如有侵权请联系删除
, m/ ?/ T+ U! f0 q& _
0 O# k% B7 I1 O# J2 z' Q
: a/ |( O  Y$ L, w3 V# A0 I5 K2 G; H4 J
收藏 评论0 发布时间:2023-5-15 21:05

举报

0个回答

所属标签

相似分享

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版