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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-22 20:00
  1. #define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}- |6 v7 ~& ~& ]- t8 l0 v) G
  2. #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}$ G& i& T/ S4 G7 q% y5 m5 v
复制代码
5 P( D, _8 i, J6 y! y2 ^
6 Z3 M+ d. V3 Z+ ]0 S) F
对于我们学的STM32都是习惯性的调用库函数,操作GPIO直接对结构体成员直接赋值即可。学到I2C通信时,看到以上代码中突如其来的寄存器操作,对于我这个新手小白来说是一脸懵逼状态,经过一个下午的学习,也算是搞懂了GPIO寄存器操作。分享一下个人学结,有错误的地方欢迎各路大佬指正。
0 x0 }+ Y) r0 l3 z; Z6 I/ l9 g
8 O0 m" k. @3 t2 y/ _- U
; V3 G3 c' Z( v1 F# S0 ~9 o+ \$ v
1、所需基础知识回顾
7 h# r# L7 P- e% t) X" ^9 E由参考手册可知,GPIO端口每个位可以由软件分别配置为:
  M$ @( n+ i# V* r输入浮空$ g* @7 w/ z/ d5 z
输入上拉; {+ e, h" f* l  t1 }5 s* X
输入下拉& l- G$ Q+ ?7 G3 L  g
模拟输入
( l! ]  S/ f# f. ~* d推挽式输出/ d- G9 n" C, K4 U4 A" U
推挽式复用功能: K# ^7 S% l) G7 A
开漏复用功能
. J! o: m* s  W+ x- }0 K- Z4 `每个GPIO端口由七个寄存器来控制,分别为:' v  z( y% w, z5 r* q# A5 X9 X
端口配置低寄存器(GPIOx_CRL): S6 {, x1 _+ A
端口配置高寄存器(GPIOx_CRH)  K: {. }  M; j
端口输入数据寄存器(GPIOx_IDR)  U1 L0 |  N$ j. \/ Y
端口输出数据寄存器(GPIOx_ODR), b1 T! F5 ^/ {; E0 X# r  S8 R. Y
端口位设置/清除寄存器(GPIOx_BSRR)
  r6 R+ R) {( b; U  r8 f端口位清除数据寄存器(GPIOx_BRR)
, h* ~% e+ U5 n# v. i端口配置锁定寄存器(GPIOx_LCKR): t* Z& |6 z/ V
注:其中GPIOx_CRL配置GPIOx_Pin0——GPIOx_Pin7引脚,GPIOx_CRH配置GPIOx_Pin8——GPIOx_Pin15引脚(这个必须要明白)
0 w8 @4 f  K/ e! n& v5 I, D9 c: Q' Z; l2 G2 `4 \% a/ i, W$ J4 S
5 c7 F0 [3 A- x. a% U; Z- o
逻辑运算( U! W8 G0 Y9 P8 P) J
左移运算
; c8 `: R+ j0 V. ~% T& d- A2 k: TValue << num
, j, g$ ]9 w9 E- F- y* l" }num:指定要移位值Value移动的位数
/ L8 I2 U% s& j9 n2 e. g' R; J丢弃最高位,0补在最低位0 g6 N- ^2 k0 ~/ ^% {
左移一位相当于乘以2的1次方,左移n位相当于乘以2的n次方* c. {5 _: k' S) s1 z, [
例如:8<<28,即:8向左移动28位
( {3 C& k2 C. `5 e与运算:1 & A = A ;可得出1跟任意数进行”与“运算不会改变其值; Q8 y8 D' L* h
STM32寄存器描述
9 C$ C1 z. C; e1 h
GPIOx_CRL寄存器,也就是低位寄存器。配置:Pin0—Pin7。图一如下:
2 h: P! A  e* \3 [
, x7 B8 T$ O2 m9 [  _# p
8d0b99d571a841a0898e4f19d8fd4894.png   O# L( c  @5 h8 j1 p! m- x0 u' q

9 p. c- _0 z$ [* @GPIOx_CRH寄存器,也就是高位寄存器.配置:Pin8—Pin15。图二如下:
' @, ?0 i0 [/ ]' f% Q4 a* E' I* e8 @6 }; `& r
812f052b961547b4817ee64b743310f7.png % v: ?5 Y) T) z$ G4 P  \0 I

, G6 h# Z9 @& g. P- J也就是一个GPIOx端口分为GPIOx_CRL寄存器和GPIOx_CRH寄存器,其中MODE0[1:0]和CNF7[1:0]一起表示Pin0的配置值,以下依此类推,MODE7[1:0]和CNF7[1:0]一起表示Pin7的配置值。; @) Q6 o. k+ `$ O% G! M/ B( I/ V! x

" m+ T+ y( b* f# h( `( X  y1 P
2、代码详解9 u/ \' {5 d9 I/ x% [
对于文章开头提到的两个宏定义分开两条解释,SDA_IN()如下:+ \- S+ \% Q1 n( N) a' l8 {
& b+ E- h. S1 c2 S
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
, \% ]- N- |8 {( x6 }
8 V. G) j$ W( _. N( y9 _! j其中GPIOB->CRL&=0X0FFFFFFF 等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF0 T* S1 h7 ~( O  G
含义为:由于上述提到的CRL为低位寄存器,意思是把GPIOB端口的CRL寄存器的28、29、30、31位清0,即将PB7中CNF7[1:0]和MODE[1:0]四位都置零。(这里应该还是蛮好理解的)
' ~# x- U) W5 |! V0 |$ b  ^# ?) i# R: a5 U/ _2 Y1 H4 y9 B
其中GPIOB->CRL|=(u32)8<<28等价于GPIOB->CRL = GPIOB->CRL | (u32)(8<<28)
: m' \+ y) V9 _1 A) R* k5 t' s由于u32强制类型转换为32位,则8的二进制为:0000 0000 0000 0000 0000 0000 0000 1000
% J6 _4 A. y  D0 R( i8 t' l/ \( ?6 V将8左移28位得:1000 0000 0000 0000 0000 0000 0000 0000
2 B! Q9 X3 c  j- m由左移之后的数据可知:将31、30、29、28位设置为1000。下面对上图中的CNF和MODE解析
& X8 C9 _( ^( ~4 A: ~1 V- c& F/ [- \2 x2 B1 e
即将PB的CRL寄存器中29和28位设置为00,由图一可知,其中29位MODE7[1]的值=0;28位MODE7[0]的值为0;图三如下:
" w+ f* S0 [/ x( Z( R7 Q) d1 x( j* p3 G) T

8 V' f% J4 p+ n 57bdb75cf48a484d836d20a6a31f7923.png ) [/ i8 [7 T+ W7 W* p9 a

7 S' T* V9 ]# ], [& Y: l! X9 f
由上图得知:29:28位配置为00,由下表得知,MODE1和MODE0为00时为输入模式。图四如下:/ \2 e) Z  E/ o5 I) ~/ c
( ?: T3 a+ T. S3 |. y4 f
! u5 \9 `$ f; c- \
baf0dd61a6b348b6a47dfd6ecc295fc4.png 3 O+ W2 F/ M* I5 f2 Y, F7 L+ F
1 f! A: l+ R. a1 q
接下来分析31:30位的值:10,由图一可知,其中31位CNF7[1]的值=1;30位CNF7[0]的值为0。图五如下:$ k: u7 E1 r5 m  O- |+ i  V$ y
5 ^6 c4 i5 r3 V% @8 q
56323f282da24b1dbd2150136a292c37.png
. s/ ]' k; u. m7 K( l
$ Q/ Z; Q( h4 p6 f5 R2 d
由29:28位得知:为输入模式,且31:30位的值为10,对照图四亦可得出,即为上下拉输入模式
' M- k; E, B: G. `SDA_OUT()如下:
# R8 f; R3 j5 ^6 Z- i; c

. Z- y2 o5 c7 P1 e' z#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}" Y" z6 [, f) l
% w' Y! Q' W5 B/ q/ f
其中(GPIOB->CRL) &= 0X0FFFFFFF等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF, |2 o- A& w: g& P% M* e6 w# U/ t& A* ~  \
其含义为:把PB端口的CRL寄存器的第28、29、30和31位清空,把GPIOB端口中的CNF7[1:0]和MODE7[1:0]置零
9 i/ K1 Q; |2 g' `
6 Y; Y! c0 ?5 p+ c! u3 }. s
其中GPIOB->CRL |= (u32)3<<28 等价于 GPIOB->CRL = GPIOB->CRL | (u32)(3<<12)! b6 y! W1 d5 m- v2 i+ v! i1 P, x
3转换为2进制为:0000 0000 0000 0000 0000 0000 0000 0011. [& w. Z; @# `) \! S# n& d
将3左移28位得:0011 0000 0000 0000 0000 0000 0000 0000
( `3 |5 u3 r+ n) q9 \" q: p6 {分析左移之后的数据为,将31、30、29、28位设置为00 11" z9 ]# I7 |* Y& e/ H5 D
PB的CRL寄存器中29和28位设置为11,其中29位MODE7[1]的值=1;28位MODE7[0]的值为1。即为输出模式,最大速度为50Mhz。, a3 F  k0 T# _3 q
0 E- ?* f8 _5 t- M
bd0b6655f914488c8b083441edf707d0.png
# M. i0 r  g6 f* w* i

5 X3 B* @' ?' |; H5 \) `8 CPB的CRL寄存器中31和30位设置为00,其中31位CNF7[1]的值=0;30位CNF7[0]的值为0;由图五可知:通用推挽式输出模式。
5 m( R; Q2 r7 }  M, k————————————————
0 d2 G* R' @+ I版权声明:枫华雪悦v
* A, l) `) s; S+ E# |5 b: d: q如有侵权请联系删除
' J4 I. T6 @  I- {& F) [2 [* t# R! K4 ]3 H! _( h6 S. z" w/ \: ^. y

. i7 F+ W  t2 X
* @' ^; u0 l5 R2 N% k  o
赞 收藏 评论0 发布时间:2023-5-22 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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