|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
——疯壳·开发板系列 I2C教程
$ U, S. q) _7 W1 C7 ]8 t
7 T0 A1 w/ x2 _$ C
% {& \ ?; h; \! K( }4 ^; r+ d6 l& m
; L; q( a( ?1 ]5 |/ K
图12 ~* E8 t3 A) w
+ r* [# `7 ~# N% t- [5 D 第一节I2C硬件电路- Q1 q: [3 g$ g/ W# ^, b
将P12与P13配置为I2C的两个接口即可,P12与P13已通过排针引出,如下图所示:: {' ~1 M* p3 [* j6 @
/ j6 X! R$ l8 T; z( @% N
8 k" D! Y- X( M& `
. `0 x/ e% _/ I/ Z- H' n1 M2 R9 ^5 t- N 图2
. b/ S$ @' O5 V- B& E# }" G4 N# `6 ^5 V' C
\2 [, C+ y, K# \
" k# d/ \ T" i! E- _+ c, f 第二节 I2C1 J; W* o: a: V: f2 \# j, b: t
6 y; @7 i" ]9 L* d9 }' k: T
2.1 I2C介绍- |0 k( i& |4 W3 ~+ { y2 v0 P: z
I2C总线是一个为系统中电路通信提供支持的可编程控制总线,它是一个软件定义的两线通信协议。- Y: @% e' `+ U9 D) C: {3 t
两线I2C串行接口包括一个串行数据线(SDA)和一个串行时钟线(SCL);% }* T. J7 Q( W# k
支持两种通信速率,标准模式(0~100Kb/s)和快速模式(小于等于400Kb/s);" o [- J# I8 _. k% v$ B
时钟同步;, j" p4 y7 w5 o
32字节的发送接收FIFO;
. q0 I$ R: `% S; Y5 I; @ 主机发送与接收操作;
1 z2 m) ~2 Z; c6 A6 y# N8 M 7或10位地址,7或10为混合格式发送;
2 O/ `: I( b% ] 块发送模式;
# o F5 c4 D: O. f3 r 默认从地址为0x055;
D: w; u& D' U+ n1 d 中断或者轮询操作模式;; m3 W1 B! |5 w {$ o6 y% v( k7 A
可编程的数据线保持时间;8 F: \% v! l, X) ~- n
$ n8 h. A/ |9 j( r( S, w4 L3 n" v
2.2 寄存器介绍
1 e. Q( b4 }7 e- X I2C相关的寄存器比较多,所以我们只介绍常用的寄存器,其它的可以参考官方数据手册AD14580_DS_v3.1.pdf,位于目录:..\WT开发板\硬件资料。
' N, s- w) n) d% s
" f4 c4 N- f0 @# p! E. e 2.2.1 I2C控制寄存器
8 v2 @: ]2 I* G# u6 t/ h9 w) E& F G
# {1 C" @. a6 {6 r* _! F/ f c
图32 y5 M' c8 X- F
15:7位:保留不使用;
3 Q/ e6 z4 D9 |9 O* b b9 _( L 6位:I2C从设备使能位,’0’表示从设备使能,’1’表示从设备不可用,该位不一定要软件设置,但是要保证如果该位为’0’则该寄存器的第0位也为’0’;" \4 y' |0 {5 s. W; n) b
5位:当作为主设备时,是否发送重启条件,’0’表示不可以,’1’表示可以;
/ d& n: l+ J. u+ Z: X2 J$ C 4位:作为主设备时,决定以7位地址还是10位地址开始发送,’0’表示7位地址,’1’表示10位地址;; L) i7 b# v1 z& @7 r. _0 Y
3位:作为从设备时,决定以7位地址还是10位地址开始发送,’0’表示7位地址,’1’表示10位地址;' ?. R0 d0 _6 J) ?$ g6 w. d
2:1位:I2C通信速度选择,1表示标准速度(100Kbit/s),2表示快速(400Kbit/s);
# [& N# a3 Q: M5 p& F. y! b 0位:I2C主设备使能,’0’表示主设备不可用,’1’表示主设备使能,要保证如果该位为’1’则该寄存器的第6位也为’1’;
. K. \+ u' {( Z# x' g; C. \' P4 s: i% t8 g
2.2.2 I2C目标地址寄存器
, \& N. F" u7 Y8 H% J4 b; H; }+ {# p0 W! a, ], {7 ?) M
8 t: v4 u" Z# ^) Z$ A6 }* T; B
& \7 X, Y$ X8 O: L 图4. c4 X8 n) J9 E* d4 D/ M( p, R
15:12位:保留不使用;# Y4 b. Q' O, P! C! h5 z
11位:该位决定软件是否进行广播或者开始字节命令,’0’表示忽略第10位GC_OR_START并且正常使用IC_TAR;
9 v8 p9 s% c1 s3 Z4 d5 P! P4 ~ 10位:如果第11位设置为’1’,则该位表示控制器是否进行广播或开始字节命令,’0’表示发送广播地址,之后只能进行写操作,如果进行读操作则导致TX_ABRT置位,控制器一直停留在广播模式,直到第11位被清除,’1’表示发送开始字节;
: v* E0 J# A" ]( |# v6 J" q" \- M4 J 9:0位:这是主设备发送的目标地址,如果发送广播则该位被忽略,CPU只需要写一次这些位;注意如果目标地址与从设备地址相同则存在回路,但是FIFO为主从共用,所以完全回路是可行的,只支持单方向的回路,一个主设备不能给自己发送数据只能发送给从设备。* @, v2 b$ i2 \5 T8 R
' S9 x( {# G9 L
2.2.3 I2C接收发送数据缓存与命令寄存器6 O1 v" q9 o! @% A' A% _
1 |( j2 m* M5 G6 E# g" c: t; P% G2 F
& v+ c& @$ r' i5 V: O0 }: R7 S
8 [' v; I8 s9 y" u 图5" {( F/ @ N% b! t. u
15:9位:保留不使用;! v1 e* u. @0 x, h( Q
8位:读写控制位,作为从设备时不能控制方向,只能作为主设备时使用,’0’表示写,’1’表示读;
2 v1 ^) R' u4 K; g$ q 7:0位:存储I2C总线上发送或接收的数据,如果你正在操作该寄存器并且要进行读操作则该位被忽略,如果你读该寄存器则该位存储的是接收到的数据。' c3 ?: K0 O5 y$ D9 |) d8 a
9 \6 U* J' ?5 T8 k' i" ^2 l( R 2.2.4 I2C清除TX_ABRT中断3 g: t+ j. d$ e% T5 @9 {
- G* J+ @5 [0 J8 f$ s% K, D
( n9 t& y: ~# v2 j+ `0 k B. w' M0 J( U 图60 G4 m" s0 ^9 ?! R! W2 l
15:1位:保留不使用;* B, l* }6 Y/ ?% G2 V% J0 V2 w2 z) o
0位:清除发送异常停止位,读该位则清除发送异常停止中断位,和发送异常停止源寄存器位。同时发送FIFO从刷新/复位状态中释放出来,可以允许更多写入。! Q9 o8 C- l/ q* L) s/ A1 `
0 s" y$ u4 y$ f0 \% C
2.2.5 I2C使能寄存器
5 }+ }% W) ?' |
/ M3 U6 T+ M& B, j
- K% P7 V! I/ f9 @
& d9 V6 I' m9 l* l2 B- g+ k+ @" Y
图7
{# M7 n( l$ F( n$ C/ P0 ] 15:1位:保留不使用;
! i, w- i: _" I7 q5 `& }5 U' z 0位:控制器使能位;$ M& E7 q: r' ?) Q. {2 f
' w7 _( o7 D. V; t
2.2.6 I2C状态寄存器
9 V4 w* @, @7 a w+ {, f. B* _* j. G" ^ j8 {
1 H' C9 X7 i, H. _- P" J
: c0 M: j) Z+ U) O9 R) q4 b 图82 a5 p% Q$ q0 I" i( I; s
15:7位:保留不使用;
: }# ?2 {+ U1 H% H0 @2 L 6位:判断从设备是否活动;
9 ?: Q4 Q- u7 p s 5位:判断主设备是否活动;- v( r$ M- N0 a u0 W
4位:判断接收FIFO是否全满;& }& k' L v/ m' `, v. _" j$ H
3位:判断接收FIFO是否为空;$ a" w M- Z6 X2 x0 ~( A8 a
2位:判断发送FIFO是否全满;
. d S2 _) f7 D# @/ C& m 1位:判断发送FIFO是否为空;% Q7 R2 l8 N- ~; u. X9 j
0位:判断I2C模块是否活动。( a$ c' B6 B6 ^8 Z# \# }: U
' c2 p4 |" r- I* ^9 ?( m+ @
2.2.7 I2C接收FIFO数目寄存器9 O' c" r# E* M1 ]! V1 a; k. f; m
8 }7 h( t Y2 B; P+ F
; a6 s& f7 e. x: n4 j# \
图9
9 ]# e$ O) X% V( \0 x$ j { 15:6位:保留不使用;
- S, d8 R: Z; O( N 5:0位:接收FIFO可以接收多少字节。' h9 T0 o R; m% d/ l* `/ |' I
4 u+ P S5 p: [6 F% a* T. ~) ~. k 2.2.8 I2C发送异常终止源寄存器2 v# v+ V; x$ L1 z/ K1 p! }
$ L, T( o2 `' W6 a
: s2 [/ E9 `8 `" I' F6 w
& F* X0 u- {* E v) J0 U; y 图10
8 Z) D" E! M. q& \% m. F+ x 15位:当主设备需要发送数据时,却进入读数据状态;( a- z2 @& m! K7 }+ L6 x
14位:当发送数据时,从设备丢失总线;
( U g/ C7 ?/ E5 B 13位:当从设备要接收数据时,FIFO中已经有一些数据; j% \' i: w4 |+ X7 F
12位:失去仲裁;) X3 ^; n3 H2 Y8 }/ E" j) d
11位:当主设备不可用时,用户进行主设备的操作;. g1 a8 t" S a8 n. z$ @' T% T
10位:重启不可用,并且主设备在10位地址模式下发送读命令;
8 ~+ G4 Q, `% e, @ 9位:重启不可用,但是用户发送一个开始字节;
1 ~+ r- O6 f* A# h0 w6 ]# `( r: } 8位:重启不可用,但是用户试图在高速模式下发送数据;* x8 X3 C! u' c
7位:主设备已经发送了一个开始字节,并且开始字节被确认;( C; U# F5 D8 q$ w
6位:主设备在高速模式下,并且被确认;/ g& ~: s4 z. F. M
5位:主设备控制器广播之后进行读操作;1 ]/ ]8 k" `7 ^' I
4位:主设备发送广播,但是没有从设备确认;' r1 n% f E& q6 d. \7 h- m: O5 N
3位:只有主设备有效,主设备已经发送地址,并确认,但是发送数据得不到确认信号;
, k( L& T8 w7 i$ G) S 2位:主设备使用10位地址模式,10位地址的第二个字节没有被任何从设备确认;
2 t) [# m; G$ m/ I 1位:主设备使用10位地址模式,10位地址的第一个字节没有被任何从设备确认;
1 V. ^! z Y- `3 i6 `, ? 0位:主设备使用7位地址模式,但是没有被任何从设备确认。/ u; r' n4 s+ J* \) F, z9 z/ e
( q0 j) Z: S, B6 U) _4 h' r9 o1 c
2.3 寄存器配置讲解7 O, e0 [1 T: b
: u0 h5 W8 g$ \: N #define CLK_PER_REG (* ( volatile uint16*)0x50000004)
' Y+ [- T) q/ V& x1 [ #define I2C_CON_REG (* ( volatile uint16*)0x50001300)
" V u6 Y" X* u Z' R2 E8 q+ I5 x #define I2C_TAR_REG (* ( volatile uint16*)0x50001304)
' q0 ]) @. h9 N. e9 E! b #define I2C_DATA_CMD_REG (* ( volatile uint16*)0x50001310)/ B: G; Z0 ?1 _, k& g
#define I2C_CLR_TX_ABRT_REG (* ( volatile uint16*)0x50001354)
W3 {( H% P! m- R+ ~0 u; _5 h2 ^ #define I2C_ENABLE_REG (* ( volatile uint16*)0x5000136C)
6 U0 c( M$ ~, @0 E2 X6 M% I% R #define I2C_STATUS_REG (* ( volatile uint16*)0x50001370)
0 G; c: A& _( ~3 g2 T #define I2C_RXFLR_REG (* ( volatile uint16*)0x50001378)
1 W% C# j6 M# ~ #define I2C_TX_ABRT_SOURCE_REG (* ( volatile uint16*)0x50001380)6 T1 V7 w! W- {- m3 `7 |/ @
启动I2C模块的时钟:CLK_PER_REG |= 0x0020;
! e# f' e& \ r I2C的初始化寄存器配置:5 R: x" V' ]8 {1 g
先关闭I2C控制器, I2C_ENABLE_REG=0x00;# u/ t0 [+ ~: H" _ _/ R1 [1 S
设置为主模式,关闭从模式,可以重复开始,速度设置为快速,地址为7位模式(0x0000000001100101), I2C_ CON _REG =0x0065;. o' U j2 ?5 d
设置目标设备地址为0x51, I2C_TAR_REG =0x51;8 X1 k( _6 ^( J$ ?
打开I2C控制器, I2C_ENABLE_REG=0x01;8 @+ w1 Z3 |: b4 y- s
等待控制器准备好,while( (I2C_STATUS_REG & 0x20) != 0 );& b& ]: ~7 q9 \" [/ A- g
读取地址为0x98处的一个字节,先发送地址I2C_DATA_CMD_REG = 0x98;等待发送完毕while((I2C_STATUS_REG&0x0002)==0);发送读指令I2C_DATA_CMD_REG = 0x0100; 等待发送完毕while((I2C_STATUS_REG&0x0004)==0);之后等待数据接收完毕while(I2C_RXFLR_REG == 0);读取接收缓冲区的数据即为接收数据rx_data = I2C_DATA_CMD_REG;, v# s& H; h+ A }
向地址为0x98处写入一个字节0xaa,先发送地址I2C_DATA_CMD_REG = 0x98;等待发送完毕while((I2C_STATUS_REG&0x0002)==0);发送数据I2C_DATA_CMD_REG = 0xaa; 等待发送完毕while((I2C_STATUS_REG&0x0004)==0);
) \1 f4 r3 e4 s3 c' a, J- ~+ k+ e$ d( B6 z& n% K# Y
* l, z( F: Y+ A7 a/ _! T- B2 u) ?+ e l9 W U8 R( ^7 l
: E, a5 E+ {5 R& V' V9 K$ n! A3 S 第三节 I2C实验) N0 R$ Y' p) J8 u$ s7 Z- v
$ M- W, o) g& v% U9 P5 p5 ]" g
实验需要使用的模块有:手机开发板底板,Jlink调试工具,杜邦线、心率体温模块、3.7V锂电池或Mocro USB线。1 ]# a; c1 D \/ X3 d0 R
将心率体温模块通过杜邦线连接到主控底板上,连接方式如下:
; V5 R( W8 {+ P6 V' p% q: h (1)心率体温模块一端主需要使用杜邦线连接心率体温模块的3V3、GND、SCL、SDA四个引脚,如下图所示:
5 H6 r5 d! ^0 J/ x6 T3 O0 m8 e0 G
9 {" z: M1 w M* t
" S2 v1 G8 Q& A2 ?' y
图115 f: p& e- o$ R5 i3 ]
(2)手机主控板一端需要使用杜邦线连接J4的2个引脚以及J10的两个引脚与心率体温模块的引脚一一对应,如下图所示
9 J7 V+ g0 b) H9 M! j
/ m, ^# @9 y# J" D) K: U
. v; Z5 w3 h2 Y; k7 U4 t! z6 U
; b. I+ Q- D x9 W# ]! g3 x/ \3 G
+ D7 p0 J7 H# E2 P* S 图12
8 b3 @9 b& v' I- { 使用JLINK通过杜邦线连接手机蓝牙位于手机主控底板,连接方式如下:
% g+ B1 l/ f+ }% v! t/ V (1)JLINK一端只需要使用杜邦线连接JLINK的SWC、SWD、GND三个引脚,如下图所示:
9 r7 ?1 |5 t0 T0 n- O- w4 h
* ^" Y7 C; S2 n, L V2 f
+ N2 ?( O1 ?+ i" r% L
图13( R' P* X- V' s0 s# {: P* h
(2)手机蓝牙一端需要使用杜邦线连接上方右侧的J3三个引脚,与JLINK的连接引脚一一对应,分别为SWC-->SWCLK、SWD-->SWDIO、GND-->GND,如下图所示:
* h) Z/ m8 ? x, m7 E7 D, O
6 e- n+ c9 V" A" y; z* J* a
2 X0 ]- D! v3 @5 e) O( n 图14
1 {8 A$ G, `" |8 C+ h7 e+ P' z 将JLINK插上电脑的USB接口,连接好之后给手机主控底板供电,详细的介绍可以参考《如何上电》教程,路径为:..\WT_Mobile\0.从这里开始\0.开机测试。- S1 S' n! F6 J' W- h
打开I2C实验的Keil工程i2c_eeprom.uvproj,位于目录:/ y( h5 }! P8 n
..\WT_Mobile\1.初级教程\DA14580\5_初级_I2C\projects\target_apps\peripheral_examples\i2c\i2c_eeprom\Keil_5,如下图所示:
- I* k; M' ^7 o- Z# _5 H' u
7 @3 U D; c. |3 K( w
" K( j' t7 Z P! |& R2 k 图15
6 V! h4 h4 ~! X% h8 f 在KEIL中编译源代码,点击DEBUG,然后点击全速运行,在存储温度数据的变量下方打上断点,当程序运行到断点时就会停止。将该变量添加进变量查看窗口中,可以看到温度值,如下图所示:
1 c) R5 c% p( \; O& G- r
5 Q/ e2 j' A) T1 i
0 @% c, }7 j$ I: ~8 P/ H2 A$ T
4 c. J2 o4 _" A" G; Q3 d+ L) p
+ G$ [( U* U5 J6 _$ \
: N+ v8 Z' M$ }; R" D
" o9 `# a0 x: B8 Z9 H, J
6 Y$ ~0 x% R( T& F9 K1 U4 U. a5 z
) R8 V' k; i) _3 ?
图16! Q& y) U( ?0 n4 E- P8 E
$ w' h" n+ k) e# N$ x: E' l
% U0 z& k1 S8 N/ [4 I" @
0 A$ `2 [8 z# i- Y( c1 _+ v/ [3 I: j4 q N2 e
文件下载请点击:
I2C教程.pdf
(1.53 MB, 下载次数: 0)
! n1 N) Q3 ]- o* F* c7 C0 j
- e$ o* q, T& x& _
& M2 N0 _8 N' ^. f5 O# I5 Z: U
0 O- e- f9 G+ A* Q/ J |
|