|
|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
I2C教程 ——疯壳·开发板系列
/ m# J. s4 P/ O- h: ~' K
$ @5 k* k" Q9 H2 }
5 Z+ f1 O% i# ?6 _0 M: _
7 i& `* A& \ l' g2 R
图1
6 s- ?8 ?& l6 A; r! T: V" q$ _' [' ]1 i
第一节I2C硬件电路6 L& }4 D8 H. Z- Q8 |$ b: t5 J
将P12与P13配置为I2C的两个接口即可,P12与P13已通过排针引出,如下图所示:8 g8 O. ~* S8 e7 s* M) m
u) f% T8 o' p! \; g' o) |7 E
+ n4 m, }) [; m; m* [
: q/ L7 d" D" w) Z
图2
9 d5 V. E* ?4 l5 l v# M# v& \+ m3 @* H- [+ ]' ]
" P. I3 C% ^4 `
) _' U- {# Q! |2 Y+ R& L 第二节 I2C2 Y' A& M2 C8 V. ?. H- b- B
* V" d u+ t) [2 T, f; X
2.1 I2C介绍7 a( C9 ]- f( B( E
I2C总线是一个为系统中电路通信提供支持的可编程控制总线,它是一个软件定义的两线通信协议。
6 Y% h, c2 Q2 V- X4 L, { 两线I2C串行接口包括一个串行数据线(SDA)和一个串行时钟线(SCL);3 \) e, z- J- W, S) W" Y% B
支持两种通信速率,标准模式(0~100Kb/s)和快速模式(小于等于400Kb/s);
, W- L8 b0 @8 \7 ?8 `5 g7 e+ ~ 时钟同步;
1 D. R' t3 Q+ G2 Q 32字节的发送接收FIFO;
4 c5 Q5 b7 K3 K5 c5 D. T* ? 主机发送与接收操作;
! f7 `; s9 y; g; a5 X/ P 7或10位地址,7或10为混合格式发送;. Q* y4 A& X% x: o: T% U) y; j2 f) ]
块发送模式;2 E3 h3 ~* c; L" D# w K
默认从地址为0x055;7 g _+ B/ I# f8 H$ ?* U% C/ C
中断或者轮询操作模式;
0 s! Z; S8 K" G) o3 ] 可编程的数据线保持时间;
7 Y5 U9 D) f/ t I; v
0 q: o& n- n2 ^" f, P* d1 Q6 P- ^ e 2.2 寄存器介绍
1 h7 v$ y d- C! g8 @1 x I2C相关的寄存器比较多,所以我们只介绍常用的寄存器,其它的可以参考官方数据手册AD14580_DS_v3.1.pdf,位于目录:..\WT开发板\硬件资料。. G: r ~. G/ l
5 X7 G% E; k$ X$ m, v3 n 2.2.1 I2C控制寄存器: \- B1 a; y3 Q, D
; Y3 n6 K8 }( _5 f
' H" S1 m! p' I3 G* Y4 B 图3( n, d( R8 \0 p" n1 r8 U
15:7位:保留不使用;% [' F* _6 Y( E- O4 [& o+ U
6位:I2C从设备使能位,’0’表示从设备使能,’1’表示从设备不可用,该位不一定要软件设置,但是要保证如果该位为’0’则该寄存器的第0位也为’0’;
$ `/ }" |5 Q* q" G" H 5位:当作为主设备时,是否发送重启条件,’0’表示不可以,’1’表示可以;
1 Z& L- H: O. `& {; s7 q8 z; @ 4位:作为主设备时,决定以7位地址还是10位地址开始发送,’0’表示7位地址,’1’表示10位地址;
6 e- T3 ]# {. X( Z2 D3 G6 t* ` 3位:作为从设备时,决定以7位地址还是10位地址开始发送,’0’表示7位地址,’1’表示10位地址;
% Q/ R6 Y) g4 K 2:1位:I2C通信速度选择,1表示标准速度(100Kbit/s),2表示快速(400Kbit/s);% |$ H: A4 i6 I' N2 a1 w/ w, j
0位:I2C主设备使能,’0’表示主设备不可用,’1’表示主设备使能,要保证如果该位为’1’则该寄存器的第6位也为’1’;
' J1 {+ s- R0 z; |
( Y) K: j: ?5 Q) _ 2.2.2 I2C目标地址寄存器% T' C' L7 m7 ^7 l0 I! @
1 v u7 f- Y! F) ?' V: w. w& e9 x
, T( H1 I D7 A. b: S
8 p, d% R( G7 y: d$ I9 L9 F
图4/ h" p7 f- F6 K. X; r
15:12位:保留不使用;5 R5 [$ x- V' \
11位:该位决定软件是否进行广播或者开始字节命令,’0’表示忽略第10位GC_OR_START并且正常使用IC_TAR;& r$ @; _1 p+ e! y$ P
10位:如果第11位设置为’1’,则该位表示控制器是否进行广播或开始字节命令,’0’表示发送广播地址,之后只能进行写操作,如果进行读操作则导致TX_ABRT置位,控制器一直停留在广播模式,直到第11位被清除,’1’表示发送开始字节;/ q, }3 A0 N, _2 H0 \+ t6 H! o
9:0位:这是主设备发送的目标地址,如果发送广播则该位被忽略,CPU只需要写一次这些位;注意如果目标地址与从设备地址相同则存在回路,但是FIFO为主从共用,所以完全回路是可行的,只支持单方向的回路,一个主设备不能给自己发送数据只能发送给从设备。
3 N7 J2 H4 C! i) G! S9 b) ^, j4 w5 ~; f- H( ~
2.2.3 I2C接收发送数据缓存与命令寄存器3 q. h+ X x- ~
: d9 k( K# }/ d4 d5 H: D" G
: c }+ N: g$ w1 v( p5 z& G
! y/ A8 a6 W8 r( n
图5
1 N. {. J" C. r1 @: f 15:9位:保留不使用;
2 Q3 [( f1 B+ F8 L7 ^ 8位:读写控制位,作为从设备时不能控制方向,只能作为主设备时使用,’0’表示写,’1’表示读;
- _5 y( ]9 l0 N% U0 p 7:0位:存储I2C总线上发送或接收的数据,如果你正在操作该寄存器并且要进行读操作则该位被忽略,如果你读该寄存器则该位存储的是接收到的数据。4 ]5 O/ l2 l! r# b5 F7 N5 c
% {' [6 p, w6 q0 P' i 2.2.4 I2C清除TX_ABRT中断7 m% o* H" T% c0 T
$ q- a& t; p4 I, _. W$ `; n
3 t0 r* @. M5 Z* g" [' Y$ _1 y
图61 q! e( k- @! J n7 Q
15:1位:保留不使用;! \7 E& e/ t& `6 `, ~3 K
0位:清除发送异常停止位,读该位则清除发送异常停止中断位,和发送异常停止源寄存器位。同时发送FIFO从刷新/复位状态中释放出来,可以允许更多写入。
, M. J2 L" |/ H& \8 ^9 h7 D8 B2 k. L* k1 I/ Z" C% R
2.2.5 I2C使能寄存器
+ i9 O& |) ^ Q1 Z3 v
6 F5 V8 s7 n! u2 E+ C' q ^
. S6 O9 q' O& _/ E$ f- \ u. C
3 J2 G% O" L6 F+ j 图7
3 w8 E6 p: m- D$ r- s 15:1位:保留不使用;' c( i% ]0 k Z0 c* ?' V- V
0位:控制器使能位;! X; f0 ]1 r# t3 G' @- R6 m0 n" Y
1 F/ X/ R# Y* g) H
2.2.6 I2C状态寄存器
" b4 ^( {) F& q+ _' g0 h
7 T2 Q0 B$ L" X1 r+ _
# h+ T$ D+ P# V3 Y# h+ ^$ `
- ^1 \; X* M( [+ i! ~" }# C# J
图8
^ ]. z& F! O) o 15:7位:保留不使用;
: h( o/ y* h: j) [6 O& \! w7 i 6位:判断从设备是否活动;
( j6 g. G0 s! A& S# k* G; G% { 5位:判断主设备是否活动;
+ s2 r, q9 u; `/ i/ p 4位:判断接收FIFO是否全满;' w: n2 Q- g) N# A
3位:判断接收FIFO是否为空;, I+ |& B; H# D E# d# t v
2位:判断发送FIFO是否全满;* l$ B; \2 o8 Q
1位:判断发送FIFO是否为空;
. g, _$ Z$ I' o 0位:判断I2C模块是否活动。' }, k$ S; C3 @3 _) z) P# L
3 V! ], ^: u% R# I% S$ | 2.2.7 I2C接收FIFO数目寄存器
' G5 }; h/ p5 k N5 C0 E' J8 a3 ~, U+ J/ c4 p j1 h) s8 O% C! s; `
5 s/ N9 E/ b6 j; F# ~
图9
1 N" o+ m; F {2 T3 X2 s+ K 15:6位:保留不使用;6 f& Z0 Q0 u; e! h; A4 Q
5:0位:接收FIFO可以接收多少字节。 z0 K4 j. ]7 f! G" ~
v. ~1 w. G( G3 T' f% f7 D. `. | 2.2.8 I2C发送异常终止源寄存器7 c6 @, F# h: ~9 t T
9 w, b# ~3 ~* \4 N9 }) E, x1 @
4 I0 q& _$ I9 k# a' L- Z# d
4 |- _" \) x+ C* s3 ], n 图10
+ e" i6 M6 i' b. a# Z4 |4 j: b 15位:当主设备需要发送数据时,却进入读数据状态;; C& h2 C Y7 z* b( W) c
14位:当发送数据时,从设备丢失总线;
6 [' J2 d- ^, s% K6 W 13位:当从设备要接收数据时,FIFO中已经有一些数据;8 u+ X# N/ c+ B, o; [3 K
12位:失去仲裁;
$ d/ E- P. m( R3 L8 E* B, a 11位:当主设备不可用时,用户进行主设备的操作;) y( k& S. ~$ T% D# Y
10位:重启不可用,并且主设备在10位地址模式下发送读命令;
. f. q6 o4 f8 R; L 9位:重启不可用,但是用户发送一个开始字节;+ F+ Z6 w! k- s- X E( s
8位:重启不可用,但是用户试图在高速模式下发送数据;
! y* N9 b) l8 P. l' h 7位:主设备已经发送了一个开始字节,并且开始字节被确认;
4 b5 A1 B5 D" A( ` 6位:主设备在高速模式下,并且被确认;9 l2 J! _9 n$ V9 q4 i
5位:主设备控制器广播之后进行读操作;. p" a1 y$ P% H! X
4位:主设备发送广播,但是没有从设备确认;) x+ S0 G9 A& ~1 [5 }! u
3位:只有主设备有效,主设备已经发送地址,并确认,但是发送数据得不到确认信号;
/ J! W3 A! s$ S q) h: n 2位:主设备使用10位地址模式,10位地址的第二个字节没有被任何从设备确认;+ E' p1 o. g% I: R# c& P
1位:主设备使用10位地址模式,10位地址的第一个字节没有被任何从设备确认;
9 a8 V9 g3 w& v( o 0位:主设备使用7位地址模式,但是没有被任何从设备确认。
, ?, k6 H0 B& M Q7 L2 V/ u2 X
& J' c6 h" u# U; W1 a% W/ r- U# c 2.3 寄存器配置讲解! }; s! g% \: T8 |5 |
5 _; n( M" j7 r. H9 x; U& I5 p
#define CLK_PER_REG (* ( volatile uint16*)0x50000004), K0 z, V' S8 S! w' }9 T5 K- R; N& y
#define I2C_CON_REG (* ( volatile uint16*)0x50001300)
) i' l9 C" i: q. A1 D: j) J* I `# I #define I2C_TAR_REG (* ( volatile uint16*)0x50001304)
" J1 X2 [' v8 E4 a | #define I2C_DATA_CMD_REG (* ( volatile uint16*)0x50001310)
3 |: y: G) z6 L/ w #define I2C_CLR_TX_ABRT_REG (* ( volatile uint16*)0x50001354)3 F F0 L% g" X7 U; e
#define I2C_ENABLE_REG (* ( volatile uint16*)0x5000136C): A$ L5 D4 ?, p
#define I2C_STATUS_REG (* ( volatile uint16*)0x50001370). }) m/ G3 r0 q! D8 }) O' ]
#define I2C_RXFLR_REG (* ( volatile uint16*)0x50001378)
' h! e( e* D6 l& q' a #define I2C_TX_ABRT_SOURCE_REG (* ( volatile uint16*)0x50001380)5 x! Z) v. b4 o0 f
启动I2C模块的时钟:CLK_PER_REG |= 0x0020;
9 [9 F3 T# w/ A) M( a& E$ p I2C的初始化寄存器配置:8 z# j+ Z. e% J( n2 o3 j3 |
先关闭I2C控制器, I2C_ENABLE_REG=0x00;8 }5 K6 C- V5 G: C1 k: |! B& L
设置为主模式,关闭从模式,可以重复开始,速度设置为快速,地址为7位模式(0x0000000001100101), I2C_ CON _REG =0x0065;
9 E+ j% w5 @0 I' Q; b 设置目标设备地址为0x51, I2C_TAR_REG =0x51; ]1 d0 X8 G. n! ^+ X: M
打开I2C控制器, I2C_ENABLE_REG=0x01;( B5 o& T) z2 g- u
等待控制器准备好,while( (I2C_STATUS_REG & 0x20) != 0 );/ W6 Q. [- R; J0 J6 O% L
读取地址为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;
, ^- P* ^( R/ \ 向地址为0x98处写入一个字节0xaa,先发送地址I2C_DATA_CMD_REG = 0x98;等待发送完毕while((I2C_STATUS_REG&0x0002)==0);发送数据I2C_DATA_CMD_REG = 0xaa; 等待发送完毕while((I2C_STATUS_REG&0x0004)==0);
' [6 Y2 K& r9 p# @( z
! G+ Y$ P; B* v( d. m
9 I5 p7 v9 o3 B9 L1 L% A
/ \/ f( {8 C6 P0 K
6 @) ?) B+ M# S7 B g6 P 第三节 I2C实验
) m# C' V) t! |9 u" ?9 P
0 e4 m6 g& h# ]! W 实验需要使用的模块有:手机开发板底板,Jlink调试工具,杜邦线、心率体温模块、3.7V锂电池或Mocro USB线。
6 j, F4 \0 N4 Z2 B1 h$ X( z 将心率体温模块通过杜邦线连接到主控底板上,连接方式如下:
, H9 e/ V* z0 Q6 _6 C (1)心率体温模块一端主需要使用杜邦线连接心率体温模块的3V3、GND、SCL、SDA四个引脚,如下图所示:" _0 i( A$ I( F- \2 d8 L' J/ r C; T
6 ]+ `; w' A1 X- q E" p8 G
: u6 L W+ A$ Z: l) Y7 R
图113 T" \, ]& s- E. y. v" w
(2)手机主控板一端需要使用杜邦线连接J4的2个引脚以及J10的两个引脚与心率体温模块的引脚一一对应,如下图所示
Y2 N2 f: v$ g j* W/ F
. [5 w0 ~4 b& C i4 B
4 G0 F- @7 t# A' V' t( J0 U
7 t3 x ]3 q4 H! {. ?2 I
* P2 r! _# L. ~; L0 o ^ 图12
- M9 ]* `! v! K, H 使用JLINK通过杜邦线连接手机蓝牙位于手机主控底板,连接方式如下:
/ W$ `' z q! d' S; w! g% K (1)JLINK一端只需要使用杜邦线连接JLINK的SWC、SWD、GND三个引脚,如下图所示:
8 r7 P3 k" J2 c2 C
/ ]+ l7 M5 Z2 D4 _9 E
6 H, {7 `7 `9 h# A9 q$ S
图13% `7 |$ e4 r% Z3 O5 \, }- x
(2)手机蓝牙一端需要使用杜邦线连接上方右侧的J3三个引脚,与JLINK的连接引脚一一对应,分别为SWC-->SWCLK、SWD-->SWDIO、GND-->GND,如下图所示:/ m) M, m6 `, b
/ F8 T! {: v9 }9 d+ b; V. }
' J+ ? f' K. q
图14
, J+ ^' w( E F3 E, {7 x; O6 D: ^ 将JLINK插上电脑的USB接口,连接好之后给手机主控底板供电,详细的介绍可以参考《如何上电》教程,路径为:..\WT_Mobile\0.从这里开始\0.开机测试。
$ a5 n4 G3 y! V+ o0 d5 ~$ q 打开I2C实验的Keil工程i2c_eeprom.uvproj,位于目录:7 U$ r4 t& A0 D) H, X& _& l9 D
..\WT_Mobile\1.初级教程\DA14580\5_初级_I2C\projects\target_apps\peripheral_examples\i2c\i2c_eeprom\Keil_5,如下图所示:2 {$ Q8 {% @# m' U# L5 \, j
; f6 m p2 O: ~# Z
8 |! Z6 F: E, N' o2 \
图15
& S; p# n- ]* z9 _/ D3 v 在KEIL中编译源代码,点击DEBUG,然后点击全速运行,在存储温度数据的变量下方打上断点,当程序运行到断点时就会停止。将该变量添加进变量查看窗口中,可以看到温度值,如下图所示:
, h0 ]5 f2 ^. H0 l6 p' b4 t" E$ H$ d' `
7 W" c* d r4 ]8 v- D6 X
5 P0 e9 I# ^5 i" |
4 ~2 N; @5 x9 F+ c1 `
- e! z$ \/ _1 W
- Q7 J) R9 w3 i+ N5 w5 D, B9 x8 r
& D) Y2 W- J+ y7 A
1 P# p! D8 j: ]8 F" b' S) d 图16
1 k) `( \3 j. K r: |& _
* J+ x4 f) c6 e* i1 |) k- u
% O; K! b5 D# U; m, b% x1 v. w. e
+ X, G# s/ m& ` 配套资料:http://www.fengke.club
- k0 K7 {( e& k 套件地址:http://shop115904315.taobao.com/2 E6 \4 m; A: f
文件下载请点击:
I2C教程.pdf
(1.53 MB, 下载次数: 0)
9 f- [$ ]) ?6 b) K' t( K
4 G: @/ {: s6 P5 T! p# S8 m1 m! N) ~
, M+ Z5 V; x& b% Y2 p: @; U. K2 ~9 ~4 o( \
|
|