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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-22 20:00
  1. #define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
    / h& V$ |  p: O! R7 H
  2. #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}* q% y0 Q5 K+ `6 @
复制代码
) n( B: k  m" t; [  L' [2 W; O
- e+ \" t1 n1 H0 `$ `
对于我们学的STM32都是习惯性的调用库函数,操作GPIO直接对结构体成员直接赋值即可。学到I2C通信时,看到以上代码中突如其来的寄存器操作,对于我这个新手小白来说是一脸懵逼状态,经过一个下午的学习,也算是搞懂了GPIO寄存器操作。分享一下个人学结,有错误的地方欢迎各路大佬指正。
* q6 w: P% |( g0 r8 s, P5 i# O$ ~. Q: [# q
6 N7 y( z8 b# z
1、所需基础知识回顾$ ~' D% Y/ t* T5 a
由参考手册可知,GPIO端口每个位可以由软件分别配置为:
. G( Q1 B9 Z2 \6 _输入浮空
3 H% B# @8 w3 h& H7 }* n输入上拉
4 I  e9 G# _6 b+ j8 H5 a, p输入下拉4 p; ~# f, X* f& d0 F& B1 F! Z2 y
模拟输入) V$ ]) N' ?9 {3 x
推挽式输出
! P# u% ?% i/ C% A推挽式复用功能
0 p- Z5 n' H4 j开漏复用功能
; I7 k. F& G, s每个GPIO端口由七个寄存器来控制,分别为:
" e0 ^% S  L% Q; l端口配置低寄存器(GPIOx_CRL)
3 ~8 {$ O1 ~! V( j( b端口配置高寄存器(GPIOx_CRH)
" ?5 T; }+ i- \% m6 X  J$ ]端口输入数据寄存器(GPIOx_IDR)9 d" l3 D8 `. I! j1 Y
端口输出数据寄存器(GPIOx_ODR)
5 S& X' i! p1 \2 d  Q端口位设置/清除寄存器(GPIOx_BSRR)
4 r# H5 ~* k- B, d: J7 f端口位清除数据寄存器(GPIOx_BRR)2 e* g! [( e# c/ t* w
端口配置锁定寄存器(GPIOx_LCKR)
. F* v7 [  G: K% M' T" H注:其中GPIOx_CRL配置GPIOx_Pin0——GPIOx_Pin7引脚,GPIOx_CRH配置GPIOx_Pin8——GPIOx_Pin15引脚(这个必须要明白)
7 r" a, ~- R: J. j. M7 T
4 ~% ]( H' Y7 f0 y8 H
3 `1 _8 s; {- x8 E1 H
逻辑运算
( T3 X/ a- m" }8 N& v' R左移运算1 _, R8 A, N% u( O/ J- v
Value << num
, T4 ~0 O- b; U" W% }" f3 Wnum:指定要移位值Value移动的位数* y8 I' R. {  ]& ?
丢弃最高位,0补在最低位
2 z& i' x' F9 t. N5 ?; }3 Q左移一位相当于乘以2的1次方,左移n位相当于乘以2的n次方5 u) Q4 C; ?' \) J% C) C
例如:8<<28,即:8向左移动28位" ~, w' [# |% Y. v+ g
与运算:1 & A = A ;可得出1跟任意数进行”与“运算不会改变其值7 _( q) k4 `, [  g3 b, o1 V5 f
STM32寄存器描述
0 _' h/ K0 p( _% i0 s" ]
GPIOx_CRL寄存器,也就是低位寄存器。配置:Pin0—Pin7。图一如下:3 P) g4 d. T$ c3 y" K( q5 U

/ q) N' P7 f/ Z3 P7 l" f- K3 |: x
8d0b99d571a841a0898e4f19d8fd4894.png
* p2 c7 Y  T% R5 q- F4 ]& s

5 T: j1 P( _- W& O4 |GPIOx_CRH寄存器,也就是高位寄存器.配置:Pin8—Pin15。图二如下:' i; r7 Y, o  O1 ?6 U7 `8 Z

/ h! K4 S: e4 d) {" t
812f052b961547b4817ee64b743310f7.png
5 `$ l7 I- |+ l9 h6 e$ Q
& _9 p) E3 M# i: Z
也就是一个GPIOx端口分为GPIOx_CRL寄存器和GPIOx_CRH寄存器,其中MODE0[1:0]和CNF7[1:0]一起表示Pin0的配置值,以下依此类推,MODE7[1:0]和CNF7[1:0]一起表示Pin7的配置值。
, B5 O. f+ t' d+ z% b/ v( E9 @6 C1 p9 L: I, B  p3 u
2、代码详解
( ?6 i2 A: Q- i6 n4 X+ A对于文章开头提到的两个宏定义分开两条解释,SDA_IN()如下:( O- V& E+ Q  i7 ~; c" S8 Q! J) T

. a0 T+ E, J4 ?4 q2 D7 d#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
- ]" h) B+ \. z+ h: o4 [8 t! E3 y' M) t8 r' n
其中GPIOB->CRL&=0X0FFFFFFF 等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF! u5 R$ S, E7 Z) H+ k8 o
含义为:由于上述提到的CRL为低位寄存器,意思是把GPIOB端口的CRL寄存器的28、29、30、31位清0,即将PB7中CNF7[1:0]和MODE[1:0]四位都置零。(这里应该还是蛮好理解的)% W* x/ D, w) G9 U3 i
6 H% y: _: E/ L# \& f
其中GPIOB->CRL|=(u32)8<<28等价于GPIOB->CRL = GPIOB->CRL | (u32)(8<<28)$ c0 m/ Y+ b$ J$ E( G0 I' m3 }0 f
由于u32强制类型转换为32位,则8的二进制为:0000 0000 0000 0000 0000 0000 0000 1000
8 X& ?  h$ U; N. t, I将8左移28位得:1000 0000 0000 0000 0000 0000 0000 0000
9 B" \/ O: B( H$ Q4 E; u由左移之后的数据可知:将31、30、29、28位设置为1000。下面对上图中的CNF和MODE解析( D+ ]5 v. l4 U  q
2 Q( n9 I: f4 n2 \; z. w" }
即将PB的CRL寄存器中29和28位设置为00,由图一可知,其中29位MODE7[1]的值=0;28位MODE7[0]的值为0;图三如下:0 o" ~9 b! C% U4 z

; j( Q4 W8 F4 ~+ l* l) R5 i

4 x: `6 v+ [, a# b9 E 57bdb75cf48a484d836d20a6a31f7923.png
7 s/ T1 _2 C+ g8 Z8 g6 {, T
% p1 }9 ]4 D, f- y& X" R$ p+ ~
由上图得知:29:28位配置为00,由下表得知,MODE1和MODE0为00时为输入模式。图四如下:
, p. m8 s+ l* ~  K+ j$ i" x- R9 }( p% p. Q$ Z+ G5 D* j9 _; f  d& [% {4 I

0 g! @/ f+ d) @! |6 c2 I5 k! o baf0dd61a6b348b6a47dfd6ecc295fc4.png - U1 f: d9 m3 j0 Z% n; u
3 R/ _* Y  ^  d4 \8 R# v! g
接下来分析31:30位的值:10,由图一可知,其中31位CNF7[1]的值=1;30位CNF7[0]的值为0。图五如下:
0 r1 l  F5 {' [( [2 d" n* I0 W8 E! }6 N/ ]
56323f282da24b1dbd2150136a292c37.png ' g' ?; H$ E0 E9 Q5 s6 A& f. `
; k) w/ Y' G% a- _( Z
由29:28位得知:为输入模式,且31:30位的值为10,对照图四亦可得出,即为上下拉输入模式
- ~* n7 h( R" D. ^& kSDA_OUT()如下:8 w5 j4 f3 g( S) C

4 L; F2 h1 M3 X6 l) W! t: _1 l#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}0 b- @' {% `4 M+ B1 C( \2 d5 [
0 G8 E0 D$ R) ~: h2 O
其中(GPIOB->CRL) &= 0X0FFFFFFF等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF7 n' w9 J5 T& }+ }2 z
其含义为:把PB端口的CRL寄存器的第28、29、30和31位清空,把GPIOB端口中的CNF7[1:0]和MODE7[1:0]置零
% z4 K/ e! M0 o% k8 ^& w
' b6 H, R& O% h1 {" h
其中GPIOB->CRL |= (u32)3<<28 等价于 GPIOB->CRL = GPIOB->CRL | (u32)(3<<12)( v  e$ D. S6 y2 ~7 M& N
3转换为2进制为:0000 0000 0000 0000 0000 0000 0000 0011
# I7 ~2 u: S0 M" |# n) a4 w将3左移28位得:0011 0000 0000 0000 0000 0000 0000 0000
* P6 G2 I% s3 t! I" N- o# n分析左移之后的数据为,将31、30、29、28位设置为00 11- a4 k( J1 M2 `) A
PB的CRL寄存器中29和28位设置为11,其中29位MODE7[1]的值=1;28位MODE7[0]的值为1。即为输出模式,最大速度为50Mhz。4 I) i- u' G: z( ^9 @
6 R8 Z, {  U: T* P
bd0b6655f914488c8b083441edf707d0.png
5 o, i* N; W3 f
6 U4 d3 q. n0 y4 ?6 V+ U, F
PB的CRL寄存器中31和30位设置为00,其中31位CNF7[1]的值=0;30位CNF7[0]的值为0;由图五可知:通用推挽式输出模式。# B4 @& p* [: w+ ~# d
————————————————; n' s" N1 m8 U1 d! H+ {
版权声明:枫华雪悦v
/ S/ V4 K3 [; V( m, L" z; H' ]如有侵权请联系删除1 e/ ~! a$ t/ D2 c' Y, y& b( x% S" A
; {  ~1 h+ z$ f. A

5 y& n4 ^: `" R# ^  \5 L/ J" K- x, s7 N* M
收藏 评论0 发布时间:2023-5-22 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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