|
简述 IIC(Inter-Integrated Circuit)其实是IICBus简称,它是一种串行通信总线,使用多主从架构,在STM32开发中经常见到。 使用面向对象的编程思想封装IIC驱动,将IIC的属性和操作封装成一个库,在需要创建一个IIC设备时只需要实例化一个IIC对象即可,本文是基于STM32和HAL库做进一步封装的。 底层驱动方法不重要,封装的思想很重要。在完成对IIC驱动的封装之后借助继承特性实现AT24C64存储器的驱动开发,仍使用面向对象的思想封装AT24C64驱动。 . l; J1 r4 N/ U0 Q8 p
IIC驱动面向对象封装 iic.h头文件主要是类模板的定义,具体如下: - //定义IIC类
( d# e1 k4 H. M, |) U) F - typedef struct IIC_Type
# H/ C. {! }8 i - {8 S2 s+ N( S3 H K& D0 S
- //属性1 Z, p: [+ A8 L4 K
- GPIO_TypeDef *GPIOx_SCL; //GPIO_SCL所属的GPIO组(如:GPIOA)
0 _* u; Z. z# q; }" y% ]" m. M7 a - GPIO_TypeDef *GPIOx_SDA; //GPIO_SDA所属的GPIO组(如:GPIOA)5 V9 s! h2 N3 o: J1 e1 Z
- uint32_t GPIO_SCL; //GPIO_SCL的IO引脚(如:GPIO_PIN_0)( C; L- R$ {3 U6 k4 n6 y
- uint32_t GPIO_SDA; //GPIO_SDA的IO引脚(如:GPIO_PIN_0)2 s* q1 l8 A0 k5 B5 ~
- //操作
3 H2 T. r6 g( k9 I+ X+ { - void (*IIC_Init)(const struct IIC_Type*); //IIC_Init8 m) A' m- r* B7 Z
- void (*IIC_Start)(const struct IIC_Type*); //IIC_Start3 j$ |2 Q5 P! l7 A1 j$ E1 K* i6 h
- void (*IIC_Stop)(const struct IIC_Type*); //IIC_Stop
, K% ^1 B4 n# z+ m, _ - uint8_t (*IIC_Wait_Ack)(const struct IIC_Type*); //IIC_Wait_ack,返回wait失败或是成功 ]3 z4 W8 {' M& J6 e
- void (*IIC_Ack)(const struct IIC_Type*); //IIC_Ack,IIC发送ACK信号
) G& I/ a1 j! g7 v* q0 \7 X - void (*IIC_NAck)(const struct IIC_Type*); //IIC_NAck,IIC发送NACK信号$ ^% X* c6 K. G' N: u2 q
- void (*IIC_Send_Byte)(const struct IIC_Type*,uint8_t); //IIC_Send_Byte,入口参数为要发送的字节# v3 B5 W, s1 \
- uint8_t (*IIC_Read_Byte)(const struct IIC_Type*,uint8_t); //IIC_Send_Byte,入口参数为是否要发送ACK信号
# Z! M& A* f- [5 C$ U2 w5 x - void (*delay_us)(uint32_t); //us延时
( k. c4 y' M4 ~' v' N - }IIC_TypeDef;
复制代码 3 @' E! C0 H( j
8 Q* p5 ]% J3 i1 n* j: k4 q
iic.c源文件主要是类模板具体操作函数的实现,具体如下:
) B# s4 H j' j) C2 M9 i8 B- //设置SDA为输入模式4 v e b9 ]4 @3 f7 t0 [ z
- static void SDA_IN(const struct IIC_Type* IIC_Type_t)
6 _/ b: `3 b' F E; N, z - {+ b: _- N- T3 k1 J( F8 L1 E
- uint8_t io_num = 0; //定义io Num号
; i$ {: @9 Q2 L" l' ]! ]/ ^4 ]( U - switch(IIC_Type_t->GPIO_SDA)7 s& v, \; {7 f& t1 X5 {5 N
- {
4 b( t4 r* a6 I - case GPIO_PIN_0:2 P1 c1 h$ K# \# U( B1 a
- io_num = 0;) D, P/ ?; w5 b& @( h' e
- break;1 n; O3 v4 c. A
- case GPIO_PIN_1:
" q! ~% Z% k; j" _# f' J" j+ y% k - io_num = 1;
# F) t+ ^- ` f; ?/ ~- f& A - break;
3 t9 P7 Z H; p }. Q, n6 J/ g; _ - case GPIO_PIN_2:
! ^% ^% |/ c1 ?2 s - io_num = 2;, t, `, T3 {5 \& M; h1 Q5 T7 P& k- i
- break;
1 Y& b# M, }/ i2 o* r/ [" W1 t5 p" w - case GPIO_PIN_3:2 v1 ?+ C; z: e6 L0 r' z( @' T* E0 e
- io_num = 3;
: m. N8 l1 b4 Q; L _6 H, u3 n - break;! g. _. t2 h- c& d" M
- case GPIO_PIN_4:" _) }5 R/ X, Z9 b$ G w0 A% Y
- io_num = 4;
- Z) `7 I% ~$ G8 q - break;
4 R7 Z9 d3 o0 B8 \6 m; X - case GPIO_PIN_5:
$ D( `1 B; }6 M# B- o - io_num = 5;* Y/ x* e* F4 M. R& S
- break; 4 W# m5 k% ^5 u3 t9 `5 R/ f& @3 `
- case GPIO_PIN_6:
2 [0 i" Y; C% y% x, b' }- `- ` - io_num = 6;7 T5 o) @1 ?0 `/ R' r/ r4 S* e+ K
- break;
8 M m+ }( @4 } [/ Y - case GPIO_PIN_7:
% A! W) i2 M+ C* O" R - io_num = 7;
2 p, B# m/ ~$ q" R6 L9 p - break;& ~$ s% R' Q8 P
- case GPIO_PIN_8:5 |6 G; m) H/ n) o
- io_num = 8;. L- Q0 R& ^; V: z
- break; 5 E) k3 n$ e7 G& U* ?
- case GPIO_PIN_9:
' ^& C' p! h, k1 h' j7 [$ I) ~ - io_num = 9;( L! m1 k. o' b8 q& m5 W2 c
- break;
1 P7 G0 P4 |2 B% C2 p( j3 E" T - case GPIO_PIN_10:- v( Y$ b. f# r F6 O4 J
- io_num = 10;
0 @! K& _4 v( S* D* o7 H7 w - break;
* x. s( ]0 I b$ G% L2 k P3 c - case GPIO_PIN_11:
9 f* f" q2 f, B0 C( p0 B9 H - io_num = 11;
0 A# ~. G ]+ m {% O" l0 Q/ P; v - break; 0 T$ G+ e7 Y. s% x/ Y [, V. P' G3 G
- case GPIO_PIN_12:+ T/ L/ B/ L' M; C! h
- io_num = 12;
, ]/ k1 c, T" W7 n - break;+ P) @( X0 `; v, `" G' |2 j# U
- case GPIO_PIN_13:& h2 l, t6 j9 w/ L! ~+ k
- io_num = 13;0 X% N* B' U/ \ J# ^
- break;
) M: C8 A$ R- S( J - case GPIO_PIN_14:& d* h$ |5 X3 X% z$ T+ x
- io_num = 14;
* [5 ~( i0 a$ P; a! m$ |/ o0 V - break; 8 Z, A- u0 X3 E6 ]
- case GPIO_PIN_15:
3 b# k/ L4 Z& s/ g4 M* [: h8 i - io_num = 15;& \+ }' S( O+ L( y
- break;
8 t: a2 I- A. A. H7 B8 Y8 M( j - }4 r/ R, W: Z6 r8 g& [% ^
- IIC_Type_t->GPIOx_SDA->MODER&=~(3<<(io_num*2)); //将GPIOx_SDA->GPIO_SDA清零1 O+ C) `3 D- K2 `# ]
- IIC_Type_t->GPIOx_SDA->MODER|=0<<(io_num*2); //将GPIOx_SDA->GPIO_SDA设置为输入模式; N# J7 i ?, O
- }
- N2 o+ d: B5 \% x- S# i9 U% Q1 f3 \: K - 2 A" k- W2 n; x9 q7 n7 h Z
- //设置SDA为输出模式0 w& K1 I- P9 {* h! \& ]
- static void SDA_OUT(const struct IIC_Type* IIC_Type_t)
" i4 g% T- D' i6 r1 l' m - {- t* v! x$ s [# x# t$ b# k8 h
- uint8_t io_num = 0; //定义io Num号
0 Z5 W& @$ I$ h6 |% ]8 `, q - switch(IIC_Type_t->GPIO_SDA)
# w* j8 d, i5 z# X. ^ - {
) w. Z& l5 D# I: p3 v! S0 b - case GPIO_PIN_0:
% u9 {. f0 |2 v$ d, N6 A: x7 d - io_num = 0;
% @5 V; o% P2 N0 x5 Z - break;
1 a/ m+ v: R/ r( L; Q: T( ` - case GPIO_PIN_1:; N1 t2 _1 A! [6 j0 ?5 x4 x
- io_num = 1;
% d- [6 Q9 d% ~) b1 u - break;
% S( k1 P9 \( v5 z - case GPIO_PIN_2:
: H( Z2 p' V! o5 o1 \* @ - io_num = 2;
4 m4 `$ N, ?. c0 f0 s - break; ' K0 Z; R, c1 F* S- u3 k! x
- case GPIO_PIN_3:
8 A, f" q# \- \1 a b - io_num = 3;; Q" o& Q; [" f( ?
- break;
5 {' S! B; w# H3 E* @2 i) w - case GPIO_PIN_4:
" _: T5 e5 s/ W$ K3 X, v s- e - io_num = 4;
) y% U6 o5 a3 [ t# o - break;
* A _! P p& E8 E5 @- f - case GPIO_PIN_5:
* ^) a2 H, @' C - io_num = 5;
2 I% a! [% @. _- z; b4 R - break; ( ^3 G9 _. w4 q( K
- case GPIO_PIN_6:
* I; |1 O5 ^6 `' J0 A8 z - io_num = 6;2 {4 C* R T1 ?' q) F9 E
- break; - l) o$ l: h' O3 V
- case GPIO_PIN_7: q. Z; `3 M( r; h
- io_num = 7;( T% N! W& `. R0 {) v# D& r3 q4 f
- break;
! G" [1 I K ~ - case GPIO_PIN_8: W8 o% K1 N8 a
- io_num = 8;5 y# Z8 {! ?) G2 I% a
- break;
" k( u+ e8 Y+ C* A# G - case GPIO_PIN_9:
" A% w9 K3 R9 L$ x# W - io_num = 9;9 d! {; B+ Z, d) M
- break;
- B; L5 u2 O1 ?0 |6 v$ J - case GPIO_PIN_10:8 d; A& Z0 a" k6 V$ B& M
- io_num = 10;
) |4 c, ~5 \( `) n - break;
4 i: U% V9 V u0 `1 \+ A4 s - case GPIO_PIN_11:
. R+ _: ]% {% \0 R - io_num = 11;& X1 \: ~! k+ L, k! x
- break; - {( R: f/ I5 F3 J3 I4 Z/ i8 B* V
- case GPIO_PIN_12:
) c, i- f7 `4 @- G0 z! u) N - io_num = 12;
/ e' @4 ]" p$ y7 i( ^+ T v - break;8 ~/ r8 V# Z. C6 q
- case GPIO_PIN_13:
+ ^( H! |% }. p' Q5 C- w - io_num = 13; e% ^6 ?9 P3 Z x
- break; B9 e5 r# |/ p5 S, T. A
- case GPIO_PIN_14:
' y6 x' r8 j& t1 y# p; A8 J* | - io_num = 14;
, `1 g7 c) L' G$ z( { - break; . Z& ~- V3 ?8 R0 |# f* J" c! P5 Z+ ]
- case GPIO_PIN_15:
# A8 ]7 k8 K5 I" y4 a$ t9 o; _. s - io_num = 15;8 e) U2 H; K9 u2 A
- break;
2 H, k& S. J; M! ~7 W - }" N" G& e0 c! ]
- IIC_Type_t->GPIOx_SDA->MODER&=~(3<<(io_num*2)); //将GPIOx_SDA->GPIO_SDA清零* |; a8 Z6 a6 [- y' k- h0 I& i8 n
- IIC_Type_t->GPIOx_SDA->MODER|=1<<(io_num*2); //将GPIOx_SDA->GPIO_SDA设置为输出模式$ y' J, U E4 q
- }6 H' F* J) R) a1 R' ~+ K9 D0 {0 H, B
- //设置SCL电平
+ X# [. Z- m; O' e5 S- n - static void IIC_SCL(const struct IIC_Type* IIC_Type_t,int n)
2 q! u. v4 f4 K - {
9 t* P+ [. l# ^0 p3 h) V - if(n == 1)
/ b( B# y6 f/ p) }' m3 E3 } - {, j. K$ o7 m0 p; X0 t6 R* V4 S- w: j! m
- HAL_GPIO_WritePin(IIC_Type_t->GPIOx_SCL,IIC_Type_t->GPIO_SCL,GPIO_PIN_SET); //设置SCL为高电平$ L% X C) q+ i9 S# j
- }
1 ^0 j2 L& }# P. W. ^+ ` - else{$ U' `5 F R) F$ t% @2 ^! G
- HAL_GPIO_WritePin(IIC_Type_t->GPIOx_SCL,IIC_Type_t->GPIO_SCL,GPIO_PIN_RESET); //设置SCL为低电平
8 y7 R9 r; H2 h# i! m, { { - }" L; \1 h6 q1 D2 C9 [
- }
1 t3 N% O, C8 w1 P5 t0 Y - //设置SDA电平; E; m) M/ c9 k' ^( ~, g
- static void IIC_SDA(const struct IIC_Type* IIC_Type_t,int n)5 B) w; z- v' O" |, N3 C
- {- H9 _9 W: j4 u- t6 X
- if(n == 1). u3 H0 ?& j" \7 B% c, J( J
- {. W1 l; I- y8 j- p# n+ s' L ?
- HAL_GPIO_WritePin(IIC_Type_t->GPIOx_SDA,IIC_Type_t->GPIO_SDA,GPIO_PIN_SET); //设置SDA为高电平
/ d) s: `2 c6 r. K - }: J1 H% ?- l- t: P9 N: e) R0 l
- else{
( B: u2 |/ y- }6 y: g; h! } - HAL_GPIO_WritePin(IIC_Type_t->GPIOx_SDA,IIC_Type_t->GPIO_SDA,GPIO_PIN_RESET); //设置SDA为低电平
) M/ Y6 Y' n8 b1 r+ g - }3 t& C4 X' P) p1 }
- }
1 W0 u/ X1 P2 Y# b - //读取SDA电平
# M8 o' [$ a' v( x - static uint8_t READ_SDA(const struct IIC_Type* IIC_Type_t)
: P( G1 G1 n% x* I - {" e6 ]! n5 e4 x! z- s% d5 N' h
- return HAL_GPIO_ReadPin(IIC_Type_t->GPIOx_SDA,IIC_Type_t->GPIO_SDA); //读取SDA电平* X. E- Y( X& n& y" a0 }/ o' J
- }
. o w5 s8 D9 C6 i2 X/ V e0 v - //IIC初始化
7 O/ }: k0 b2 B" Z; s" I - static void IIC_Init_t(const struct IIC_Type* IIC_Type_t)
" h5 j8 S' x% ~1 k - {7 Y) V6 T7 \% w3 q: E
- GPIO_InitTypeDef GPIO_Initure;1 M" \& u' p8 X" A' L
4 U1 a2 Z6 x! E _) {4 |. q- //根据GPIO组初始化GPIO时钟: R( F, j; x2 F' Q
- if(IIC_Type_t->GPIOx_SCL == GPIOA || IIC_Type_t->GPIOx_SDA == GPIOA)
- }# l7 W& L: C' T - {8 P+ t8 J3 k3 o) d) J1 A+ u
- __HAL_RCC_GPIOA_CLK_ENABLE(); //使能GPIOA时钟, \4 `- J! q, i' e. K- `* y* }
- }
4 ^% ~! l; E j/ Q - if(IIC_Type_t->GPIOx_SCL == GPIOB || IIC_Type_t->GPIOx_SDA == GPIOB)
0 Q5 f7 @ ?3 ~# Z0 T: W" ] - {
/ k2 E# j% \' y - __HAL_RCC_GPIOB_CLK_ENABLE(); //使能GPIOB时钟
4 w$ @. _3 ~- Y - }
/ {& M5 F7 o( [! A& D9 i - if(IIC_Type_t->GPIOx_SCL == GPIOC || IIC_Type_t->GPIOx_SDA == GPIOC)) Q. @' x5 B: u6 d0 X, _
- {
( ^0 j2 F& @! k( `" \3 d - __HAL_RCC_GPIOC_CLK_ENABLE(); //使能GPIOC时钟 z& N$ Z! @; }( z9 ^
- }$ b0 h# r4 q! o/ u1 C/ M) k. R
- if(IIC_Type_t->GPIOx_SCL == GPIOD || IIC_Type_t->GPIOx_SDA == GPIOD)! l8 F2 p: H6 V+ i7 c
- {6 Q4 w7 w: Q7 I$ ]8 ~( v# V: Z1 E
- __HAL_RCC_GPIOD_CLK_ENABLE(); //使能GPIOD时钟' J( m0 w0 w+ ~$ m2 c% v* G
- }) M7 h- Z) @0 [1 c3 Z
- if(IIC_Type_t->GPIOx_SCL == GPIOE || IIC_Type_t->GPIOx_SDA == GPIOE)
6 ~& f6 L1 X. r/ ?! d* `0 h3 F - {
- A( P( p# [0 O" ?1 b - __HAL_RCC_GPIOE_CLK_ENABLE(); //使能GPIOE时钟4 W) ~* j$ z7 B! f
- }
+ w: n A2 d" c L - if(IIC_Type_t->GPIOx_SCL == GPIOH || IIC_Type_t->GPIOx_SDA == GPIOH)
+ r/ l9 [6 k! V, f+ \" K* Y+ g/ E1 m - {
3 p, ]" @" l2 Q f4 D - __HAL_RCC_GPIOH_CLK_ENABLE(); //使能GPIOH时钟
0 f. u0 }2 f6 p3 L/ u0 D5 m - } : U7 Y( B% ~: j7 W. q$ [
) A( p6 h4 s" S) P7 j4 c; s( {: I/ I- //GPIO_SCL初始化设置
5 A/ W D7 _* a! `9 j' m" l - GPIO_Initure.Pin=IIC_Type_t->GPIO_SCL;1 }& X3 V2 U9 ^+ Y" k4 n
- GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
w M. E2 I8 d. i& y# D - GPIO_Initure.Pull=GPIO_PULLUP; //上拉" K; T5 S" N' [. p
- GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //快速( ]8 r% X! [# Q3 \
- HAL_GPIO_Init(IIC_Type_t->GPIOx_SCL,&GPIO_Initure);/ p' M9 i. f& S- u s# W2 ?* ] I) l
- //GPIO_SDA初始化设置
' e4 {0 S% a8 B- q" B0 `* t, N - GPIO_Initure.Pin=IIC_Type_t->GPIO_SDA;& m7 d& z! k$ |
- GPIO_Initure.Mode=GPIO_MODE_OUTPUT_PP; //推挽输出
; {( Q( w+ a7 m- g+ z2 c1 L - GPIO_Initure.Pull=GPIO_PULLUP; //上拉7 ^' P/ L1 e8 z& [
- GPIO_Initure.Speed=GPIO_SPEED_FREQ_VERY_HIGH; //快速; M8 f4 w) r! b9 `" y* \/ D
- HAL_GPIO_Init(IIC_Type_t->GPIOx_SDA,&GPIO_Initure);
3 [* i" E; h) |3 e; j% G/ r$ H
3 ]3 L( y) [+ }) g* N, B- X9 w- //SCL与SDA的初始化均为高电平5 O: e9 b7 ]% [ c9 u
- IIC_SCL(IIC_Type_t,1);
% a N f" k( e7 z: c: J% x8 ] - IIC_SDA(IIC_Type_t,1);
- v+ r2 W0 L- w9 s- K0 \ - }
' Y: |( b0 V+ n e9 o7 t - //IIC Start
* d9 `# h; P) b4 } - static void IIC_Start_t(const struct IIC_Type* IIC_Type_t)2 }, o2 G" G/ W! ]4 I0 a( u, V8 B
- {
3 n* C* R. b" X4 j( x3 j - SDA_OUT(IIC_Type_t); //sda线输出 b. M% k4 V9 m- l' O
- IIC_SDA(IIC_Type_t,1);
2 u- o8 U* s) l; `$ Y2 y; Y - IIC_SCL(IIC_Type_t,1);
& i3 K ` l, G G3 \8 F - IIC_Type_t->delay_us(4);% k, L/ q( @% b T. \7 K: z' f
- IIC_SDA(IIC_Type_t,0); //START:when CLK is high,DATA change form high to low
" ?6 O- e6 {0 ~3 s - IIC_Type_t->delay_us(4);
) k* p* y* ^2 g7 t% Z - IIC_SCL(IIC_Type_t,0); //钳住I2C总线,准备发送或接收数据
; _* k: O) I: |( o3 k - }' K, B3 E1 y' a7 L1 c
- //IIC Stop/ [' U9 o& V Q0 s
- static void IIC_Stop_t(const struct IIC_Type* IIC_Type_t)
d8 O# I1 P3 _5 n+ X/ z* `% { - {
' P% O$ A& Z" m0 V9 w0 V8 g - SDA_OUT(IIC_Type_t); //sda线输出/ p1 c6 z E {: q% z- E8 i
- IIC_SCL(IIC_Type_t,0);9 D7 @" ~' ]( m& P( ~
- IIC_SDA(IIC_Type_t,0); //STOP:when CLK is high DATA change form low to high4 m% F' |1 T9 @+ c( q
- IIC_Type_t->delay_us(4);% `9 R0 Y+ p! x B/ ?3 p y
- IIC_SCL(IIC_Type_t,1); ! i0 i! J! Z9 ]% \# \
- IIC_SDA(IIC_Type_t,1); //发送I2C总线结束信号' E( X: e" ~% E& l; G$ f
- IIC_Type_t->delay_us(4);
1 a- F+ {- v+ X+ g - }
R2 @1 t1 X! I, t. m9 D' L2 a - //IIC_Wait_ack 返回HAL_OK表示wait成功,返回HAL_ERROR表示wait失败; X# f+ u0 N' q8 p9 J9 W5 ]; {
- static uint8_t IIC_Wait_Ack_t(const struct IIC_Type* IIC_Type_t) //IIC_Wait_ack,返回wait失败或是成功4 p+ |+ R9 W1 D
- {
( U. Q1 O, B; v - uint8_t ucErrTime = 0;1 F% o- H1 w: w8 h+ M
- SDA_IN(IIC_Type_t); //SDA设置为输入 ; O: \1 P5 k X! v" P) Y7 A7 u
- IIC_SDA(IIC_Type_t,1);IIC_Type_t->delay_us(1); 4 H8 H# g" R3 n& x5 }0 D% Z
- IIC_SCL(IIC_Type_t,1);IIC_Type_t->delay_us(1);
4 \' \' q3 I* R4 G* Y9 H' I- x - while(READ_SDA(IIC_Type_t)), c% r; d$ S8 Z) p" x) N/ c' h
- {
7 k. i# T! x C: ? - ucErrTime++;
" q6 J* U1 {, [# u3 f - if(ucErrTime>250)* _" ^; s$ _% Y3 E' {+ f
- {$ I* M. j; z8 w% q# a
- IIC_Type_t->IIC_Stop(IIC_Type_t);
9 M, V7 g: V6 A! p/ H - return HAL_ERROR;" U7 T. r) C5 b% Z
- }3 l0 l$ a+ B+ U/ F4 m9 ?
- }
7 f1 `' j% Y7 P* b - IIC_SCL(IIC_Type_t,0);//时钟输出0 + s. f/ V) i7 Z6 ]( X! ~6 z
- return HAL_OK;
$ j% z/ E E/ z% Y! F: O - }
6 m4 j* b% T; d2 Z! ? - //产生ACK应答2 Z( ]7 B, B5 Y/ I4 I+ X6 |/ A
- static void IIC_Ack_t(const struct IIC_Type* IIC_Type_t) ! `, l1 V% K$ @! Y) s: @
- {, ~: v5 n- M7 z' f
- IIC_SCL(IIC_Type_t,0);
4 s1 l& o: P3 N5 Q/ Z8 P/ r - SDA_OUT(IIC_Type_t);' T- {0 d0 O! e7 V3 Q3 p
- IIC_SDA(IIC_Type_t,0);4 \$ d) _/ J2 r3 l
- IIC_Type_t->delay_us(2);
" X: ?: u. ~+ m2 q* C! I - IIC_SCL(IIC_Type_t,1);
# M0 O5 I) R/ v3 {# B* W' h* t - IIC_Type_t->delay_us(2);
. ?) g7 ~, f+ ~+ b7 o - IIC_SCL(IIC_Type_t,0);- }; R7 y6 B7 Y3 `) r5 w; T- g& L
- }4 i6 b6 i# ~' G- C1 K
- //产生NACK应答
, d+ q/ I' ^: K) p% h - static void IIC_NAck_t(const struct IIC_Type* IIC_Type_t) 8 @& X6 _& P- f8 [9 `4 ?8 [9 \
- {
) p4 Q9 z: E0 _! N - IIC_SCL(IIC_Type_t,0);
% |" U/ H, k% y1 S - SDA_OUT(IIC_Type_t);
, g# j( Y: G( L( l1 `$ T Z+ V - IIC_SDA(IIC_Type_t,1);
- X; c. ^2 P7 p. ^6 r) k* U - IIC_Type_t->delay_us(2);
, Y2 d. `: c6 ~ @, s# [* R - IIC_SCL(IIC_Type_t,1);; T' O* m# W# T) |0 x
- IIC_Type_t->delay_us(2); |0 M. t" n+ D3 [/ c$ ?
- IIC_SCL(IIC_Type_t,0);( S! n8 u _) a3 n8 \% Z( A" i8 U4 M
- }
5 T' X) b; y9 H z - //IIC_Send_Byte,入口参数为要发送的字节8 p6 o$ n+ S$ Y
- static void IIC_Send_Byte_t(const struct IIC_Type* IIC_Type_t,uint8_t txd) 7 |2 A( C# k/ j, L1 v
- {% I2 _( G- ^. R K) _
- uint8_t t = 0;
4 I; |% q; x# a! X2 i( i7 f - SDA_OUT(IIC_Type_t); 9 {7 j6 D- y5 C: j/ w. z
- IIC_SCL(IIC_Type_t,0);//拉低时钟开始数据传输" e1 r5 U* k, ^, k6 c) X
- for(t=0;t<8;t++)) z' R& ~3 L" |" }
- { 1 w n2 |: m0 V9 o7 a
- IIC_SDA(IIC_Type_t,(txd&0x80)>>7);
7 {3 g# J+ V( l - txd <<= 1;
) z6 ]$ l5 V' C3 S - IIC_Type_t->delay_us(2); //对TEA5767这三个延时都是必须的
* g# U6 |- |7 n4 v" v2 @ - IIC_SCL(IIC_Type_t,1);
s3 Z: f& ^4 s1 e+ l" G - IIC_Type_t->delay_us(2);
9 Q2 Q7 o: ]2 x1 e# w - IIC_SCL(IIC_Type_t,0);
! f2 _8 i- A" d- F" e* G+ b - IIC_Type_t->delay_us(2);
, m/ @9 F& b' l# Q - }
2 p6 D8 a9 M! s# x e - }8 B! [; @1 Q1 S% y3 h- Q8 }! a
- //IIC_Send_Byte,入口参数为是否要发送ACK信号
; ?4 A( y6 w* [. |% U - static uint8_t IIC_Read_Byte_t(const struct IIC_Type* IIC_Type_t,uint8_t ack)
. b9 G: J1 j* U6 Q - {
0 |3 `+ L; v, N6 G: B5 r - uint8_t i,receive = 0;
, C1 l& _' P0 K, x& \' H - SDA_IN(IIC_Type_t);//SDA设置为输入
" Q. R; P$ r' t' X! ] - for(i=0;i<8;i++ )
7 x q2 N* [0 J! x8 b8 J - {+ ^) h5 Y- g9 x# }( R* h( q, \
- IIC_SCL(IIC_Type_t,0); s E2 @5 Z8 _4 ]) J+ ~
- IIC_Type_t->delay_us(2);
9 O( l' P7 i5 o7 E" ? - IIC_SCL(IIC_Type_t,1);
2 A! ~( F3 M9 W; U# g$ y - receive<<=1;" Z) i$ k& h% c
- if(READ_SDA(IIC_Type_t))receive++;
5 N4 a; n* y- G( y) O W; T8 }+ V - IIC_Type_t->delay_us(1);
, k6 Y2 I5 }/ c5 G- H6 j - } ) D @0 A% d k! @* y" V# u. s
- if (!ack)" _. K. t% ]/ ?8 J$ i
- IIC_Type_t->IIC_NAck(IIC_Type_t);//发送nACK
5 n+ Y Z5 w3 S; b" L% B - else) s' ^0 |& j. Q7 ]6 ]6 c
- IIC_Type_t->IIC_Ack(IIC_Type_t); //发送ACK : A S- L( L9 S; S M4 K* ]
- return receive;
7 w n. y0 B4 M - }2 F) ~3 E# ^. L& }
- //实例化一个IIC1外设,相当于一个结构体变量,可以直接在其他文件中使用
8 a4 s, f: |" R9 W0 u - IIC_TypeDef IIC1 = {" l. C! u3 c6 s
- .GPIOx_SCL = GPIOA, //GPIO组为GPIOA
& h- w- v. `+ P& p6 |/ } - .GPIOx_SDA = GPIOA, //GPIO组为GPIOA+ |0 J- o$ ?( a' l z/ r% W. Z
- .GPIO_SCL = GPIO_PIN_5, //GPIO为PIN51 N; _$ A5 N8 q$ |+ x
- .GPIO_SDA = GPIO_PIN_6, //GPIO为PIN6
! n- B( w/ B/ c/ v I- u$ z: S - .IIC_Init = IIC_Init_t,8 q4 l* Q) o2 n$ e1 W0 k
- .IIC_Start = IIC_Start_t, S5 e! \8 {: q1 u4 C
- .IIC_Stop = IIC_Stop_t,
- Z' V$ c! N7 K$ \. M2 g - .IIC_Wait_Ack = IIC_Wait_Ack_t,: A; U( W4 j+ K+ t3 z' ]6 ~
- .IIC_Ack = IIC_Ack_t,
6 k& r( B, }5 N; S7 q - .IIC_NAck = IIC_NAck_t,; _' |3 m# S$ T
- .IIC_Send_Byte = IIC_Send_Byte_t,
. M, @$ r7 L* |2 W) _7 I { - .IIC_Read_Byte = IIC_Read_Byte_t,& \+ g# k$ G/ H! f, X$ y, A5 ^3 [
- .delay_us = delay_us //需自己外部实现delay_us函数- Q" N' O1 d6 w5 `, c% ?
- };
复制代码
J9 F! o/ c3 W 上述就是IIC驱动的封装,由于没有应用场景暂不测试其实用性,待下面ATC64的驱动缝缝扎黄写完之后一起测试使用。 ATC64XX驱动封装实现 at24cxx.h头文件主要是类模板的定义,具体如下: - // 以下是共定义个具体容量存储器的容量
- @3 b' r' {$ y - #define AT24C01 127. [3 N' U+ K/ [. c7 h
- #define AT24C02 255
; f5 t- w# `. n$ g5 j- T - #define AT24C04 511
. u: z7 [4 I* w( H: e" I - #define AT24C08 1023
9 V* m2 T$ j. V. l) H8 g - #define AT24C16 2047
; |8 ?, n I; I+ m* Q* x2 a+ i - #define AT24C32 4095& o/ y: d [& z8 {
- #define AT24C64 8191 //8KBytes
5 i L$ J' h* B$ n. j! E4 o - #define AT24C128 163831 x( `. d8 j# U3 p, t
- #define AT24C256 32767
; `; f, I4 D+ \" x
' r4 ^$ O: M; X2 y' [" L. F- //定义AT24CXX类* @. c2 D+ U3 r" T
- typedef struct AT24CXX_Type7 G; }& } D0 H3 V
- {& w3 C* f, e. r3 G# u" O5 P) r
- //属性- w: \! ~# `- [' e3 W
- u32 EEP_TYPE; //存储器类型(存储器容量): I4 f& B% S" _+ M9 J
- //操作
) g! E- U! n% f0 {3 C& Y - IIC_TypeDef IIC; //IIC驱动9 h- N$ R3 j" W' B9 r
- uint8_t (*AT24CXX_ReadOneByte)(const struct AT24CXX_Type*,uint16_t); //指定地址读取一个字节
# b( ^! j- R, t% V) Y, L - void (*AT24CXX_WriteOneByte)(const struct AT24CXX_Type*,uint16_t,uint8_t); //指定地址写入一个字节
# B9 D: U" @" [, D: r1 N' s3 k3 I$ G3 X - void (*AT24CXX_WriteLenByte)(uint16_t,uint32_t,uint8_t); //指定地址开始写入指定长度的数据
- D) p) l0 ^( G- {+ u - uint32_t (*AT24CXX_ReadLenByte)(uint16_t,uint8_t); //指定地址开始读取指定长度数据% A% T* y1 O' n/ |) O2 f& }6 t7 @
- void (*AT24CXX_Write)(uint16_t,uint8_t *,uint16_t); //指定地址开始写入指定长度的数据
) i6 G" I/ G: K/ E - void (*AT24CXX_Read)(uint16_t,uint8_t *,uint16_t); //指定地址开始写入指定长度的数据) Y0 S0 p, g: x0 r: s+ S, F; b
- void (*AT24CXX_Init)(const struct AT24CXX_Type*); //初始化IIC7 T5 z+ U; c- C5 \+ R, v$ h9 t
- uint8_t (*AT24CXX_Check)(const struct AT24CXX_Type*); //检查器件" P7 s! Z: m3 j9 P3 G9 C/ ^+ h
- }AT24CXX_TypeDef;) G5 ^) m2 V4 y u) c( I) ?
- - r6 a2 S/ [0 G7 B0 N% b$ M
- extern AT24CXX_TypeDef AT24C_64; //外部声明实例化AT24CXX对象
复制代码
; W5 K) D" T# z4 x0 V2 @- i0 m
at24cxx.c源文件主要是类模板具体操作函数的实现,具体如下: - //在AT24CXX指定地址读出一个数据5 o1 t+ t# x0 G$ A9 G+ g0 K; o
- //ReadAddr:开始读数的地址
7 O8 m$ ~. k' V6 ?3 y- X - //返回值 :读到的数据& X& \# i ?) v6 t" A4 E
- static uint8_t AT24CXX_ReadOneByte_t(const struct AT24CXX_Type* AT24CXX_Type_t,uint16_t ReadAddr)
9 U4 m( G& F( y2 o x6 C9 H - { ! D- _# ^# B0 ^5 f* _
- uint8_t temp=0;
& t; c" Y* {7 @ - AT24CXX_Type_t->IIC.IIC_Start(&AT24CXX_Type_t->IIC);
: m, z# W9 l7 D - //根据AT的型号发送不同的地址
7 z$ Z: f' q; F; {0 w - if(AT24CXX_Type_t->EEP_TYPE > AT24C16)
* N. {! y) g: w. K: Y( Y) O7 p - {$ [) f: X0 e9 q( f" g8 }4 |
- AT24CXX_Type_t->IIC.IIC_Send_Byte(&AT24CXX_Type_t->IIC,0XA0); //发送写命令0 U# w- \% D: p2 D$ M4 L: [
- AT24CXX_Type_t->IIC.IIC_Wait_Ack(&AT24CXX_Type_t->IIC);
. f* C; e# H8 T8 t/ B" r/ H% g2 a - AT24CXX_Type_t->IIC.IIC_Send_Byte(&AT24CXX_Type_t->IIC,ReadAddr>>8);//发送高地址
7 K7 d, }$ `+ ^ - }else AT24CXX_Type_t->IIC.IIC_Send_Byte(&AT24CXX_Type_t->IIC,0XA0+((ReadAddr/256)<<1)); //发送器件地址0XA0,写数据
; g+ M# c6 B& `+ l" t4 W3 M - AT24CXX_Type_t->IIC.IIC_Wait_Ack(&AT24CXX_Type_t->IIC);
$ f* }- }+ A+ N# o - AT24CXX_Type_t->IIC.IIC_Send_Byte(&AT24CXX_Type_t->IIC,ReadAddr%256); //发送低地址
6 @( [+ h% n @) R - AT24CXX_Type_t->IIC.IIC_Wait_Ack(&AT24CXX_Type_t->IIC);
" {; F+ [' U0 e - AT24CXX_Type_t->IIC.IIC_Start(&AT24CXX_Type_t->IIC);
! b5 z3 U, n. l% C2 r' L4 ?5 g - AT24CXX_Type_t->IIC.IIC_Send_Byte(&AT24CXX_Type_t->IIC,0XA1); //进入接收模式
( d7 `* d. x4 J6 e/ c - AT24CXX_Type_t->IIC.IIC_Wait_Ack(&AT24CXX_Type_t->IIC); " R7 N* q- q: g2 C$ P# O! f
- temp=AT24CXX_Type_t->IIC.IIC_Read_Byte(&AT24CXX_Type_t->IIC,0);
1 @: P7 X h' O/ k5 [ Z& y/ z - AT24CXX_Type_t->IIC.IIC_Stop(&AT24CXX_Type_t->IIC);//产生一个停止条件
" g* x, E. w+ ~* h" p - return temp;
2 O z1 b& |) h. r) B# Y - }
4 E/ ^& }& E8 y8 F8 o* Q& b - //在AT24CXX指定地址写入一个数据: A* |# W8 B+ S2 G- U1 T
- //WriteAddr :写入数据的目的地址
% N7 q+ x& n7 n! d* \8 G+ w - //DataToWrite:要写入的数据
4 Q( }8 F( X* ?+ h - static void AT24CXX_WriteOneByte_t(const struct AT24CXX_Type* AT24CXX_Type_t,uint16_t WriteAddr,uint8_t DataToWrite)
& l% ]! z* d h' @3 Z- N0 x - { 9 d) d$ i( S# r) _0 F
- AT24CXX_Type_t->IIC.IIC_Start(&AT24CXX_Type_t->IIC);
$ ?3 g: T( @: C* x2 y9 a - if(AT24CXX_Type_t->EEP_TYPE > AT24C16)( r6 D% E4 H# r3 R2 d2 q. |/ h, w
- {; W8 C. x! X# K. B
- AT24CXX_Type_t->IIC.IIC_Send_Byte(&AT24CXX_Type_t->IIC,0XA0); //发送写命令
; S/ O/ h$ u4 B- W* p - AT24CXX_Type_t->IIC.IIC_Wait_Ack(&AT24CXX_Type_t->IIC);
, N" p) F" X& V+ h+ D% M3 O - AT24CXX_Type_t->IIC.IIC_Send_Byte(&AT24CXX_Type_t->IIC,WriteAddr>>8);//发送高地址 9 j6 r3 \# q' b& Z
- }else AT24CXX_Type_t->IIC.IIC_Send_Byte(&AT24CXX_Type_t->IIC,0XA0+((WriteAddr/256)<<1)); //发送器件地址0XA0,写数据
5 ~4 r5 `* y; W1 g/ c$ ~* } - AT24CXX_Type_t->IIC.IIC_Wait_Ack(&AT24CXX_Type_t->IIC); " K/ C3 G+ |- c K6 ^5 _7 Z
- AT24CXX_Type_t->IIC.IIC_Send_Byte(&AT24CXX_Type_t->IIC,WriteAddr%256); //发送低地址8 c3 V ^, b: v2 i, m" f9 _
- AT24CXX_Type_t->IIC.IIC_Wait_Ack(&AT24CXX_Type_t->IIC); % _ ]2 k$ B1 |& Z
- AT24CXX_Type_t->IIC.IIC_Send_Byte(&AT24CXX_Type_t->IIC,DataToWrite); //发送字节 3 ~/ ~! S# p8 Q. r
- AT24CXX_Type_t->IIC.IIC_Wait_Ack(&AT24CXX_Type_t->IIC);
) r, B) ^& g; n; g6 ]' t - AT24CXX_Type_t->IIC.IIC_Stop(&AT24CXX_Type_t->IIC);//产生一个停止条件
; O ?7 x8 E. n2 S- \ - AT24CXX_Type_t->IIC.delay_us(10000);
% |' X5 I" R" } V8 G! ~- K f) K8 M - }) f- `' O' l( U6 o+ \7 q7 k
- //在AT24CXX里面的指定地址开始写入长度为Len的数据# @; F% x: h% K6 Q, X! S: r
- //该函数用于写入16bit或者32bit的数据.6 P$ | ` i1 I2 U
- //WriteAddr :开始写入的地址
, ~* z- l7 ` b3 j8 M- N- S# W* ` - //DataToWrite:数据数组首地址
- Y* E; I# H8 T- ? - //Len :要写入数据的长度2,46 j# |' f; S, e5 i0 a& e% P
- static void AT24CXX_WriteLenByte_t(uint16_t WriteAddr,uint32_t DataToWrite,uint8_t Len)
# i0 ^& @; N: b3 s6 l - { 9 J* R5 q: W) o3 _) ^$ ^! z# l
- uint8_t t;3 H1 p: I' Y( B+ X" t6 x& u! l- e
- for(t=0;t<Len;t++)" Z7 } k0 h) l. g- u& ^
- {" }# |8 j4 j5 d5 l* S
- AT24CXX_WriteOneByte(WriteAddr+t,(DataToWrite>>(8*t))&0xff);
* O, i) X5 y% I% N. F! j" v - }
) W4 q8 X* o; i7 o - }' o6 Y+ {- i0 }* i+ y! [
- //在AT24CXX里面的指定地址开始读出长度为Len的数据
% w/ `% f. O4 F7 Y# \1 E) M - //该函数用于读出16bit或者32bit的数据.
& T' E5 I, U3 k3 v$ I - //ReadAddr :开始读出的地址
* y; D0 Z% T: x8 H# r- G) ?4 | - //返回值 :数据
6 e% D5 F! N i3 W4 Z3 Z - //Len :要读出数据的长度2,45 @% r* s( o E/ s: o
- static uint32_t AT24CXX_ReadLenByte_t(uint16_t ReadAddr,uint8_t Len)
2 x; G% o# ]# D* o6 T# F - {
; |1 r# {* F; a' J7 Q+ H/ [ - uint8_t t;" C. C2 n- Y% @$ G( S) s3 m
- uint32_t temp=0;
2 z6 i2 ^) j k& S7 r6 O8 O - for(t=0;t<Len;t++). R; X( u0 P3 J6 f, k
- {
R! G' S/ e( Y- [' H H1 X; ?3 e, @ - temp<<=8;- Q: a4 V) Z! U% e- t
- temp+=AT24CXX_ReadOneByte(ReadAddr+Len-t-1);
) y. g" ?$ @8 @& [8 i - }
% y0 y/ z, G+ R3 k' p2 `, w - return temp;
: Z: v5 u( h, I5 I; I - }9 ^8 P. F& [9 p* u3 W$ A2 J! `
- //在AT24CXX里面的指定地址开始写入指定个数的数据
; i2 C7 m# W! u @3 S - //WriteAddr :开始写入的地址 对24c64为0~8191
0 U0 t* R+ Y; _4 r1 P - //pBuffer :数据数组首地址
; A, L' C- ~ |( E5 J9 r - //NumToWrite:要写入数据的个数- k+ k" Q1 u' s+ q3 M0 |( `; U2 M
- static void AT24CXX_Write_t(uint16_t WriteAddr,uint8_t *pBuffer,uint16_t NumToWrite)! i6 {( Y* _0 r: Q' @* P# h
- {. r% r$ ^/ z5 m, L& G$ V
- while(NumToWrite--)
2 j, p9 I6 R. Q5 y5 k' T - {. u" W, l7 r% y, G4 `8 I1 c( M
- AT24CXX_WriteOneByte(WriteAddr,*pBuffer);
5 q7 M" c* I+ x, L8 v3 b! d0 a3 i - WriteAddr++;# _% Y! [; E/ I' q
- pBuffer++;& y6 f: I7 c2 k% U |0 x* H
- }
8 o s0 T( B$ s! u* S - }
# t7 V0 b2 {4 c0 ?3 Y - //在AT24CXX里面的指定地址开始读出指定个数的数据% ? I; K0 x% ]
- //ReadAddr :开始读出的地址 对24c64为0~8191
% @3 X& {/ r/ A8 D/ f - //pBuffer :数据数组首地址. b$ x. I/ I3 l( B( n0 `/ u) W8 p
- //NumToRead:要读出数据的个数$ U6 ~4 }+ ~( R5 E5 [
- static void AT24CXX_Read_t(uint16_t ReadAddr,uint8_t *pBuffer,uint16_t NumToRead)9 j w1 r" }( Q+ F% \" l
- {
4 g- K/ R1 ~% b' h' P! z7 o - while(NumToRead)
( Y+ x. U% w( X; [* V( O& m - {8 ^/ Z3 t6 }9 ^$ _+ N
- *pBuffer++=AT24CXX_ReadOneByte(ReadAddr++);
# E3 m; A: \4 S; H5 W - NumToRead--;
+ N6 [ |- I. A. p% \9 Q8 Z, H Z - }
* B7 P6 E1 M3 ^( a - }
6 X" m3 r0 S3 H" v - //初始化IIC接口1 _2 q4 y0 A3 V) q
- static void AT24CXX_Init_t(const struct AT24CXX_Type* AT24CXX_Type_t)) c5 E, L8 H( S+ y2 h+ G$ x
- {) g; K7 O2 T, ^
- AT24CXX_Type_t->IIC.IIC_Init(&AT24CXX_Type_t->IIC);//IIC初始化
4 N) u* \; b! F1 c6 l2 R* `: a - }/ [; d, d# E# A; O9 j0 p E2 t
- //检查器件,返回0表示检测成功,返回1表示检测失败: ?7 R Y" O! o7 G7 @( Z2 u* l
- static uint8_t AT24CXX_Check_t(const struct AT24CXX_Type* AT24CXX_Type_t) " O* U$ y9 S1 j
- {
4 y) H% s, o* d0 f* A. ]* U7 G. ~ - uint8_t temp;5 M! L+ k9 g' f8 ^ `7 M% ^! P
- temp = AT24CXX_Type_t->AT24CXX_ReadOneByte(AT24CXX_Type_t,AT24CXX_Type_t->EEP_TYPE);//避免每次开机都写AT24CXX
. m0 S: y1 r, J0 h7 Z - if(temp == 0X33)return 0; 1 E8 ^ P& @$ ]+ s. W8 A' _
- else//排除第一次初始化的情况
9 \8 T" c, \6 |9 y* p - {
7 {, J! \* f9 X9 R& B4 x - AT24CXX_Type_t->AT24CXX_WriteOneByte(AT24CXX_Type_t,AT24CXX_Type_t->EEP_TYPE,0X33);
3 k3 h, {* { Y/ ~! H5 r - temp = AT24CXX_Type_t->AT24CXX_ReadOneByte(AT24CXX_Type_t,AT24CXX_Type_t->EEP_TYPE);3 c3 Y6 o$ U6 L M( D( B8 s5 y
- if(temp==0X33)return 0;
. [9 d+ i; ]: g% R! ~ - }
3 k4 y# Z- R \& l+ Q; b# e - return 1;
4 a2 b- C0 t. L - } I/ e0 |1 |8 g5 \) Y2 U
- //实例化AT24CXX对象
4 `: m3 s" b" w& v! v- c - AT24CXX_TypeDef AT24C_64={
' m& l' q0 h2 E2 w - .EEP_TYPE = AT24C64, //存储器类型(存储器容量)
3 }% C, V- p0 P; V( N# A" l3 L - //操作
2 ?1 w1 E! ?/ U% x9 ~1 A - .IIC={/ r/ ^# G% b6 h, B; t& p" {) m# y' s
- .GPIOx_SCL = GPIOA,
1 o) V0 ?( Y! X/ Z1 h- f - .GPIOx_SDA = GPIOA,/ ?& R5 F1 M" v' m
- .GPIO_SCL = GPIO_PIN_5, b/ C* J2 c4 w( @
- .GPIO_SDA = GPIO_PIN_6,
j, l3 \/ c$ a1 W" W( l/ L; e8 a9 ^ - .IIC_Init = IIC_Init_t,
; ~- J% Q' R1 ?5 n! `2 k - .IIC_Start = IIC_Start_t,2 F1 ^$ A* {2 A2 w3 Z* R
- .IIC_Stop = IIC_Stop_t,
1 r. g3 x2 ^# S- q; i* ]6 C - .IIC_Wait_Ack = IIC_Wait_Ack_t,
7 H) M8 n& I1 F% b - .IIC_Ack = IIC_Ack_t,- O9 {. Y3 b* ]2 B$ h8 Q4 O
- .IIC_NAck = IIC_NAck_t," H+ f9 |/ t4 l2 d7 g# K
- .IIC_Send_Byte = IIC_Send_Byte_t,' M0 c' S3 x, m2 S, S) t6 J" \1 I
- .IIC_Read_Byte = IIC_Read_Byte_t,8 D* T/ c6 P% t. U9 r( P
- .delay_us = delay_us
; ]6 r3 `( ?- G; Z/ `! ^* e- U - }, //IIC驱动
V6 F* O# V4 B - .AT24CXX_ReadOneByte = AT24CXX_ReadOneByte_t, //指定地址读取一个字节% N; V; r8 b3 v% s" _! M/ F
- .AT24CXX_WriteOneByte = AT24CXX_WriteOneByte_t,//指定地址写入一个字节" m0 g4 X1 y# T" {* P. b
- .AT24CXX_WriteLenByte = AT24CXX_WriteLenByte_t, //指定地址开始写入指定长度的数据, y# ?- i+ C, Z7 V" ]2 q
- .AT24CXX_ReadLenByte = AT24CXX_ReadLenByte_t, //指定地址开始读取指定长度数据7 v/ b0 M* a6 ] r- N% j( {
- .AT24CXX_Write = AT24CXX_Write_t, //指定地址开始写入指定长度的数据3 f7 Y% _! \" `
- .AT24CXX_Read = AT24CXX_Read_t, //指定地址开始读取指定长度的数据$ f3 c3 K5 |+ J, |9 j! J
- .AT24CXX_Init = AT24CXX_Init_t, //初始化IIC
! J+ n! H& L! j. j - .AT24CXX_Check = AT24CXX_Check_t //检查器件
/ |* t1 e. s# i* h- r - };
复制代码5 @: g# v& V( I8 G) ~& R8 Z
简单分析:可以看出AT24CXX类中包含了IIC类的成员对象,这是一种包含关系,因为没有属性上的一致性因此谈不上继承。 之所以将IIC的类对象作为AT24CXX类的成员是因为AT24CXX的实现需要调用IIC的成员方法,IIC相当于AT24CXX更下层的驱动,因此采用包含关系更合适。 因此我们在使用AT24CXX的时候只需要实例化AT24CXX类对象就行了,因为IIC包含在AT24CXX类中间,因此不需要实例化IIC类对象,对外提供了较好的封装接口。下面我们看具体的调用方法。 % i2 P. W& U# X8 W1 @
主函数main调用测试 在main函数中直接使用AT24C_64来完成所有操作,下面结合代码来看: - #include "at24cxx.h" //为了确定AT24C_64的成员方法和引用操作对象AT24C_64# j( q' x+ G- k* R4 j+ j7 Z. o
- int main(void)
2 x! a4 c8 x2 l% g1 ] - {. L4 Z; Q* L& G/ ]7 u# [" f' x
- /************省略其他初始化工作****************/9 A+ _4 M2 q) P6 `3 w# W# p. q0 u
- //第一步:调用对象初始化方法来初始化AT24C64% _ V* k8 `& i
- AT24C_64.AT24CXX_Init(&AT24C_64);" _; J( v8 M" T. ^) v
- //第二步:调用对象检测方法来检测AT24C64
2 U" ^8 d6 W0 f - if(AT24C_64.AT24CXX_Check(&AT24C_64) == 0)
! U! a% g, D1 q1 Q4 k - {, G7 \" l- T/ N5 {+ F7 }
- printf("AT24C64检测成功\r\n");- S- z) l! c, p# x4 E
- }9 i$ W: I2 N! g, @! e% \4 j2 C: \$ M
- else{8 ~4 \' D: ^& y
- printf("AT24C64检测失败\r\n");% r7 E& s+ W) B+ q
- }- H% r5 u1 |( `
- return 0;# G* V' ?$ E/ o5 _) M
- }
复制代码4 `% R3 f; x& B1 w' j- C0 p* W
可以看出所有的操作都是通过AT24C_64对象调用完成的,在我们初始化好AT24C_64对象之后就可以放心大胆的调用其成员方法,这样封装的好处就是一个设备对外只提供一个对象接口,简洁明了。 : o6 {; z3 D. ]8 R: C
总结 本文详细介绍了面向对象方法实现IIC驱动封装以及AT24CXX存储器的封装,最终对外仅提供一个操作对象接口,大大提高了代码的复用性以及封装性。 + N0 r/ g* O$ s3 J$ A
! ]1 s. ]3 F8 K& J R |