|
EDA365欢迎您登录!
您需要 登录 才可以下载或查看,没有帐号?注册
x
——疯壳·开发板系列 I2C教程
: B5 L; J/ q/ g+ y. d" ]* B& p( X+ I9 {) M" S7 j1 J& C( ^- f. m# K
# H% L& f& R1 M& G: b- N2 [- d7 t+ m1 e
0 Y4 W! r3 ~% t+ E1 i Y+ z" W" K
图1- s- f- V C4 L9 s4 K4 W% P8 O
* n2 l: v- X) s8 x 第一节I2C硬件电路
- O* f4 t! i+ _0 M8 ~9 X 将P12与P13配置为I2C的两个接口即可,P12与P13已通过排针引出,如下图所示:9 B$ f! J, }4 T1 @
' c: G& `: t1 Z0 n5 ?% `
, e0 t- S" O3 q2 F1 z- Q. O
6 `7 ]" ~4 \* S) i) ]& q9 W7 Q3 Z 图2
) a- I, d9 @: X4 f% [1 ?# f( y& ~( ~" X
4 |5 G4 `. d& @" L9 P
) }' p, @$ c( _3 m+ x9 C2 ~1 k% ~7 M
第二节 I2C9 P- R+ `3 ?# q9 ]$ w
2 k' {: A6 T6 E% g* P% q
2.1 I2C介绍6 Z3 P J, \/ _" D
I2C总线是一个为系统中电路通信提供支持的可编程控制总线,它是一个软件定义的两线通信协议。+ y$ e6 K! y8 e. |* W# J1 Q
两线I2C串行接口包括一个串行数据线(SDA)和一个串行时钟线(SCL);
' S2 N7 q9 @3 J$ [2 P4 ~ 支持两种通信速率,标准模式(0~100Kb/s)和快速模式(小于等于400Kb/s);
' f" c7 j* f) |7 Y# b7 E 时钟同步;
% z9 C6 c' ]3 \8 m' p, S 32字节的发送接收FIFO;
W) ~6 x! ^" I5 W! l6 N+ T 主机发送与接收操作; \) t& t! [) j8 T
7或10位地址,7或10为混合格式发送;$ S. @- c* |8 v& C9 w
块发送模式;
7 ~& F% h$ k* [' I 默认从地址为0x055;, ~0 N& I+ i+ L' y) _
中断或者轮询操作模式;
8 _ ^( z2 u, y8 c! W7 H0 u 可编程的数据线保持时间;# @0 `% V1 S2 h' L
" t+ Z6 c% {, S, A2 A; g
2.2 寄存器介绍
7 w( C7 K4 L- `; M- f4 N I2C相关的寄存器比较多,所以我们只介绍常用的寄存器,其它的可以参考官方数据手册AD14580_DS_v3.1.pdf,位于目录:..\WT开发板\硬件资料。9 Y4 k9 x6 o9 c* q
' q0 K7 A8 b3 v O* X& N9 G4 B
2.2.1 I2C控制寄存器
" O$ h$ e8 r0 c" S" N9 }" b
$ l8 s2 Q0 F; J8 q* W: T
8 P# I, U8 a1 }
图3
: k& t' u- f" \- L8 I3 | 15:7位:保留不使用;
' z) M7 `9 u" K u2 \ 6位:I2C从设备使能位,’0’表示从设备使能,’1’表示从设备不可用,该位不一定要软件设置,但是要保证如果该位为’0’则该寄存器的第0位也为’0’;& d1 J4 }+ C/ ]1 T
5位:当作为主设备时,是否发送重启条件,’0’表示不可以,’1’表示可以;# g8 e( k8 F* U& |0 z T7 V9 F. W
4位:作为主设备时,决定以7位地址还是10位地址开始发送,’0’表示7位地址,’1’表示10位地址;
% j$ Q9 f" O, _4 d; m9 i' U 3位:作为从设备时,决定以7位地址还是10位地址开始发送,’0’表示7位地址,’1’表示10位地址;
+ |$ M. }0 {/ K% D- _ 2:1位:I2C通信速度选择,1表示标准速度(100Kbit/s),2表示快速(400Kbit/s);- h) T/ A) }4 |% Q: C. |
0位:I2C主设备使能,’0’表示主设备不可用,’1’表示主设备使能,要保证如果该位为’1’则该寄存器的第6位也为’1’;
& q; m M/ z' a" @9 y8 G: f
; B4 b+ B8 X$ K7 F+ v+ g! o, h6 g H 2.2.2 I2C目标地址寄存器' o( Y! Q2 b$ E+ M' b( S
! P- J6 t. Q% v8 L- r3 N
0 [4 x( p- l. T2 L/ V! F
) A7 M; q1 |$ n% f! p4 }0 \
图4/ k$ S* V1 e! j$ v2 J/ b
15:12位:保留不使用;' n+ ?1 ?* s7 n6 ~; ]5 n; ]
11位:该位决定软件是否进行广播或者开始字节命令,’0’表示忽略第10位GC_OR_START并且正常使用IC_TAR;) j, U4 ]; k- Q5 m7 H2 b
10位:如果第11位设置为’1’,则该位表示控制器是否进行广播或开始字节命令,’0’表示发送广播地址,之后只能进行写操作,如果进行读操作则导致TX_ABRT置位,控制器一直停留在广播模式,直到第11位被清除,’1’表示发送开始字节;& i" R7 v2 L; r/ H; t8 `# P1 V) Q
9:0位:这是主设备发送的目标地址,如果发送广播则该位被忽略,CPU只需要写一次这些位;注意如果目标地址与从设备地址相同则存在回路,但是FIFO为主从共用,所以完全回路是可行的,只支持单方向的回路,一个主设备不能给自己发送数据只能发送给从设备。
/ o, R: v+ ]$ C1 X: \: H; ]/ U0 Q# [! U" T6 I( c. t6 A3 h
2.2.3 I2C接收发送数据缓存与命令寄存器0 W" g3 K$ ^* ]/ v
+ n6 w+ I) V" R$ s4 a
+ {2 u8 @- k1 T5 g" u
2 Q ]% I) C* Q; _' B4 z 图5$ }- }! W/ \9 j- D& }( z5 X' J
15:9位:保留不使用;' f% S3 a/ g6 \+ q
8位:读写控制位,作为从设备时不能控制方向,只能作为主设备时使用,’0’表示写,’1’表示读;6 b7 E3 s* n6 T0 |7 T. g" L
7:0位:存储I2C总线上发送或接收的数据,如果你正在操作该寄存器并且要进行读操作则该位被忽略,如果你读该寄存器则该位存储的是接收到的数据。; ]8 k0 ~1 p% o$ v. l0 g
, V: a0 R% L: w+ ]
2.2.4 I2C清除TX_ABRT中断
E _: {1 Z" W6 n' q; [, d! t9 c0 H7 ?
: X1 {; Q1 [. X' `3 _8 w% C
图68 \6 N* v4 Z* |9 F0 C4 v
15:1位:保留不使用;
7 f/ Z' V4 v! b5 E& d 0位:清除发送异常停止位,读该位则清除发送异常停止中断位,和发送异常停止源寄存器位。同时发送FIFO从刷新/复位状态中释放出来,可以允许更多写入。- k1 H% L: c* e4 w3 S1 a! R
/ R2 ~$ _, J* R) s# t
2.2.5 I2C使能寄存器* G% l& ~& D* X4 J
) c" C, |# k v: e# O
/ F) u1 {2 g m% L( \
+ @8 C/ D( z$ ~
图7
% E( ?8 X0 T5 S$ T/ ~+ a 15:1位:保留不使用;( ]3 J6 E# N" N3 r0 f
0位:控制器使能位;
) R2 ?1 Q2 s9 y& q7 ~ B
9 F3 k5 a0 l( u' Y) C 2.2.6 I2C状态寄存器
- l' v- I, k$ y7 w4 J* _( `# f- R. |6 d: F3 a, w
0 B; V: w7 S3 {: c: t
* ~* |8 r/ J3 _. \- Z8 Z
图8# Q0 e; G: n' Q2 i7 R+ V' W
15:7位:保留不使用;
" S0 S& p% f' N: M v5 Q* W 6位:判断从设备是否活动;
3 T7 L# ]$ B1 Z 5位:判断主设备是否活动;8 y3 N2 s$ T( z8 w& W) Y. _
4位:判断接收FIFO是否全满;
" Y E% w/ q7 ?: t3 ]7 w 3位:判断接收FIFO是否为空;
" `# \) E& B9 l) Y. `/ g! @! l$ { 2位:判断发送FIFO是否全满;0 S. a/ ] t! N7 t' H+ s1 Q' P
1位:判断发送FIFO是否为空;
" a! D6 _; w' H 0位:判断I2C模块是否活动。! y; |; t+ L$ b/ H: l/ H4 T8 M
8 q0 Z0 T; ~( ?4 V/ C 2.2.7 I2C接收FIFO数目寄存器
0 l5 O/ H0 G8 s: h0 d* p; X( k( y! d7 y% a# ~/ l9 K- w g
. i; O; j |- T+ ^9 }( ]# | 图9
7 ~/ [- t3 T: h! P 15:6位:保留不使用;
! }* A9 P1 I, v( R' h" H( G 5:0位:接收FIFO可以接收多少字节。5 [3 W' E0 j! {2 e& N' L* k8 V
! l Q' z% i w. r1 L 2.2.8 I2C发送异常终止源寄存器
" \! g, z. j' s
' l! g, I3 `/ j- l: N' G
- C" W8 p3 { K% V1 A% P/ D2 ^4 Q
, S( g* @7 D% c0 r% k, z; B
图10
" ~! j8 c; e4 O+ @( s 15位:当主设备需要发送数据时,却进入读数据状态;
3 n( y2 s) J1 o 14位:当发送数据时,从设备丢失总线;
" C6 P/ l6 n, w% a* S) I1 W8 i 13位:当从设备要接收数据时,FIFO中已经有一些数据;% j% S" }4 K. V9 B9 i9 }8 t
12位:失去仲裁;9 A( ^: n& g- o" S6 }
11位:当主设备不可用时,用户进行主设备的操作;
- k0 g) w l* S z2 z- t. O 10位:重启不可用,并且主设备在10位地址模式下发送读命令;
; }& O, b9 b) e+ x 9位:重启不可用,但是用户发送一个开始字节;
- P! h- k+ q/ a7 ?1 I 8位:重启不可用,但是用户试图在高速模式下发送数据;
7 W9 W. M# u. s6 v) e+ e" { 7位:主设备已经发送了一个开始字节,并且开始字节被确认;
- k4 X6 W; M- C7 V5 a9 I 6位:主设备在高速模式下,并且被确认;
2 H% {7 N7 |/ }) c) C" ~ 5位:主设备控制器广播之后进行读操作;
" U% `; H( F9 [ B2 u( A 4位:主设备发送广播,但是没有从设备确认;
; {- S# a$ u% Z3 s! h& O 3位:只有主设备有效,主设备已经发送地址,并确认,但是发送数据得不到确认信号;+ T0 x: t* y" N0 N! b+ k s" g
2位:主设备使用10位地址模式,10位地址的第二个字节没有被任何从设备确认;
* E$ E: x- e7 N7 } R; { 1位:主设备使用10位地址模式,10位地址的第一个字节没有被任何从设备确认;- r- J' z3 d* F- u" g
0位:主设备使用7位地址模式,但是没有被任何从设备确认。* h* q/ O# J+ m; c
7 y8 U% \2 ?: O+ K" n1 h
2.3 寄存器配置讲解
^- c( P# L: V/ z$ b, u7 S. E
5 |4 L& r8 c& }- Q; i #define CLK_PER_REG (* ( volatile uint16*)0x50000004)% z2 W" K9 [: j) U, x
#define I2C_CON_REG (* ( volatile uint16*)0x50001300)2 u0 U6 J, r! f3 _( e7 ^
#define I2C_TAR_REG (* ( volatile uint16*)0x50001304)5 f9 ?! o3 s' l: o
#define I2C_DATA_CMD_REG (* ( volatile uint16*)0x50001310)$ `( t6 ] J6 q v" Q: v" K6 y& K
#define I2C_CLR_TX_ABRT_REG (* ( volatile uint16*)0x50001354)
! @ q6 \4 i: k% R6 B; p# { #define I2C_ENABLE_REG (* ( volatile uint16*)0x5000136C)
& u/ Y, s) n. P" o #define I2C_STATUS_REG (* ( volatile uint16*)0x50001370)
]- ~& N) T. k% O G k #define I2C_RXFLR_REG (* ( volatile uint16*)0x50001378)
# @. a4 e" |, |# _$ e' H #define I2C_TX_ABRT_SOURCE_REG (* ( volatile uint16*)0x50001380)
; V# @- L& g0 Z& Y. X! C 启动I2C模块的时钟:CLK_PER_REG |= 0x0020;
7 }- ~& L3 e6 ^9 Q- h* y% O I2C的初始化寄存器配置:3 I& s, s: i9 `* V6 Y9 l2 C+ v
先关闭I2C控制器, I2C_ENABLE_REG=0x00;) a( W, J W9 A* U9 \
设置为主模式,关闭从模式,可以重复开始,速度设置为快速,地址为7位模式(0x0000000001100101), I2C_ CON _REG =0x0065;
3 x. N; G. O, k1 j 设置目标设备地址为0x51, I2C_TAR_REG =0x51;) ^; c$ ~& e+ o
打开I2C控制器, I2C_ENABLE_REG=0x01;
% J# E+ P4 [8 X; B 等待控制器准备好,while( (I2C_STATUS_REG & 0x20) != 0 );
( g) R' w( N! R1 h- 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;
# a1 l& Q( k7 X; G# \3 H. | 向地址为0x98处写入一个字节0xaa,先发送地址I2C_DATA_CMD_REG = 0x98;等待发送完毕while((I2C_STATUS_REG&0x0002)==0);发送数据I2C_DATA_CMD_REG = 0xaa; 等待发送完毕while((I2C_STATUS_REG&0x0004)==0);
, A4 l3 S) h& b& ^ L
% F6 s5 n9 W$ a7 `. N0 q( m: C3 \* Q$ d0 ~. n) T9 o5 ]; t1 R' c
! N* T. j8 W. K; X
6 U' O3 H( [) T) P T. e5 s! p4 T* n 第三节 I2C实验
5 _" J/ E s9 Z! s, O. i$ ]
: `1 J. c7 {8 g6 { 实验需要使用的模块有:手机开发板底板,Jlink调试工具,杜邦线、心率体温模块、3.7V锂电池或Mocro USB线。1 \" h% `5 A! R4 v% I1 Y! m$ I
将心率体温模块通过杜邦线连接到主控底板上,连接方式如下:% b! B0 ^+ C& f+ g
(1)心率体温模块一端主需要使用杜邦线连接心率体温模块的3V3、GND、SCL、SDA四个引脚,如下图所示:
2 D ^! i y. j! g9 H# M& K' |
6 c: v8 Z+ _9 Y$ G5 Q
- Q0 ^7 l. M& E. T 图11( d( R: e" t5 B; Q% M
(2)手机主控板一端需要使用杜邦线连接J4的2个引脚以及J10的两个引脚与心率体温模块的引脚一一对应,如下图所示" h2 n( ^6 l; h* g- [. q1 ?
6 c' J; M: h- L0 P* q2 ^
4 b) g9 C; M3 ^8 |' d) c
( h# g. m, {& l( k3 r O
. E0 g; r* L7 ^$ B
图12
O* k' v# F7 w 使用JLINK通过杜邦线连接手机蓝牙位于手机主控底板,连接方式如下:
$ f" l3 e( O% c! S3 V& P (1)JLINK一端只需要使用杜邦线连接JLINK的SWC、SWD、GND三个引脚,如下图所示:
4 O/ F. l u3 t3 T' i1 ~
/ d' }4 V+ {% o4 j+ k3 ^& P/ q& S
$ o- O1 n, S0 \6 p. e 图13
( `8 o! f! X: ? (2)手机蓝牙一端需要使用杜邦线连接上方右侧的J3三个引脚,与JLINK的连接引脚一一对应,分别为SWC-->SWCLK、SWD-->SWDIO、GND-->GND,如下图所示:
+ N' n9 |; n+ W
4 ^' x$ _ y( x0 F! J
# l# P: W7 P$ Y4 d9 `0 I) g2 z9 J 图14
2 u; i/ c! N3 r9 @! U" N 将JLINK插上电脑的USB接口,连接好之后给手机主控底板供电,详细的介绍可以参考《如何上电》教程,路径为:..\WT_Mobile\0.从这里开始\0.开机测试。
% i$ R1 } S3 h 打开I2C实验的Keil工程i2c_eeprom.uvproj,位于目录:. \9 M1 \& {; x6 K5 m5 b
..\WT_Mobile\1.初级教程\DA14580\5_初级_I2C\projects\target_apps\peripheral_examples\i2c\i2c_eeprom\Keil_5,如下图所示:* f! [5 R' i9 T
9 r7 D, R) j* h% E' n2 }
# a! L( |& p3 C! z! j& ~8 v, `- e 图15+ I8 `2 y2 c3 A: C( C B( |
在KEIL中编译源代码,点击DEBUG,然后点击全速运行,在存储温度数据的变量下方打上断点,当程序运行到断点时就会停止。将该变量添加进变量查看窗口中,可以看到温度值,如下图所示:
$ b0 t! g* B! k# j& z
0 c% X- K6 K. U- T$ r" w
- I3 m3 q+ r% y' N# `
0 u' l' w# o; _* ?, T1 b
5 K, |( Y8 E9 Q" h/ I5 L
/ F/ `; D9 ?0 f+ L. C3 I7 v4 J7 X& d
4 r, F, ?9 g' W. o- m
5 R0 v3 K- D/ D' I' W/ X3 v2 ~
( J3 Q& B+ r U- Q E3 ^
图16
/ m& A, t6 h$ L$ O0 F7 |, ?: S( a. X# g6 T, @' Y) i4 b, M
/ ?. h7 z! m: N1 W
4 `, C8 \3 o3 |
1 M4 z' I0 E5 U
文件下载请点击:
I2C教程.pdf
(1.53 MB, 下载次数: 0)
1 T7 @ }6 ?. W, O% ~
" W/ a9 q$ u$ `: [$ P- l8 [; ^ P/ [
( i3 @) N# ^1 X$ \- h/ J7 K+ ~- U
|
|