这几天拿到了stm32f3discovery,拿到手的第一件事就是测试了硬件i2c,使用stm32cube生成库,测试对象为AD5934与ADG715。经过两天的调试,完美调通。中间也碰到了些问题。9 t: D8 c8 s& Y
1、一开始用的I2C1,一仿真就会出现死机的情况。
2 \) g1 r& e- n; A, Y 由于I2C1与swd接口重合,所以调用HAL_I2C_Init()函数后就死机,改成I2C2后问题解决。
0 g! j8 l! o# U: y- e2、无法访问指定地址的设备5 Y4 M( L! X- \# T6 H3 O
库函数中的入口地址并不是7bit地址,需要输入8bit。我的设备地址为13,始终无法访问设备,改为26后解决。
9 y* f' T2 K2 j- s" Z3、可以读写单个地址的数据,但是不能多字节读写。
; x6 n. y/ ~: O2 {! ? (1)、对于多字节写, 库函数中的9 ~4 \9 H u$ P/ [2 O
HAL_StatusTypeDef HAL_I2C_Mem_Write(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
2 M5 }! I! u3 \; o4 s, [; e0 \+ [ 其中 MemAddSize表示地址的位数,0表示7bit地址,1表示10bit地址。我误认为这个写的字节数,所以导致在写多字节的时候出错。
& P+ L& B6 u2 W3 r' P( b% k. E- k (2)、对于多字节读,由于AD5934的读操作与库函数的读操作有些出入,所以导致一直读错误。在库函数中写完读的内存地址就开始读,而AD5934中写完block read后接着还要再写一个number bytes read然后才开始读。所以需要对库函数进行修改,新增一个函数,以适合AD5934的block read.
% D0 f3 l2 k. a* c! ^( E1 J3 b0 h- u# u4 W5 t7 l4 C: p0 v
3 y# e. Q4 D! { stm32f3的i2c有三种模式:Reload、AutoEnd、SoftEnd模式。
1 n& ?) ^6 n0 ?3 a: C! Y
% q& }* J7 t# n( n O i2c每发送完一个字节,就会产生TXIS标志,当发送完最后一个字节时:
" q8 o! r0 }* x) c5 W" g0 a' ~/ y$ a+ H* c+ D6 }
对于Reload模式,当字节大于255字节时,必须使用此模式,此模式下发送结束后,会产生tcr标志。
4 @( }6 N; Z' q
( ^( r3 H) j+ u6 t2 d+ F. A( V& ` 对于AutoEnd模式,发送后最后一个字节时,会自动产生STOP。
5 Y, A8 b* t7 q# N! I( I5 |3 ]4 Y0 B8 _0 U: L6 {
对于SoftEnd模式,发送完最后一个字节时,会产生tc标志,对于发送过程中需要Restart的需要使用此模式。
) ?- C V: o% H+ Z9 E6 Q: z. \, Y3 d& t" d) f8 E) F! Z O
对于AD5934的读操作,可以事先工作在SoftEnd模式,发送完block read与number bytes read字节后,再转入AutoEnd模式进行Restart,读取完指定的字节后自动产生STOP。操作流程如下:, k; O7 K Q% @% n: |* k6 W( O
+ z7 `% O v2 \# `- HAL_StatusTypeDef HAL_I2C_Mem_Read_AD5934_Block ( I2C_HandleTypeDef * hi2c , uint16_t DevAddress , uint16_t MemAddress , uint16_t MemAddSize , uint8_t * pData , uint16_t Size , uint32_t Timeout )+ f6 r. O0 s9 A* s! t
- {
: d1 M% L7 o& H; X3 ] - uint32_t Sizetmp = 0 ;8 E, u6 O0 S, P7 p s7 z
- / V5 V" N4 ]+ y
- /* Check the parameters */
# f/ l6 T K( j9 H8 X) m- \7 R0 { - assert_param ( IS_I2C_MEMADD_SIZE ( MemAddSize ));
) @$ ?9 I4 [, {+ X - * @% M; O# ?5 W' L! I+ i
- if ( hi2c -> State == HAL_I2C_STATE_READY )
0 ^$ d( t' l! L/ F M1 m4 N# Y, e% m - { ( l9 w' }* Y+ Z/ A
- if (( pData == NULL ) || ( Size == 0 )) ; Y0 c7 B% Z! G3 \: J6 a
- {
1 l5 d. a9 Y# C. a3 ^7 @ - return HAL_ERROR ;
5 j2 h! W) ?! |& v/ h. {% I - }8 G0 n8 _; k- h, ^0 a3 u
- 6 i A3 X- d9 X0 Q% j6 r' \, Y
- if ( __HAL_I2C_GET_FLAG ( hi2c , I2C_FLAG_BUSY ) == SET )5 f/ z& L }" `/ q7 M
- {
+ l6 F1 m6 U) L4 b' k - return HAL_BUSY ;
' W' k. M8 ~& A0 L6 k: Y) j* z6 n - }9 h5 L; N6 t! ^% i4 D
- * f! \! G7 |) P; E/ k4 O
- /* Process Locked */
$ K9 S/ t7 H: a1 C! \5 F - __HAL_LOCK ( hi2c );
5 f, E5 V" V" K5 k' [4 N8 z9 U) e
+ J/ M, Z; G( F- S- hi2c -> State = HAL_I2C_STATE_MEM_BUSY_RX ;
# L7 v2 b# O5 A1 @ - hi2c -> ErrorCode = HAL_I2C_ERROR_NONE ;
9 ?/ G5 E+ d# @/ v. t+ X - /*
0 J/ T0 c: I. E' x - //Send Slave Address and Memory Address % ~, ]7 b0 U( a$ U
- if(I2C_RequestMemoryRead(hi2c, DevAddress, MemAddress, MemAddSize, Timeout) != HAL_OK) f6 }* @9 F% |; B3 V- P! Z
- {# S0 @" s" d2 C, t* a
- if(hi2c->ErrorCode == HAL_I2C_ERROR_AF)- D( z: I) P+ r) f* r, d
- {: o3 W, A; b* N, F
- // Process Unlocked 2 _" j( ?% E, i! O' Y
- __HAL_UNLOCK(hi2c);8 X# B5 o+ M7 B4 ~( _
- return HAL_ERROR;
# L! X! i, Y, @ - }
9 m+ _/ Z2 U; u* }' J9 z, L9 ] - else8 | i# P! D7 k4 n
- {
! Z* l% E: T% o- u2 R - // Process Unlocked
, V6 a. \. l8 G/ U - __HAL_UNLOCK(hi2c);8 d$ b2 z" j- e7 r# D8 s
- return HAL_TIMEOUT;5 M; ^' u% A6 M) V* j
- }
. \8 J# z, Z4 h. [$ } - }*/) @$ K- L/ ^: L& m
2 x! j9 t0 }! {, M: k" v' k- I2C_TransferConfig ( hi2c , DevAddress , MemAddSize + 1 , I2C_SOFTEND_MODE , I2C_GENERATE_START_WRITE );
9 v, v) F, W/ \1 H+ S - . u/ E3 t3 y; J' y
- /* Wait until TXIS flag is set */
7 B3 A' { ]; H - if ( I2C_WaitOnTXISFlagUntilTimeout ( hi2c , Timeout ) != HAL_OK )
: @3 A1 ^( S+ ^0 s - {9 U) Y0 L" D' m0 a& U$ Y
- if ( hi2c -> ErrorCode == HAL_I2C_ERROR_AF ). ]! M: P3 X4 D) }, X' V5 s
- {: S2 p; v& p9 O, Q6 x$ z+ t
- return HAL_ERROR ;: k. ^0 r! _5 s0 j3 _/ c
- }8 x- s9 _+ x* t; g
- else
H/ q8 w! h, A9 ?( C4 q - {
/ E3 R: e C0 D8 i+ L' `: e - return HAL_TIMEOUT ;
$ J/ |9 h7 ]4 C: h7 J; N - }
# a3 x2 R9 }( A0 G+ k" w - }% D" m- F! i. x0 [' t! W! l
3 E& ^4 @6 n- ~3 ?' c- /* If Memory address size is 8Bit */
) c+ ]% u3 a8 [9 a - if ( MemAddSize == I2C_MEMADD_SIZE_8BIT )
7 K4 B) |, D7 q/ |8 x; J$ x9 H - {* q5 Y; G$ w6 Y' ~# u; t8 U
- /* Send Memory Address */9 x8 a/ [# I' R2 O: j
- hi2c -> Instance -> TXDR = __HAL_I2C_MEM_ADD_LSB ( MemAddress ); 3 v$ U7 p% X" I" L
- } ; N! f7 W6 v+ m
- /* If Mememory address size is 16Bit */
( E; ? R: y7 E0 r& P* l7 g, S - else) c6 U# D: p5 O/ h: S* @4 H
- {
0 f) j9 k% Q5 S; P, N/ C - /* Send MSB of Memory Address */! Y0 k( s* T! z i/ s% J v$ k
- hi2c -> Instance -> TXDR = __HAL_I2C_MEM_ADD_MSB ( MemAddress ); 1 V( Z/ x% d8 W8 R7 R
) }3 {/ V, [, K) q% ~! k- /* Wait until TXIS flag is set */7 H4 H L1 P& d8 v( o8 I5 r- a
- if ( I2C_WaitOnTXISFlagUntilTimeout ( hi2c , Timeout ) != HAL_OK )
7 F2 k/ ]7 m: B9 M" F1 P% f2 I - {
1 p7 x: H" E# G0 o4 G) }5 Z - if ( hi2c -> ErrorCode == HAL_I2C_ERROR_AF )
1 o6 R: D1 {9 a. V7 }3 Y6 [ - {
0 Z+ V5 U7 R' y. t - return HAL_ERROR ;' d+ L, a6 E6 D
- }
- A( h% i+ ?4 m - else6 t2 H) L, K. k1 @- r
- {
# V/ e' G& H p, o, q& S# \ - return HAL_TIMEOUT ;
' L! q! T% q( \6 k i; } - }/ J; T4 r, ~4 S: W/ c7 g4 f# U+ o
- }" y% F' \; p2 n- I v
- + @/ h" A0 R0 p+ n
- /* Send LSB of Memory Address */" C2 n( G' _% j5 M* g
- hi2c -> Instance -> TXDR = __HAL_I2C_MEM_ADD_LSB ( MemAddress );
! ~, l6 d# W8 R# G - }
0 h/ I8 g' D. D
; {+ L2 J' j$ C- /* Wait until TXIS flag is set */% g/ e! l( }& ^3 m& f: K
- if ( I2C_WaitOnTXISFlagUntilTimeout ( hi2c , Timeout ) != HAL_OK )5 r: M% z9 f; |- V* q/ f
- {
2 O& v* C9 c1 x$ ^) V" S - if ( hi2c -> ErrorCode == HAL_I2C_ERROR_AF )
. K, O" m5 f0 n; R3 V - {
% ]3 A K9 I4 H W - return HAL_ERROR ;3 ]& ]: `, {5 l7 n: w
- }
5 e+ m( l2 i( G1 V# x7 b - else
$ r1 n( y' J2 {8 c# n: D - {( u+ W; F/ q' P' O
- return HAL_TIMEOUT ;7 X J( ?5 X6 [) i% A6 n* W
- }. r. t/ m4 O# t" s! e
- }
9 Z! i- {% r6 b) T0 r
- U0 b* m. }& Z- hi2c -> Instance -> TXDR = Size ;
2 L4 A: X* R7 k; R& K
9 J) g6 J/ _0 ]" Q- /* Wait until TC flag is set */
( w8 M% i7 n- s( n* ~8 _5 X0 X" T - if ( I2C_WaitOnFlagUntilTimeout ( hi2c , I2C_FLAG_TC , RESET , Timeout ) != HAL_OK ) . m% ~. L7 K$ V2 l: w
- {0 E+ P6 A; D2 ^/ z" Z8 m7 m6 d2 |
- return HAL_TIMEOUT ;
4 Y% w. C% T' ~% ~ - }
- H4 u% n% u0 t$ |
3 t; M* o g3 T) f" F- /* Send Slave Address */
) m$ P- A* j5 x4 Q% @. l - /* Set NBYTES to write and reload if size > 255 and generate RESTART */3 U+ G* m; i$ w I0 v8 ]* y
- /* Size > 255, need to set RELOAD bit */9 h" B/ |9 S/ P1 O3 H
- if ( Size > 255 )( _8 T8 \( ?: s3 Q4 g) ^
- {
& u% k! P5 V( ` - I2C_TransferConfig ( hi2c , DevAddress , 255 , I2C_RELOAD_MODE , I2C_GENERATE_START_READ );( t6 l& z) k! U' r; v7 `0 F
- Sizetmp = 255 ;4 i9 m& ^, I6 K% _, M, U1 g9 D# O: f
- }; i+ K, q2 @9 @' _% `
- else
" P4 y4 \( |) q9 H q" R9 T - {
& m4 m' H# g: J$ q6 s; M8 ~ - I2C_TransferConfig ( hi2c , DevAddress , Size , I2C_AUTOEND_MODE , I2C_GENERATE_START_READ );
, R' [/ o" m8 @9 d* }4 ]0 \ - Sizetmp = Size ;7 N4 l$ m2 x: y2 N) r' V; j8 X4 s
- }
, A9 o3 G; K) R5 J - / p# r2 b" \" O
- do
8 C) X; `4 m- u" y - {
7 G" W& q4 V8 B, ~6 w - /* Wait until RXNE flag is set */
! Y V' H# D8 k+ t, a& [ - if ( I2C_WaitOnFlagUntilTimeout ( hi2c , I2C_FLAG_RXNE , RESET , Timeout ) != HAL_OK ) ' Y7 I7 R: c( U0 ]; A' S @
- {) e# y' Y: f4 b# i* M
- return HAL_TIMEOUT ;
, e, p. S" a4 T; f2 p- m - }
- c: G! |& d7 O9 p; f$ N3 f# z
( O' w C& r2 R5 R- L+ t- /* Read data from RXDR */
, i" `; s/ r: h+ O - (* pData ++) = hi2c -> Instance -> RXDR ;, [* H0 I7 ~0 g% {# `. f/ Z8 j5 N
! |' B; P3 g& g2 P- /* Decrement the Size counter */9 t, @. x0 t8 r5 {' d/ F
- Sizetmp --;8 l1 Z, Q* k. {: i2 A6 o4 y. q
- Size --; 1 ?' N: z$ N: x; ~: s$ ~4 V
- - D1 _: e) N# `4 l9 Y
- if (( Sizetmp == 0 )&&( Size != 0 ))
* Y: H: L- L, _8 E! z; E - {6 M& G5 D0 _+ Q% l2 V
- /* Wait until TCR flag is set */
; j& g. i! P# X4 `7 } - if ( I2C_WaitOnFlagUntilTimeout ( hi2c , I2C_FLAG_TCR , RESET , Timeout ) != HAL_OK )
& K7 w2 R. F6 M3 X' A: J" H* O* h) S0 D - {
& c; ~# y6 K* J/ R6 m) } - return HAL_TIMEOUT ;5 X& S5 I( w' A5 G. [! Y, Y
- }
# q5 B6 n' J# n0 f! e, T* v - 8 e% j7 N# i4 Z; |
- if ( Size > 255 )
7 ]. O( w0 l3 Q' u- _5 [" n - {
- h3 a; D6 ^$ m* E9 k" R - I2C_TransferConfig ( hi2c , DevAddress , 255 , I2C_RELOAD_MODE , I2C_NO_STARTSTOP );: u3 ]7 J0 I" @: p# t$ ~6 U! I2 f
- Sizetmp = 255 ;) I% H6 G m% b7 d2 A
- }; q* u1 C! e+ }9 a& ~! S
- else! F/ ~8 f, `1 R; V
- {
! N1 g z0 p& p( ^ - I2C_TransferConfig ( hi2c , DevAddress , Size , I2C_AUTOEND_MODE , I2C_NO_STARTSTOP );
) R* e: r2 x/ y4 U3 j" t7 o - Sizetmp = Size ;
s2 z) B( V3 ?# N - }
# u; Z" R# Y1 h8 y4 r, C- l - }
* ~; ^8 a; m' m9 v
9 [5 {6 j0 Q/ O- } while ( Size > 0 ); n7 l0 N3 i: o- {4 H
# f" d$ b, r9 ]! o! H* g3 l3 p1 M- /* No need to Check TC flag, with AUTOEND mode the stop is automatically generated */& F" ~5 Q+ @9 C1 X- ?0 O* M2 ^
- /* Wait until STOPF flag is reset */
6 t. ]0 g9 f9 x; f6 a - if ( I2C_WaitOnSTOPFlagUntilTimeout ( hi2c , I2C_TIMEOUT_STOPF ) != HAL_OK )/ ]) W* O! N) U6 J
- {
; x. B( T9 e4 O3 d0 K3 b" K& C - if ( hi2c -> ErrorCode == HAL_I2C_ERROR_AF )9 H) f/ c3 M/ h/ t
- {% N" H3 k8 O6 C* v8 t' Y, v- a
- return HAL_ERROR ;
T' e! c3 I N' z8 u& q - }
q, d" @4 O+ i f4 |" n - else1 H7 ^& N. P3 w- r) U6 @/ q6 |
- {
" W6 w2 \5 ]0 @+ z - return HAL_TIMEOUT ;
! Y: i f! p' r" M: e - }
- w0 R' Q, i* a \2 G+ u - }" R0 t0 l4 U, N# T. i. b/ y
3 v# l5 z1 B1 y% J! }% {- /* Clear STOP Flag */$ }; f8 _# J$ y3 Y8 t
- __HAL_I2C_CLEAR_FLAG ( hi2c , I2C_FLAG_STOPF );
8 a% r8 c- S5 n! q7 ?$ ] - ( d2 T# I/ }+ q7 D) C2 m
- /* Clear Configuration Register 2 */
9 W, e: }3 O6 x, j1 y - __HAL_I2C_RESET_CR2 ( hi2c );
4 v/ x. y) ^( i+ E
Q% b. L1 ]# G2 g+ e6 J2 \- hi2c -> State = HAL_I2C_STATE_READY ;
. K. x; n( h+ e9 U6 j
! s1 p$ c8 a( K% M" P$ d4 N- /* Process Unlocked */
) z# V" S6 j# ]. I1 C4 W4 G% C - __HAL_UNLOCK ( hi2c );
8 O5 y3 ?+ B4 Q: Q% w( U) Q _
" v T* n' v5 S3 F5 y- return HAL_OK ;5 Z! W2 [# T3 m: q
- }
* i1 ~0 ?4 W1 [9 @: g0 X6 C8 c - else
9 a# E3 ~4 F8 z# ~2 o, V+ v - {
3 F5 Q, S$ N/ g, J9 j& O - return HAL_BUSY ;! V/ o. C; i' O! ]
- }
' A" q5 b, T0 ^- N+ v6 I: Z - }
6 U5 e6 A c: N
复制代码
) ~3 @+ U% W5 D2 u; ?# ?* p, i
. @- M' ^7 [4 V: O' ? |