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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-22 20:00
  1. #define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}1 A2 ?' w, D) d6 k9 ?, w( ^
  2. #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}0 k4 j( d* H, R; b2 M
复制代码

' K( @4 X7 W0 U( D
, l: E8 U* _; y$ l对于我们学的STM32都是习惯性的调用库函数,操作GPIO直接对结构体成员直接赋值即可。学到I2C通信时,看到以上代码中突如其来的寄存器操作,对于我这个新手小白来说是一脸懵逼状态,经过一个下午的学习,也算是搞懂了GPIO寄存器操作。分享一下个人学结,有错误的地方欢迎各路大佬指正。$ _7 v& |) D1 R1 p) t

! W+ ^  z& m/ L: [  ~# R

* K* j8 S3 p! `* d- x, u. b; N1、所需基础知识回顾0 J+ [) O/ V' \3 L8 b4 W: g- Y9 N
由参考手册可知,GPIO端口每个位可以由软件分别配置为:
( ?. d, N$ z) O1 C" z输入浮空
: X- z: v# W3 q4 o' M* u; n" x# V$ F/ b# R3 }输入上拉; x; o$ D: c  l+ F9 Y
输入下拉' Z- x( \% k" y$ w: a
模拟输入4 V5 V2 E+ B3 h
推挽式输出
& e- K! n4 c* C3 e, M7 J9 C推挽式复用功能
" c; D5 D( m$ ?$ C; Z, q4 ~) b0 ~+ D! K开漏复用功能
4 r0 `9 G; m4 o2 E2 z% `每个GPIO端口由七个寄存器来控制,分别为:, C. s( w( _4 V- q* b' B
端口配置低寄存器(GPIOx_CRL)
- Q+ j/ Z6 l1 v. m6 l2 J端口配置高寄存器(GPIOx_CRH)
& o* ^7 L" e( [' K5 t( _: y端口输入数据寄存器(GPIOx_IDR)6 E0 E$ J! a' R( e7 E. k, H" J
端口输出数据寄存器(GPIOx_ODR)
2 X+ d7 |/ u6 S  b- H* m8 q6 ]  u端口位设置/清除寄存器(GPIOx_BSRR)
3 _- U& f/ J( D. u) K5 X端口位清除数据寄存器(GPIOx_BRR)
" z) \: l0 y( F( `/ M端口配置锁定寄存器(GPIOx_LCKR)$ ~( _, I$ U, v; G: n) F
注:其中GPIOx_CRL配置GPIOx_Pin0——GPIOx_Pin7引脚,GPIOx_CRH配置GPIOx_Pin8——GPIOx_Pin15引脚(这个必须要明白)
! p/ `# t2 I/ c( U: R
( R2 F4 q4 Q1 T9 Q, u6 {

  g  e  K8 f1 T5 i6 @逻辑运算' e* }( @( v1 }- J$ U
左移运算
" t7 S' u6 @9 v& Z: o: h" \Value << num8 I& {9 z/ x, Y: L, K2 N) h
num:指定要移位值Value移动的位数1 C) \5 y& k) D& a* u2 Z+ D
丢弃最高位,0补在最低位
* i2 `- c  `9 |6 ~. N; h% ?6 P左移一位相当于乘以2的1次方,左移n位相当于乘以2的n次方
8 B7 t! N/ m  K/ i例如:8<<28,即:8向左移动28位
, p# ^8 r& ^/ m1 b8 Y5 B与运算:1 & A = A ;可得出1跟任意数进行”与“运算不会改变其值
) \. l2 g2 I0 N( `# d3 y5 T; h# z( e5 N
STM32寄存器描述

6 g+ N# [9 i; g) @6 H# b3 R' VGPIOx_CRL寄存器,也就是低位寄存器。配置:Pin0—Pin7。图一如下:
; p  Y6 B# `" u/ W! }) ^1 Z/ C  b8 q/ o8 m' i) o9 \
8d0b99d571a841a0898e4f19d8fd4894.png 4 Z1 Z9 U# ]- Y6 ~' n3 A2 [' h

. ?1 a1 D7 w& a/ KGPIOx_CRH寄存器,也就是高位寄存器.配置:Pin8—Pin15。图二如下:* B5 T3 J, C1 W
$ A* y9 t; V) y8 `2 A* r, e# S
812f052b961547b4817ee64b743310f7.png / A: K( S& _8 N! @
6 w! [8 ]- i1 F
也就是一个GPIOx端口分为GPIOx_CRL寄存器和GPIOx_CRH寄存器,其中MODE0[1:0]和CNF7[1:0]一起表示Pin0的配置值,以下依此类推,MODE7[1:0]和CNF7[1:0]一起表示Pin7的配置值。( x( s4 ^/ A! B: C3 \8 _" |+ P

8 ]7 S: W, ^! G0 P# u( P
2、代码详解
& v7 x9 z) w$ s2 ]6 j( |" I对于文章开头提到的两个宏定义分开两条解释,SDA_IN()如下:$ F2 A+ `2 [2 A
6 r4 n/ u7 K. L3 |. h
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}9 E6 z& s, [& [' w+ P

0 H+ T& N" Y! f- J其中GPIOB->CRL&=0X0FFFFFFF 等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF0 ^+ f% D; [" [# H. i2 l0 m
含义为:由于上述提到的CRL为低位寄存器,意思是把GPIOB端口的CRL寄存器的28、29、30、31位清0,即将PB7中CNF7[1:0]和MODE[1:0]四位都置零。(这里应该还是蛮好理解的)! P0 j( C; P. R4 L
/ g0 s  c/ u# |# [" l
其中GPIOB->CRL|=(u32)8<<28等价于GPIOB->CRL = GPIOB->CRL | (u32)(8<<28)
0 U0 d- o4 d9 c; u# ?; Y由于u32强制类型转换为32位,则8的二进制为:0000 0000 0000 0000 0000 0000 0000 1000" p' n5 _3 f8 z5 l# l/ C1 Y
将8左移28位得:1000 0000 0000 0000 0000 0000 0000 0000
+ z2 w, ]8 `* _3 T) h- N由左移之后的数据可知:将31、30、29、28位设置为1000。下面对上图中的CNF和MODE解析- X0 C# W& t. B3 h% x5 q- Z1 v

5 M9 u$ E; b) I3 b% N6 M
即将PB的CRL寄存器中29和28位设置为00,由图一可知,其中29位MODE7[1]的值=0;28位MODE7[0]的值为0;图三如下:
' k( N8 X3 R5 m4 X( Y- r8 X1 G- E1 ]# B0 b7 r
: r( x8 d! V8 M( U" X6 x0 c
57bdb75cf48a484d836d20a6a31f7923.png $ a* a9 H7 ]( k
; |0 `) `+ e8 N7 C
由上图得知:29:28位配置为00,由下表得知,MODE1和MODE0为00时为输入模式。图四如下:5 h" C6 w3 w3 X. ?
( {; }/ |& x0 Z" Q+ \

; c! Z% d# {4 g baf0dd61a6b348b6a47dfd6ecc295fc4.png ; l6 n! M# j7 U: o8 o4 `
' C. O- ^4 Q, l) s/ G
接下来分析31:30位的值:10,由图一可知,其中31位CNF7[1]的值=1;30位CNF7[0]的值为0。图五如下:" }/ R1 K& O+ b7 v0 F

2 E9 i. A1 @* @- R( Y
56323f282da24b1dbd2150136a292c37.png
+ [6 p7 B, A& \6 i4 W+ J) m

; N3 Q. `" Q5 `4 \由29:28位得知:为输入模式,且31:30位的值为10,对照图四亦可得出,即为上下拉输入模式: x! ~2 W# s' j
SDA_OUT()如下:
' ]( c+ ?5 S" n. t, x1 s' ^3 x3 j* n

, k; j, x1 C' _  @6 }5 y#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
9 {) a1 W( s6 ^. b3 k! I, `* \9 @; A
其中(GPIOB->CRL) &= 0X0FFFFFFF等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF
/ j7 ~" g3 x( Z( d! d7 z$ K0 \其含义为:把PB端口的CRL寄存器的第28、29、30和31位清空,把GPIOB端口中的CNF7[1:0]和MODE7[1:0]置零( N7 R" _/ |6 q) [5 s1 [6 T
% ^$ f# g) [8 Q. P- y4 O
其中GPIOB->CRL |= (u32)3<<28 等价于 GPIOB->CRL = GPIOB->CRL | (u32)(3<<12)
& a, U$ _: N! n: H3转换为2进制为:0000 0000 0000 0000 0000 0000 0000 0011
. t0 b) o+ W8 f# D1 O/ ~将3左移28位得:0011 0000 0000 0000 0000 0000 0000 0000
+ z3 ?' x2 T/ c分析左移之后的数据为,将31、30、29、28位设置为00 11
( {5 G+ L+ r1 p7 \  c- EPB的CRL寄存器中29和28位设置为11,其中29位MODE7[1]的值=1;28位MODE7[0]的值为1。即为输出模式,最大速度为50Mhz。" r1 t- o4 B# O; v

4 `# S) \+ I( ?( R" s. v
bd0b6655f914488c8b083441edf707d0.png 9 I- a( T5 ^9 s, ?: |- r0 h" E
4 [% V( e1 b; W. z( l+ w: U/ D* G! c
PB的CRL寄存器中31和30位设置为00,其中31位CNF7[1]的值=0;30位CNF7[0]的值为0;由图五可知:通用推挽式输出模式。
; b$ _4 p, Z7 y/ T1 M( s————————————————6 w9 y" j3 [, e3 t. c" _
版权声明:枫华雪悦v" |' T/ {) e6 R2 u
如有侵权请联系删除
/ k" U' k9 p6 M( f* l- z! G, o5 u4 W/ ^' m, y7 m4 s

. B7 O7 V! ~  a
: t4 D9 {& n5 Q8 j4 S9 P
赞 收藏 评论0 发布时间:2023-5-22 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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