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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-22 20:00
  1. #define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
    ; J/ R  E# d* ?5 l
  2. #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}+ x0 ]* K& a: T
复制代码
) j& i, d1 R/ S5 H  Q0 y1 m8 x/ {
- R3 Y/ y! P6 `1 T' [" V: T
对于我们学的STM32都是习惯性的调用库函数,操作GPIO直接对结构体成员直接赋值即可。学到I2C通信时,看到以上代码中突如其来的寄存器操作,对于我这个新手小白来说是一脸懵逼状态,经过一个下午的学习,也算是搞懂了GPIO寄存器操作。分享一下个人学结,有错误的地方欢迎各路大佬指正。% O4 F) t4 O& Y

& O, Y0 G" L! {: c; P

) L$ E4 S; O. w4 f7 i7 @. w) x1 r4 f2 Y1、所需基础知识回顾2 S- [+ J" g! t" Y' F4 [
由参考手册可知,GPIO端口每个位可以由软件分别配置为:
' _! \: B2 r5 V5 a5 k+ T* T输入浮空
+ k3 H1 ?( U; w8 s, _输入上拉
' g; N4 G* T( m, S; n3 j1 M输入下拉
$ n- T6 D+ h# }. {5 A" n, V模拟输入  G, S  m; l- X
推挽式输出
0 y" e5 O5 H. ?! b* G推挽式复用功能
0 q5 x: z: e  @5 X- a' }+ G, ~% E" V! B开漏复用功能
9 j. `. n6 |/ p/ @9 [每个GPIO端口由七个寄存器来控制,分别为:
3 h& E6 F# T1 a6 o. Q& \端口配置低寄存器(GPIOx_CRL)
7 @; C8 {+ h& d( F) p: c2 ~6 g7 [端口配置高寄存器(GPIOx_CRH)
0 V4 O& `$ Z0 u4 y: C端口输入数据寄存器(GPIOx_IDR)
( S+ u5 G; \5 y2 t3 L$ r4 }; d端口输出数据寄存器(GPIOx_ODR)0 ^& j* j; t8 O8 `; m
端口位设置/清除寄存器(GPIOx_BSRR)
& h1 \+ t$ w: p+ [端口位清除数据寄存器(GPIOx_BRR)( v8 r5 f8 i3 q$ N( b* R
端口配置锁定寄存器(GPIOx_LCKR)
' k4 h7 a4 Y3 I+ L/ Y注:其中GPIOx_CRL配置GPIOx_Pin0——GPIOx_Pin7引脚,GPIOx_CRH配置GPIOx_Pin8——GPIOx_Pin15引脚(这个必须要明白)
( R; f$ C$ D. K. @5 |, I% Z
+ f2 V+ }# f9 Z

2 V' Q" X! \) t6 u逻辑运算
0 E7 Z( p2 ^( F, v9 k% i7 t: ~/ o左移运算
: b- M3 w2 n. ]( ?! RValue << num/ i& ?( z) Q  F. Q2 {* t* \. P' |$ l
num:指定要移位值Value移动的位数& X' n1 e3 q- V/ r* [
丢弃最高位,0补在最低位
+ f0 U3 i5 u3 [7 W左移一位相当于乘以2的1次方,左移n位相当于乘以2的n次方  s( L7 j4 @- D! V8 z
例如:8<<28,即:8向左移动28位& r8 C7 |2 E8 O0 b- p+ l& p
与运算:1 & A = A ;可得出1跟任意数进行”与“运算不会改变其值
; w* l% Z0 X4 O; |( W. j, Q
STM32寄存器描述
* z0 E# K4 {$ F" |
GPIOx_CRL寄存器,也就是低位寄存器。配置:Pin0—Pin7。图一如下:
/ i* X9 p$ b& P% e( x
  w7 d9 @* K' D* Z3 N+ ]
8d0b99d571a841a0898e4f19d8fd4894.png + q2 I; w# A" N/ Z

4 M; k- p' p$ D; E. kGPIOx_CRH寄存器,也就是高位寄存器.配置:Pin8—Pin15。图二如下:/ k* I1 p, `3 N; W3 x- u

1 L) I- O. t$ k  A/ F
812f052b961547b4817ee64b743310f7.png ( v0 H8 r& p+ Z: Q# e
$ J" I2 ^7 ~2 e9 V
也就是一个GPIOx端口分为GPIOx_CRL寄存器和GPIOx_CRH寄存器,其中MODE0[1:0]和CNF7[1:0]一起表示Pin0的配置值,以下依此类推,MODE7[1:0]和CNF7[1:0]一起表示Pin7的配置值。/ R1 b& I, O0 j) o7 u
8 S* z+ B4 r$ |) C$ K( d3 ]- J1 q, K
2、代码详解
; D$ g% E! u1 v4 Z2 S1 |对于文章开头提到的两个宏定义分开两条解释,SDA_IN()如下:% }  K4 C% G8 J

6 h/ u( K  i8 P) s* _#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
* j9 N( T% A+ X7 n% s- @
) Y7 N9 v8 U. {6 a7 e( o* R其中GPIOB->CRL&=0X0FFFFFFF 等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF" c( t; H# t( y- q- j% t
含义为:由于上述提到的CRL为低位寄存器,意思是把GPIOB端口的CRL寄存器的28、29、30、31位清0,即将PB7中CNF7[1:0]和MODE[1:0]四位都置零。(这里应该还是蛮好理解的)- t) X- l: S( [+ g, l, H

9 O) J& u6 W3 s& v
其中GPIOB->CRL|=(u32)8<<28等价于GPIOB->CRL = GPIOB->CRL | (u32)(8<<28); o7 D7 B" d6 d6 f2 e* j  H
由于u32强制类型转换为32位,则8的二进制为:0000 0000 0000 0000 0000 0000 0000 1000
4 l0 ]* G2 ?. u' s& O! L6 g+ k将8左移28位得:1000 0000 0000 0000 0000 0000 0000 0000
% n$ |2 v& }, h6 N3 V! J( l4 N: r由左移之后的数据可知:将31、30、29、28位设置为1000。下面对上图中的CNF和MODE解析
' u3 p2 U* b3 h. n$ ~2 A! [
; j- R0 X1 C! m, d, W1 e
即将PB的CRL寄存器中29和28位设置为00,由图一可知,其中29位MODE7[1]的值=0;28位MODE7[0]的值为0;图三如下:
# {) g1 H) X- I3 \3 P3 b( k6 ~  {9 Q) A7 ]

0 h( {, [( J* @$ a 57bdb75cf48a484d836d20a6a31f7923.png
9 z9 y" m9 X, d+ p& k4 z9 o7 @6 H
; a; w* ]1 a) g5 m
由上图得知:29:28位配置为00,由下表得知,MODE1和MODE0为00时为输入模式。图四如下:. J8 u: J- [" _" u" o
' `+ h9 m, `) ^. m/ ~
8 C" ~  A2 d" B9 S5 }3 O6 S( @
baf0dd61a6b348b6a47dfd6ecc295fc4.png : M* Y1 V- A* B6 Z8 w% ]
0 H1 Y; |; @5 }& b) _
接下来分析31:30位的值:10,由图一可知,其中31位CNF7[1]的值=1;30位CNF7[0]的值为0。图五如下:
: o2 @" W$ I3 f  b: i6 e9 ~7 H. p  L# B
56323f282da24b1dbd2150136a292c37.png
! T7 Y& Q  h3 l, \. b6 J* r, h
( V* g6 C# q( B. `
由29:28位得知:为输入模式,且31:30位的值为10,对照图四亦可得出,即为上下拉输入模式3 [+ I- H/ |* B% @* s
SDA_OUT()如下:
7 V7 O$ t) p! V- Q) V. ]
2 h3 x' O! {+ v
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}" L2 ^0 M8 c; j; C* D; [

6 k2 L& l( |& Y$ o) \" x  D其中(GPIOB->CRL) &= 0X0FFFFFFF等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF
/ e" w  H$ h+ k( J5 ?  s4 d" a其含义为:把PB端口的CRL寄存器的第28、29、30和31位清空,把GPIOB端口中的CNF7[1:0]和MODE7[1:0]置零7 H$ n7 q3 d. g% f5 p/ B
) n7 s. {7 t3 D
其中GPIOB->CRL |= (u32)3<<28 等价于 GPIOB->CRL = GPIOB->CRL | (u32)(3<<12)
3 ^7 B( H0 P. J( ?% {( [. ^6 h3转换为2进制为:0000 0000 0000 0000 0000 0000 0000 00113 t! h" E8 j5 a. N/ F
将3左移28位得:0011 0000 0000 0000 0000 0000 0000 00008 G3 B9 H- G4 ^, {6 H# \. P
分析左移之后的数据为,将31、30、29、28位设置为00 11
/ x8 ?, E' k$ H: e( dPB的CRL寄存器中29和28位设置为11,其中29位MODE7[1]的值=1;28位MODE7[0]的值为1。即为输出模式,最大速度为50Mhz。; n# J5 w: J" a$ \6 T! ^

# `& b4 z# l. ]8 ^  y5 R$ H8 x
bd0b6655f914488c8b083441edf707d0.png
. ^4 [  U  {  I/ z2 ]
) [  O. ~! s8 P8 {" ]
PB的CRL寄存器中31和30位设置为00,其中31位CNF7[1]的值=0;30位CNF7[0]的值为0;由图五可知:通用推挽式输出模式。- G# q, j) a2 {0 ]6 s
————————————————
2 C# u& k0 S0 X7 S0 C+ x版权声明:枫华雪悦v
2 c, ^2 q( y$ b( `! \, l4 w4 W1 d9 H如有侵权请联系删除
% k0 k# ^2 m/ W9 c' ]) _, |5 V( W  p" m8 p! m

# O; q4 [& u4 k$ p2 Q1 j* P; o, o: m' W: I6 ^
收藏 评论0 发布时间:2023-5-22 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
STM32N6 AI生态系统
STM32MCU,MPU高性能GUI
ST ACEPACK电源模块
意法半导体生物传感器
STM32Cube扩展软件包
关注我们
st-img 微信公众号
st-img 手机版