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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-22 20:00
  1. #define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
    2 j8 r6 q1 i' X1 P
  2. #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
    , `) P8 N5 G, ^" M8 a# X7 H
复制代码

' @6 f* a- m) z
6 B- P: i/ y" c; a对于我们学的STM32都是习惯性的调用库函数,操作GPIO直接对结构体成员直接赋值即可。学到I2C通信时,看到以上代码中突如其来的寄存器操作,对于我这个新手小白来说是一脸懵逼状态,经过一个下午的学习,也算是搞懂了GPIO寄存器操作。分享一下个人学结,有错误的地方欢迎各路大佬指正。+ X/ ?, t  b: o3 F+ ~9 y
7 r1 i2 W) l& |1 s' J( \

' ~8 @: s' D* o2 E0 \( b1、所需基础知识回顾
) @4 S. {$ }( B8 D9 C由参考手册可知,GPIO端口每个位可以由软件分别配置为:
  Z7 w3 X. _' C输入浮空
% x. X3 ]" g/ p) C8 `0 A输入上拉0 W2 `4 i  A& D' p) I" {9 c9 z
输入下拉% u1 s( j" c( g( X8 d
模拟输入
9 ^3 ?" `9 o$ m" B推挽式输出, g1 u8 Y4 ^8 H/ r; |
推挽式复用功能
3 k/ G: h5 R5 t7 @* {开漏复用功能
6 [' Q4 C1 k! X+ v' v) o: y# b每个GPIO端口由七个寄存器来控制,分别为:
* f! Z) ?7 M: j& [* d' Y8 k! A端口配置低寄存器(GPIOx_CRL)
. N1 I7 H6 l! y5 f4 a6 ]端口配置高寄存器(GPIOx_CRH)5 J6 F( L$ x& _% m8 ~5 v
端口输入数据寄存器(GPIOx_IDR)
8 @. i- E! h' u# Y# R端口输出数据寄存器(GPIOx_ODR)3 j0 }$ b/ e$ D3 _6 L. k" t
端口位设置/清除寄存器(GPIOx_BSRR)* @" U/ t& g$ F) t2 ~: a
端口位清除数据寄存器(GPIOx_BRR)* e3 O7 e! d5 g  s: ~
端口配置锁定寄存器(GPIOx_LCKR)4 R3 O% l- n, K# s" F# ?7 x* z4 ?
注:其中GPIOx_CRL配置GPIOx_Pin0——GPIOx_Pin7引脚,GPIOx_CRH配置GPIOx_Pin8——GPIOx_Pin15引脚(这个必须要明白)
" M( E' H, U' D) A5 B' }' k  w9 w' t8 D# _. x- o; C+ l1 q

+ I5 b" e: D9 u逻辑运算
3 M  `, X8 b4 P" A0 y5 D# d& S左移运算
) I" H- k7 g7 |) B& x+ vValue << num
" e' {, L4 C3 v1 U$ anum:指定要移位值Value移动的位数
6 z- ]! T3 b, H! V- L丢弃最高位,0补在最低位3 |, j0 N8 {  W8 o! @
左移一位相当于乘以2的1次方,左移n位相当于乘以2的n次方% U+ q* z+ O+ A/ H" @& h4 P
例如:8<<28,即:8向左移动28位
+ z& F% f  J8 a# Y( U5 I与运算:1 & A = A ;可得出1跟任意数进行”与“运算不会改变其值
" Q  y' T3 b7 Y8 l  f, v9 q$ k
STM32寄存器描述
  U1 m/ I0 m( q5 l" l( ?, c+ P
GPIOx_CRL寄存器,也就是低位寄存器。配置:Pin0—Pin7。图一如下:0 }0 l% v- e3 ?; \

& S1 w- |" `. W
8d0b99d571a841a0898e4f19d8fd4894.png + b9 O# k- ^# Q' y" G- i
) s: n' }- ]* n' u& h7 [: {
GPIOx_CRH寄存器,也就是高位寄存器.配置:Pin8—Pin15。图二如下:
- t. m4 f0 T/ Z: q6 e
3 U$ I. F3 e4 o. [8 ^/ P1 }2 F
812f052b961547b4817ee64b743310f7.png
0 P, c* R) ^. t

" o  j; ?9 W, s5 e1 q" v也就是一个GPIOx端口分为GPIOx_CRL寄存器和GPIOx_CRH寄存器,其中MODE0[1:0]和CNF7[1:0]一起表示Pin0的配置值,以下依此类推,MODE7[1:0]和CNF7[1:0]一起表示Pin7的配置值。
0 b1 V, O4 x* _: z/ @4 ]' S7 k
: z& A! R# |- Q' G* i
2、代码详解
6 r4 v7 e! E, z+ @' G对于文章开头提到的两个宏定义分开两条解释,SDA_IN()如下:
8 Z* s( B/ Y5 v7 w
) }- ~7 y& _- _4 u" G! q#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
8 Q" X' F+ p% ~9 J* h- b
; U7 [7 {' [5 n% B9 e其中GPIOB->CRL&=0X0FFFFFFF 等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF
) Y) [5 \. c/ {! Q* u8 k# Z9 Q! [含义为:由于上述提到的CRL为低位寄存器,意思是把GPIOB端口的CRL寄存器的28、29、30、31位清0,即将PB7中CNF7[1:0]和MODE[1:0]四位都置零。(这里应该还是蛮好理解的)
, {$ i( r4 m2 @+ z# C. @
+ t& ^! B  S$ c' q( K$ q# m/ x
其中GPIOB->CRL|=(u32)8<<28等价于GPIOB->CRL = GPIOB->CRL | (u32)(8<<28)
: o) q  i' l+ C, ~% H- Y9 T由于u32强制类型转换为32位,则8的二进制为:0000 0000 0000 0000 0000 0000 0000 1000
: U* C' V/ j+ H6 \% q; [将8左移28位得:1000 0000 0000 0000 0000 0000 0000 00001 b; x# O3 g0 E8 V$ Q7 p4 N
由左移之后的数据可知:将31、30、29、28位设置为1000。下面对上图中的CNF和MODE解析
* L- s- K9 M& R, A( _
) M- W0 V" J: a
即将PB的CRL寄存器中29和28位设置为00,由图一可知,其中29位MODE7[1]的值=0;28位MODE7[0]的值为0;图三如下:$ m% {1 b; S7 M7 l
$ t: [# @6 |9 n+ L

0 y( _1 J% U6 a! I5 R: | 57bdb75cf48a484d836d20a6a31f7923.png 2 u. o; l! ^' Y

5 }! S: _/ i1 @
由上图得知:29:28位配置为00,由下表得知,MODE1和MODE0为00时为输入模式。图四如下:# E! G3 J% P1 K  `) b/ {3 U2 B

! D1 z; Q8 f) R
# m' G  |) Z+ v1 G
baf0dd61a6b348b6a47dfd6ecc295fc4.png
+ J8 S% Z( l: R$ ^! b" U) W$ g% Z5 P- u9 @0 i' C
接下来分析31:30位的值:10,由图一可知,其中31位CNF7[1]的值=1;30位CNF7[0]的值为0。图五如下:! ?& ~8 P) s8 p! w1 }

5 W0 u1 W6 d: b5 j8 a0 U* b
56323f282da24b1dbd2150136a292c37.png . j% m. S- T- z! J5 P5 E

8 t9 C* x! j' k( O由29:28位得知:为输入模式,且31:30位的值为10,对照图四亦可得出,即为上下拉输入模式
: W  f! l) Y6 [5 r7 L/ m3 `$ MSDA_OUT()如下:
8 U- C5 f) f7 c5 o2 A" u
* h6 `2 D0 F& I4 A
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
3 @2 m, }1 z5 a* E+ j9 t8 i
7 j- t% J; ^! n% F其中(GPIOB->CRL) &= 0X0FFFFFFF等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF% l2 c4 |5 a; f+ w: o. _  r0 |
其含义为:把PB端口的CRL寄存器的第28、29、30和31位清空,把GPIOB端口中的CNF7[1:0]和MODE7[1:0]置零
- d" F. z) r% E' ?. c% Y
9 q2 L! ^& j; R% |2 e7 T
其中GPIOB->CRL |= (u32)3<<28 等价于 GPIOB->CRL = GPIOB->CRL | (u32)(3<<12)
2 G7 {9 m  Q* ~: i3转换为2进制为:0000 0000 0000 0000 0000 0000 0000 0011& W, |: U6 L2 V
将3左移28位得:0011 0000 0000 0000 0000 0000 0000 0000
0 T7 y/ U! ?: T6 s分析左移之后的数据为,将31、30、29、28位设置为00 11
; x* z# j. d5 Z6 Y4 K, n$ P) OPB的CRL寄存器中29和28位设置为11,其中29位MODE7[1]的值=1;28位MODE7[0]的值为1。即为输出模式,最大速度为50Mhz。
- M  e4 X1 g6 n1 e& e
# m/ ?9 i; n3 e6 f. Z7 u: `
bd0b6655f914488c8b083441edf707d0.png ; U; ]0 Z* `, L6 |+ A$ _

# O1 a& B$ H8 S- _7 W" E2 X; f- e; ePB的CRL寄存器中31和30位设置为00,其中31位CNF7[1]的值=0;30位CNF7[0]的值为0;由图五可知:通用推挽式输出模式。
( W$ v  ~# Y) M————————————————
2 n4 N3 j* U* j5 u/ E0 y9 B版权声明:枫华雪悦v- h0 `& i" h6 O; k% x7 o) q
如有侵权请联系删除8 E1 s5 m5 r; |# Y2 G  c* d8 d' X9 K
2 z8 w! L  a$ \! O9 X7 y: R

5 j0 I) P4 z' O: O/ A, H% c7 q: c% p
赞 收藏 评论0 发布时间:2023-5-22 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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