你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

STM32F103标准库开发---IIC主控实验---普通I/O口模拟---底层驱动程序

[复制链接]
STMCU小助手 发布时间:2022-9-7 15:22
IIC底层驱动程序
2 N" z- `0 a1 g% O* g这次I是普通I/O端口模拟IIC通信实验
& I' b. O5 g1 D) v6 M9 L具体引脚配置如下:
, H/ z: V2 g: s1 R 1(AJZXY`OWAA2]LA6E)0B.png
3 V3 C) {6 F- ]6 e8 ~! D: s' M- A8 K4 l$ k$ [3 ^- O6 f! ~
6 y0 q6 S( k) n; g2 e" G
IIC主控实验----底层驱动GPIO配置
9 w5 B' d! V. d6 L4 {: W/ |GPIO初始化配置" O' s. i" @, j9 i3 X9 E5 @
具体代码如下:
) T  R/ v6 e1 W) G' g
1 L2 b# r- Z' B2 T: n
  1. //初始化IIC0 f5 _8 Y+ f: Q2 A: y
  2. void IIC_Init(void)
    4 J0 M! r6 j8 u; F9 s/ j
  3. {                                             9 O, T4 R3 t( _% _/ O
  4.         GPIO_InitTypeDef GPIO_InitStructure;% x) A" |9 o2 j1 o& p  A- o
  5.         RCC_APB2PeriphClockCmd(        RCC_APB2Periph_GPIOB, ENABLE );        //使能GPIOB时钟
    6 l4 A8 g$ T9 G1 c& J
  6.            # ~( L) P0 f/ ~5 t9 N# I
  7.         GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;
    % i6 E& z- L. i+ d6 m4 [
  8.         GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP ;   //推挽输出( c$ o& g; D$ n5 I- w* O; Y: x0 |
  9.         GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;! f5 {% Z" V* a( L8 P
  10.         GPIO_Init(GPIOB, &GPIO_InitStructure);
    ( ?5 a# x% y( i# x! s" A+ C
  11.         - H- @' ~  A, P3 V+ v
  12.         GPIO_SetBits(GPIOB,GPIO_Pin_6|GPIO_Pin_7);         //PB6,PB7 输出高电平---空闲状态5 r; [3 W5 \- X5 F2 t" f
  13. }
复制代码
1 ^1 k8 E) k6 W: ~! R6 b
时钟线(SCL)—GPIO功能配置
. A& o% X8 e2 F" C4 X7 X在IIC通信中,主控的时钟线(SCL) 一直是输出状态
0 c, j" p) }) E1 k) V. B具体程序如下:# O. r& U/ G  s% H: h2 \& z% b

" i+ R; P0 ^( c, B2 |$ {
  1. //时钟线(SCL):PB6输出---高电平
    & @" p# \, ?+ f8 p
  2. #define SCL_H                  GPIO_SetBits(GPIOB,GPIO_Pin_6)  
    * Z3 A, j2 _2 J
  3. % ?1 c( t* P0 C
  4. //时钟线(SCL):PB6输出---低电平                                                                                       
    0 A, |- P. \$ L9 W) r
  5. #define SCL_L                  GPIO_ResetBits(GPIOB,GPIO_Pin_6)
复制代码
1 S3 G  R, o. [  H2 P' e" E- g
数据线(SDA)—GPIO功能配置
0 g5 |: z8 f, ^0 R; D9 Y由于IIC通信是半双工通信方式
1 x$ Z, a( h* d3 n( Y% T因而数据线(SDA)可能会是数据输入,也可能是数据输出。/ L' Q5 L' C5 a0 m! S- R
% }/ e6 ^) K6 @/ [6 O: R. b
  1. 数据线(SDA)输入模式$ C9 E* D9 O- |5 a" y' l6 e
  2. //数据线(SDA):PB7输入' Z, k9 z5 t2 o4 h; ?4 I
  3. #define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}7 @  Z5 ?1 r* \4 l0 k$ I
  4. % `& c" ^: s1 I9 G, D3 R
  5. //读取PB7的电平
    , ^$ o9 u6 E7 T% s/ E/ t* f
  6. #define READ_SDA  GPIO_ReadInputDataBit(GPIOB,GPIO_Pin_7)
复制代码
: K1 C8 |& Y9 h
数据线(SDA)输出模式
# M9 H/ n/ a* B/ p( s8 W3 ^6 G
  1. //数据线(SDA):PB7输出1 E# ?- T& B4 v7 b2 `  J' c' E
  2. #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
    5 E" b  s- o7 G! l

  3. 9 Y5 ~2 s7 `& v* q0 g) p
  4. //数据线(SDA):PB7输出---高电平
    5 \+ s, K( S' }" h( r
  5. #define SDA_H          GPIO_SetBits(GPIOB,GPIO_Pin_7)        
    ) P# n& z/ B- m& n/ o
  6. //数据线(SDA):PB7输出---低电平3 `: g5 O/ r- k( A! k& \! W( e
  7. #define SDA_L          GPIO_ResetBits(GPIOB,GPIO_Pin_7)
复制代码
7 ?0 K- _; v, y2 g; K
IIC主控实验----底层驱动程序* ]6 o! M  G% p( x; p; w/ {4 [
开始信号0 z' S% H7 L3 X8 j$ E9 ?: V
当时钟线SCL 为高电平时,数据线SDA 由高电平向低电平跳变。
8 o, h3 Z* T4 @0 ^, Q& z
- V; e3 z7 g, m% ~1 j$ [具体程序如下:
. `3 r1 p  l. _) U: f  E$ v: P6 X/ H- d$ S
  1. void IIC_Start(void)//开始信号
    # O5 z+ ~! W5 N$ x. N$ p
  2. {7 |/ [7 {( [, n9 D6 i) J5 L5 g
  3.         SDA_OUT();                        //数据线(SDA)输出模式
    * @+ \( ?1 }0 {0 ^3 p1 ^
  4.         SDA_H;                                //数据线(SDA)输出高电平
    3 f! ^1 ~0 Q+ L
  5.         SCL_H;                                //时钟线(SCL)输出高电平$ C6 _' L& d0 v+ I
  6.         delay_us(5);
    6 a" z/ W1 [( o1 m( S% u  P
  7.         SDA_L;                                //数据线(SDA)输出低电平8 y8 ]( L- c2 Y$ V! ^! }
  8.         delay_us(5);
    8 O  ?$ d8 D$ ?: x0 P
  9.         SCL_L;                                //时钟线(SCL)输出低电平( D- O1 ^- y7 d& d
  10. }
复制代码
+ @& j; @7 [' H: k
终止信号- I( `# i' j: l! E1 k( @8 T+ b
当时钟线SCL 为高电平时,数据线SDA 由低电平向高电平跳变。0 D# P/ P0 K$ D
6 u6 C. `! k; [. t, q
85e82cdd10414eafa919be9c7d480bf4.png " o( D' J7 Y# _/ N  M

( V- q! h) l: Z具体程序如下:7 R0 C0 o% H8 L

. p/ ^0 v$ [8 s' K
  1. void IIC_Stop(void)//终止信号
    % u' |, t: e6 N4 K# |
  2. {) d: i% Y; E& T2 i
  3.         SDA_OUT();                //数据线(SDA)输出模式& ]) n( R3 T3 q4 h" V2 Z7 B
  4.         SCL_L;                        //时钟线(SCL)输出低电平
    " P. G+ ]5 D+ m
  5.         SDA_L;                        //数据线(SDA)输出低电平5 P2 x" D  X/ e1 [
  6.         delay_us(5);0 ~0 n  `$ M/ {/ k5 G, k
  7.         SCL_H;                        //时钟线(SCL)输出高电平
    : h9 a4 X& S& k$ H
  8.         SDA_H;                        //数据线(SDA)输出高电平
    7 @2 S  [) T3 ^
  9.         delay_us(5);+ z6 g  v4 H2 F- \  O' l
  10. }
复制代码
8 p, I7 k5 v) _. @6 `
应答信号
  x9 j7 U1 @- D- v% h+ h1 i# s0 r我们这里写的是IIC主控程序,在读取从控数据的时候,需要回复应答信号。
  K+ w% g) n/ ~% S; n- v+ W: s4 P产生应答信号,表示接收数据成功。
6 g( Y3 R! m* y1 B% h( P9 [. g' ]# j6 K+ i$ X$ H0 z
87595168bd4d4c1aa0c65f6957e146e7.png 6 j1 N" h8 _* o" j

& |; i" `& `% X- b$ K9 B具体程序如下:
6 p6 ^2 ^& K) ~  ]( X& V* r' G" e- o8 v/ R1 S% O
  1. void IIC_Ack(void)//产生应答信号
    3 n% k  Y4 V# ^8 M9 ]# t
  2. {& Q. w6 `8 }+ r
  3.         SCL_L;                        //时钟线(SCL)输出低电平
      U0 D& f) u/ F: F7 ]$ h3 {
  4.         SDA_OUT();                //数据线(SDA)输出模式
    * G$ p& Q% k- ^2 d* d; z
  5.         SDA_L;                        //数据线(SDA)输出低电平, c% R6 W( @! e4 _  a# ^
  6.         delay_us(2);
    3 ]6 x3 P0 w" S8 `; e$ K+ t- S
  7.         SCL_H;                        //时钟线(SCL)输出高电平
    9 f$ j" R0 H9 a$ E1 {; z  y
  8.         delay_us(5);
    , {) W' @- j" [) [
  9.         SCL_L;                        //时钟线(SCL)输出低电平
    , q( l" u' k0 M: R5 g# S2 N
  10. }
复制代码
9 p& J& Q% |. c- J2 T; ^
产生非应答信号,表示接收数据失败。
: z- _7 o( j1 M; {! Y
+ W4 d7 G, q8 u# `# Z e71f596960034e5797457ea9bcbd1fd2.png
( d( B* U7 l+ A1 B5 v1 x
+ k! z! q# d% b: `具体程序如下:
* z! t5 G, @3 E$ u1 F8 ~6 H. V* u0 i  y) \  \' O( P; [
  1. void IIC_NAck(void)//不产生应答信号; U! w% T% N$ c% z
  2. {' K2 \- a) h0 W4 q5 K" i6 r
  3.         SCL_L;                        //时钟线(SCL)输出低电平# e( W9 k0 ~) Z* j2 F! k3 V! `
  4.         SDA_OUT();                //数据线(SDA)输出模式) a3 a. A3 I5 t3 {" H% ?; z5 }
  5.         SDA_H;                        //数据线(SDA)输出高电平1 }3 j8 h2 v" @+ Z+ C5 E4 m
  6.         delay_us(2);/ n6 R. A' L" @( G5 M
  7.         SCL_H;                        //时钟线(SCL)输出高电平
    . r$ r, x( J+ E2 o! X9 A1 F
  8.         delay_us(5);  a& O1 R* |2 o* B" B& S6 s6 P
  9.         SCL_L;                        //时钟线(SCL)输出低电平
    7 f7 R$ M6 j# M) r+ S, S- H
  10. }
复制代码
- o5 c, }6 v2 l

# P9 ]  N5 `+ _9 r" gIIC主控程序,在写入数据到从控的时候,需要等待应答信号。
) Q) H0 i4 n; W' E' ^* M
$ R- \, q% `, V( f
  1. //返回值:1,接收应答失败0 L) M! Z* V% ^% K) T& c
  2. //        0,接收应答成功
    % I8 ^1 C% ?* h& k, w' t; U
  3. u8 IIC_Wait_Ack(void)//等待应答信号. _  x# o* [; ~" v$ f/ Z
  4. {
    . ]7 N! x9 {# j# m& o" j
  5.         int uc=0;! i: t7 E3 o. P  E# Q
  6.         SDA_IN();                //数据线(SDA)输入模式8 p# v5 T$ |" O5 n& v" O* @
  7.         SDA_H;  delay_us(1);
    9 T/ @+ q1 l- [& s
  8.         SCL_H;  delay_us(1);% }1 G# \" _+ Y0 y* Y6 k
  9.         while(READ_SDA)
    2 V- v0 L$ g! s! M0 ~7 C, e  P
  10.         {) k! F& Z6 M( w0 `* U9 m
  11.                 uc++;: t2 l: W5 @1 }9 C- r
  12.                 if(uc>250)//接收应答失败0 @% l9 g5 f1 Q$ f
  13.                 {! P) n; M9 u) V" E" K
  14.                         IIC_Stop();//发送终止信号                * X/ @7 I; |. k
  15.                         return 1;; r/ D; j3 ?4 x3 V
  16.                 }6 N1 i- ~  V8 G: F2 D+ K; _
  17.         }- b' |; \( E& v( X
  18.         SCL_L;
      Q( W; C' D- y* c; ^3 E& O- Z
  19.         return 0;
    6 O; m$ u9 @+ }7 }- d; y8 }
  20. }
复制代码
/ i7 H0 t; c, D
数据传输* I3 Y0 h9 f, t) u0 B
IIC总线进行数据传送时,时钟线(SCL)上的信号为高电平期间,数据线(SDA)上的数据必须保持稳定。% C/ a1 B; l) ^9 \$ a" d
只有在时钟线(SCL)上的信号为低电平期间,数据线(SCL)上的高电平或低电平状态才允许变化。
2 S$ Z' F. s; B
4 h, y  C- O0 A% Q. q$ F& S, Z6 d3 H# u6 G e4fb93724d594f4b8cea33fae5a7e126.png 9 z3 f+ M8 k. ~
7 l( J" U( S8 l/ N
输出到数据线(SDA)上的每个字节必须是8位1 q. x- i- [. h3 C+ N  G$ S
数据传送时,先传送最高位(MSB),后传送最低位(LSB), y2 @7 A' r9 X& p. h' h! v
每一个被传送的字节后面都必须跟随一位应答位(即一帧共有9位); F$ f* T% s0 L7 b& {, D

( I: t, ^% e7 t0 w d41a30c5c86f40ca8c599ad13b0d5de8.png
& k* W) {( K; Q# ^0 [# M- B
% q0 S1 A5 b2 H) P6 ^9 iIIC主控发送一个字节数据1 C3 p  J8 ~4 x+ D. C+ f
具体程序如下:
- u8 }. {% O& q" |: E+ P1 k6 Y
' O2 c' O9 O' H, }$ l
  1. void IIC_Send_Byte(u8 txdata)//发送一个字节数据---高位在前,低位在后
    0 o  W5 w8 h) }) Q: _' h* R0 p
  2. {
    ' }& z' m" B' [% [2 {
  3.         SDA_OUT();                                //数据线(SDA)输出模式
    . N- y/ `. o# W' |; {
  4.         SCL_L;9 X1 Q+ ^7 I8 A; s* p
  5.         for(int t=0;t<8;t++)        //高位在前,低位在后。9 {. c, ~0 M, ^+ u% V
  6.         {1 A$ V+ n6 c$ O" L# B- ?! f: h5 F
  7.                 if((txdata&0x80)>>7)           SDA_H;( D5 H" y: S8 N, @" d
  8.                 else                        SDA_L;1 E0 n+ m- e: G5 x# H& Q
  9.                 txdata<<=1;/ b# r* S! Q6 e" y  i2 l
  10.                 delay_us(2);
    9 p' X3 q, X. Q9 _. |
  11.                 SCL_H;/ ^1 x! k# u% |3 k$ L: B1 ]
  12.                 delay_us(2);
    ) w2 C: F. w$ m; X
  13.                 SCL_L;* b, w* m* F$ U& s% B& [# }
  14.                 delay_us(2);
    5 r( w* R8 o. L
  15.         }/ ^/ g$ }9 v8 P2 F% H
  16. }
复制代码

$ T# Z  X( K" f0 W* l: K% D8 YIIC主控接收一个字节数据& _5 }6 v( X% |% p0 y
具体程序如下:6 Q0 X9 X  A8 t" s& t; }

% ^  S+ j+ H0 Q% e
  1. u8 IIC_Read_Byte(unsigned char ack)//读取一个字节数据---ack=1时,发送ACK,ack=0,发送nACK9 `; r3 `7 ]% A- `" O
  2. {4 u$ i# z. L' g, t$ e1 i
  3.         unsigned char rxdata=0,i;2 |& S, T2 b1 w, M8 i% g
  4.         SDA_IN();                //数据线(SDA)输入模式
    ( `* H- b% g. Y6 d' m! C
  5.         for(i=0;i<8;i++)9 `/ A; K& Q9 E! x5 u+ `
  6.         {1 b2 Z$ R% W1 J# \: D; g1 y
  7.                 SCL_L;
    4 A  [' V: O! X+ Y3 _. V6 x9 [
  8.                 delay_us(2);. i. v4 p2 b3 m8 M0 u9 T4 J
  9.                 SCL_H;; g3 a' Q/ R2 h, V
  10.                 rxdata<<=1;
    8 T8 ~) U  M" ?/ X3 O9 U
  11.                 if(READ_SDA) rxdata++;
    ; y. j6 T2 Y2 z
  12.                 delay_us(1);8 i( V) ^1 M+ U3 I
  13.         }7 l6 W7 d* w9 g' v8 W
  14.         if(!ack)   IIC_NAck();/ i" t- e% a2 L, T$ b
  15.         else       IIC_Ack();
    5 S" l+ ]% {$ P4 n! o8 N
  16.         return rxdata;
    % z7 J" p( Q* N1 Q4 {5 w& Y
  17. }
复制代码
5 G1 L7 s8 V. K0 L+ o3 n

% F( d7 z1 {- N  O; R5 I2 l: R————————————————" j! O8 N+ l6 }+ Y! m+ b
版权声明:根号五
% R) o) V. A* t& F+ ?
) n9 T5 |4 j8 L% i' S4 P/ A7 p0 a7 O* R; A$ N$ }9 \
08ca25e70b6748a585680b8b4fb6bb86.png
赞 收藏 评论0 发布时间:2022-9-7 15:22

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版