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

基于STM32F1模拟I2C通信中寄存器操作IO方向经验分享

[复制链接]
攻城狮Melo 发布时间:2023-5-22 20:00
  1. #define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
    * ?5 O2 B* b8 k
  2. #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
    ' H1 s2 z7 m2 b' I: @1 U
复制代码

4 k  `" J0 h  I* Z7 k8 k! H5 m* Y  q* {2 x3 m* }6 H
对于我们学的STM32都是习惯性的调用库函数,操作GPIO直接对结构体成员直接赋值即可。学到I2C通信时,看到以上代码中突如其来的寄存器操作,对于我这个新手小白来说是一脸懵逼状态,经过一个下午的学习,也算是搞懂了GPIO寄存器操作。分享一下个人学结,有错误的地方欢迎各路大佬指正。
0 p5 }  k- I$ T0 C% x% ^+ v$ j% \  v/ [; Z4 m
; N! @- ?4 M4 E3 v4 p
1、所需基础知识回顾
$ w1 ]) ^" s- j. z4 V4 f# E, A由参考手册可知,GPIO端口每个位可以由软件分别配置为:
% F) f( Q) z6 M! H& Z% z! }; i3 J输入浮空
4 P7 Z4 k" f# i. J0 }( U输入上拉
7 s7 E( S) w' t2 K/ E+ X7 @输入下拉
! k, u7 [: f; ?8 c  c( [5 O/ S) @+ G模拟输入
" z  L9 b3 b* o# x推挽式输出
7 y6 i. h0 l5 ?; e/ l! |推挽式复用功能  ]8 S! \4 ?6 T
开漏复用功能: R5 ?, a, d( Q
每个GPIO端口由七个寄存器来控制,分别为:
  n6 @: n* n; L5 E端口配置低寄存器(GPIOx_CRL)
0 V: w; q) U6 y( Z6 p# X端口配置高寄存器(GPIOx_CRH)
% ~- S8 V: }; C端口输入数据寄存器(GPIOx_IDR)/ p% a; c# S7 x! F4 U
端口输出数据寄存器(GPIOx_ODR); I1 Q* I9 c7 d# I' N
端口位设置/清除寄存器(GPIOx_BSRR)6 H' ?. ]% i( [3 I8 P& ], F
端口位清除数据寄存器(GPIOx_BRR)6 z$ N& I- v6 F$ g$ H' ^# h
端口配置锁定寄存器(GPIOx_LCKR)
/ `1 o; N$ B1 @9 ?6 q/ [6 D- i/ l4 M注:其中GPIOx_CRL配置GPIOx_Pin0——GPIOx_Pin7引脚,GPIOx_CRH配置GPIOx_Pin8——GPIOx_Pin15引脚(这个必须要明白)
  z1 J. n# `' q/ s
- d; @8 Q. D  r
$ Z2 Q, A8 n# n! n/ h6 s
逻辑运算/ V- D9 B0 N) {; F0 o  I
左移运算
4 h9 g/ I2 y! F: cValue << num9 A% z( H. b* c# F, Z; m
num:指定要移位值Value移动的位数( r, X1 n4 u9 H
丢弃最高位,0补在最低位
- C2 _- C2 n, g# a左移一位相当于乘以2的1次方,左移n位相当于乘以2的n次方. ]% K6 h& Q) P/ W6 P7 y/ T
例如:8<<28,即:8向左移动28位( n5 B6 @( p' O7 m% a/ s
与运算:1 & A = A ;可得出1跟任意数进行”与“运算不会改变其值
% x. F4 g! m: R- @9 }* ~5 H7 l
STM32寄存器描述
+ N/ H8 U+ }$ F( [& q" W
GPIOx_CRL寄存器,也就是低位寄存器。配置:Pin0—Pin7。图一如下:
  g. ^+ H$ C. e9 I& v/ n2 C2 |" N" Q8 f+ ^% f6 m
8d0b99d571a841a0898e4f19d8fd4894.png
+ `5 m3 V) L5 q% J3 G0 C

5 H8 W7 K5 W8 l" J2 X! ^GPIOx_CRH寄存器,也就是高位寄存器.配置:Pin8—Pin15。图二如下:
2 d' t1 X3 u4 b7 A* U- Y' b
) j2 ]( ^3 P& r* U. l7 n' y
812f052b961547b4817ee64b743310f7.png
/ Z, o4 @" }8 j7 M

  A3 R# r/ n& L. S. y也就是一个GPIOx端口分为GPIOx_CRL寄存器和GPIOx_CRH寄存器,其中MODE0[1:0]和CNF7[1:0]一起表示Pin0的配置值,以下依此类推,MODE7[1:0]和CNF7[1:0]一起表示Pin7的配置值。% ]( O" B- H& |! x4 {! Q

0 _- H9 G2 [) k
2、代码详解
/ ?5 h8 _1 j' p+ F- p5 {" g' P对于文章开头提到的两个宏定义分开两条解释,SDA_IN()如下:
* ?% J# @5 `& g2 ]
; I$ b) h7 z8 ^0 I4 S+ K' ^#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}2 a0 u$ `) i4 @# a( N
! X* G6 V; K9 X% ^7 x( Q
其中GPIOB->CRL&=0X0FFFFFFF 等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF
4 {6 e) b3 W, ^$ j6 v/ o/ S; o8 J含义为:由于上述提到的CRL为低位寄存器,意思是把GPIOB端口的CRL寄存器的28、29、30、31位清0,即将PB7中CNF7[1:0]和MODE[1:0]四位都置零。(这里应该还是蛮好理解的)8 k- T- w; E6 j
5 ~; `  k: y; l- N
其中GPIOB->CRL|=(u32)8<<28等价于GPIOB->CRL = GPIOB->CRL | (u32)(8<<28)
6 k% O$ C2 ^6 z- @6 E3 P' |由于u32强制类型转换为32位,则8的二进制为:0000 0000 0000 0000 0000 0000 0000 1000
( C6 T% \" q: ^: k6 c7 \: w9 f将8左移28位得:1000 0000 0000 0000 0000 0000 0000 0000( J1 d( v- x9 }/ r' k' U! u1 ]" F  v
由左移之后的数据可知:将31、30、29、28位设置为1000。下面对上图中的CNF和MODE解析
) E' R& A! U6 I: W. U& h* Z
, g  b0 K( r0 v3 `% W
即将PB的CRL寄存器中29和28位设置为00,由图一可知,其中29位MODE7[1]的值=0;28位MODE7[0]的值为0;图三如下:
& O& Z% i, p- p8 u4 F( f0 M4 ?9 I( {7 _! f9 Y4 X8 b9 ^# A
( K* G& M6 M0 n+ W: V
57bdb75cf48a484d836d20a6a31f7923.png
$ n% B8 j+ `/ Z& h9 W
4 I0 h$ O* l, ?
由上图得知:29:28位配置为00,由下表得知,MODE1和MODE0为00时为输入模式。图四如下:6 S7 b5 A, u; V8 {. j, w/ `5 {
  e) g) X5 l- V/ j$ J
6 _0 k# A  K/ E/ [+ ]5 \$ Z8 S
baf0dd61a6b348b6a47dfd6ecc295fc4.png 7 b) f1 }3 t! ^: d+ J/ u
5 A! _' G  y! J2 G
接下来分析31:30位的值:10,由图一可知,其中31位CNF7[1]的值=1;30位CNF7[0]的值为0。图五如下:" Z0 M/ s9 j, m$ b* r6 B
8 I5 C' t7 R( B/ N! i0 F
56323f282da24b1dbd2150136a292c37.png
  t8 t, F4 g: q3 D

% h1 y  D6 ~9 s* U由29:28位得知:为输入模式,且31:30位的值为10,对照图四亦可得出,即为上下拉输入模式# q: T  t  `- S, Z
SDA_OUT()如下:
( i; G5 y1 x6 y: y% J, l% N4 o

3 L' g' M- A+ N! V#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
8 N% j6 k# N4 Q5 U/ q1 i) n- R+ b+ o
其中(GPIOB->CRL) &= 0X0FFFFFFF等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF: j5 h0 e- f8 t( P9 ?6 p* {
其含义为:把PB端口的CRL寄存器的第28、29、30和31位清空,把GPIOB端口中的CNF7[1:0]和MODE7[1:0]置零: F4 @* ^3 }7 c9 N$ ]" ~+ L' V

6 T0 i0 d$ C3 l7 ~: S  F3 P
其中GPIOB->CRL |= (u32)3<<28 等价于 GPIOB->CRL = GPIOB->CRL | (u32)(3<<12)( |; J8 [! f0 l& N) T
3转换为2进制为:0000 0000 0000 0000 0000 0000 0000 0011
% s% K. i6 L# Z# d4 \, H( D将3左移28位得:0011 0000 0000 0000 0000 0000 0000 0000
' L: Y8 t! b$ B, }1 ]' U分析左移之后的数据为,将31、30、29、28位设置为00 11% s' ^# i' x& N. o( \! z
PB的CRL寄存器中29和28位设置为11,其中29位MODE7[1]的值=1;28位MODE7[0]的值为1。即为输出模式,最大速度为50Mhz。
3 `7 V2 y: T# X' |1 q& E# O( p0 u# i% n, h9 O
bd0b6655f914488c8b083441edf707d0.png
8 V/ I1 z# ^4 Y; {- y$ [, p

# k6 Y0 l+ |" _- J+ U& YPB的CRL寄存器中31和30位设置为00,其中31位CNF7[1]的值=0;30位CNF7[0]的值为0;由图五可知:通用推挽式输出模式。
, d4 y; W& E  ^4 ?$ }9 x% Y8 G$ K————————————————, A! G* h; `: m5 l! [0 y
版权声明:枫华雪悦v
, G4 p. z" p; t# S6 K4 W& B" W如有侵权请联系删除0 D' A. R+ ^8 Z  [4 c. k) m

. o% P% D" J, ^, p; a) P2 s1 `, N* z2 q: q0 [3 h* [+ O
8 S+ z  y* {1 _6 A1 @
赞 收藏 评论0 发布时间:2023-5-22 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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