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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-22 20:00
  1. #define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
    " }; y* t/ f0 `
  2. #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}. g" ?. o. J/ U% p2 A) ?& Z
复制代码

0 s. G: C) K, v* m+ X
6 \( e9 x. O* s' c* T% I对于我们学的STM32都是习惯性的调用库函数,操作GPIO直接对结构体成员直接赋值即可。学到I2C通信时,看到以上代码中突如其来的寄存器操作,对于我这个新手小白来说是一脸懵逼状态,经过一个下午的学习,也算是搞懂了GPIO寄存器操作。分享一下个人学结,有错误的地方欢迎各路大佬指正。
4 T5 k. o3 G5 q! ?0 E0 }0 o2 I  P9 _6 v1 r

: ~# j- m) p5 b9 A/ X- u" d1 x1、所需基础知识回顾
  [) v8 s, L. `* d, S由参考手册可知,GPIO端口每个位可以由软件分别配置为:) `; @$ U) w# n% j! X9 R  k
输入浮空
) m( X9 v/ y7 F输入上拉) ~; z& z& Y, M& ]* l4 ~7 i
输入下拉: K5 z6 Q& q% V9 A( e
模拟输入
4 E$ ~- X  b4 o$ u推挽式输出" ~3 _+ e9 k3 {3 y' f
推挽式复用功能
+ {* D# E5 m' W  X开漏复用功能
( L: t0 [+ f5 I: u每个GPIO端口由七个寄存器来控制,分别为:) w# j5 k* _0 A- C' U! Y& X
端口配置低寄存器(GPIOx_CRL)
! W( m1 ~$ y' A. ?/ v端口配置高寄存器(GPIOx_CRH)
3 Z2 }: @! Z- S2 y& u  c* n端口输入数据寄存器(GPIOx_IDR)
, e1 P' ]: h+ J" F端口输出数据寄存器(GPIOx_ODR)6 }% i8 }. Z4 `8 J; s* I- v6 Q+ n
端口位设置/清除寄存器(GPIOx_BSRR)2 N: v1 Y, d; ^' _& l+ @
端口位清除数据寄存器(GPIOx_BRR)
) H3 X, `# M% B" k1 Y端口配置锁定寄存器(GPIOx_LCKR)
4 X4 w7 e5 j- o注:其中GPIOx_CRL配置GPIOx_Pin0——GPIOx_Pin7引脚,GPIOx_CRH配置GPIOx_Pin8——GPIOx_Pin15引脚(这个必须要明白)! \( V- X* k( h, {, @

4 s+ b8 c$ V& f# m. H
& P$ e/ i" `( Q/ \6 k) X& [
逻辑运算! J3 W4 h/ {0 ~7 t* k- \
左移运算( t0 E: u2 _3 o  J' H+ @
Value << num
2 e) M% s) W7 k" U$ c0 z1 V) gnum:指定要移位值Value移动的位数/ t9 s8 s' K/ b. W- d
丢弃最高位,0补在最低位- D- U/ ?/ S$ R" c2 E# ?: o: S
左移一位相当于乘以2的1次方,左移n位相当于乘以2的n次方
5 e; Y4 D% ~3 ~% L3 l例如:8<<28,即:8向左移动28位5 C& ^7 ?+ e0 B5 B8 L# o2 q
与运算:1 & A = A ;可得出1跟任意数进行”与“运算不会改变其值8 k; |) t- x1 {* L4 Z0 @* }
STM32寄存器描述
( s) K3 @! q3 z  F% B
GPIOx_CRL寄存器,也就是低位寄存器。配置:Pin0—Pin7。图一如下:( q$ V+ ~  j! v5 t+ ?7 h* _4 h
# i; \0 R" X' l7 O- i
8d0b99d571a841a0898e4f19d8fd4894.png
& Q2 j- M- r% R1 A: o% r- Z
8 w2 P* X! S1 w8 p6 |* \- {. X
GPIOx_CRH寄存器,也就是高位寄存器.配置:Pin8—Pin15。图二如下:2 Z: V8 B9 @& ~& b1 o) y" v
: u9 N  T$ f9 y+ h
812f052b961547b4817ee64b743310f7.png - b. C# W- a7 @+ ], p# r

4 W$ A4 H) x: j! ?6 g* K  I也就是一个GPIOx端口分为GPIOx_CRL寄存器和GPIOx_CRH寄存器,其中MODE0[1:0]和CNF7[1:0]一起表示Pin0的配置值,以下依此类推,MODE7[1:0]和CNF7[1:0]一起表示Pin7的配置值。
: U" T$ V! t7 x7 x& ~: n, P. Z/ a  j1 K. x1 Z1 b( d0 i1 }1 M
2、代码详解
2 _! w! _' C/ P" ?7 a& [对于文章开头提到的两个宏定义分开两条解释,SDA_IN()如下:
% a8 `% C: C+ |. o; J* w: W8 {8 z( R# o" f0 Z
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
. B2 o7 }8 ^8 D; D; Y* E- W3 T2 e0 d% z
其中GPIOB->CRL&=0X0FFFFFFF 等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF7 K1 z% ?% ^& }; e4 u
含义为:由于上述提到的CRL为低位寄存器,意思是把GPIOB端口的CRL寄存器的28、29、30、31位清0,即将PB7中CNF7[1:0]和MODE[1:0]四位都置零。(这里应该还是蛮好理解的)
1 u' [- j. k/ X, H) c$ k+ C& c
4 N! ?  J/ p# r' g* ]* S4 i$ @
其中GPIOB->CRL|=(u32)8<<28等价于GPIOB->CRL = GPIOB->CRL | (u32)(8<<28)1 @# e- ?# E9 n7 n$ o
由于u32强制类型转换为32位,则8的二进制为:0000 0000 0000 0000 0000 0000 0000 1000! J& ]1 B7 T5 U- m, ]' d6 T. {/ O
将8左移28位得:1000 0000 0000 0000 0000 0000 0000 0000
+ d3 U7 B% X7 O由左移之后的数据可知:将31、30、29、28位设置为1000。下面对上图中的CNF和MODE解析8 R/ J$ H& z) Q* W

. S5 ?+ Y3 `6 n+ ]7 @
即将PB的CRL寄存器中29和28位设置为00,由图一可知,其中29位MODE7[1]的值=0;28位MODE7[0]的值为0;图三如下:
8 c- f& t) N( K( _  Z) J, `& B4 [! E. f; m' ~
% X* p. f! D# h. z: q$ @; Z8 c
57bdb75cf48a484d836d20a6a31f7923.png - c: Z( c# y( c0 I0 G/ E/ W& Z
1 E6 k0 B* S4 r4 @0 k
由上图得知:29:28位配置为00,由下表得知,MODE1和MODE0为00时为输入模式。图四如下:
. Q' |9 o) _) T: e" m! r# {  F
% Z7 c) i' ]# x2 n; l1 I$ \% G1 V1 l( n; N
; F# l5 t( O* t" Z
baf0dd61a6b348b6a47dfd6ecc295fc4.png $ R. M# h& h( I3 A3 ~

8 W& @/ q2 s# b8 m! B
接下来分析31:30位的值:10,由图一可知,其中31位CNF7[1]的值=1;30位CNF7[0]的值为0。图五如下:- H1 m/ `7 U- W

/ z$ D3 r& P* ?- J4 W/ {
56323f282da24b1dbd2150136a292c37.png
+ W/ t  F4 d7 r* h
' B" p  ~$ r# m7 P3 @9 g
由29:28位得知:为输入模式,且31:30位的值为10,对照图四亦可得出,即为上下拉输入模式
* ?* u4 k7 v; u# A1 _" k: }SDA_OUT()如下:
- s* r2 N9 j+ S$ q$ ^, K

0 y. Z8 U8 o- H#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}( b! Q8 i3 ~& e: N

3 d/ r8 d6 K) ?, k6 K) q其中(GPIOB->CRL) &= 0X0FFFFFFF等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF
  ~5 @6 s4 l$ J其含义为:把PB端口的CRL寄存器的第28、29、30和31位清空,把GPIOB端口中的CNF7[1:0]和MODE7[1:0]置零
4 M: B( E1 T4 U9 _3 d8 f; C4 H8 A. R, J  S& r# u: q: h! E
其中GPIOB->CRL |= (u32)3<<28 等价于 GPIOB->CRL = GPIOB->CRL | (u32)(3<<12)5 D# G+ s( k$ h, O7 H. C. \
3转换为2进制为:0000 0000 0000 0000 0000 0000 0000 00114 o" t* i  t5 n$ b0 Y6 ]* C
将3左移28位得:0011 0000 0000 0000 0000 0000 0000 0000; b0 n1 {' c5 |$ H4 p
分析左移之后的数据为,将31、30、29、28位设置为00 11; B& \$ c6 H$ w* D, f  P- ]
PB的CRL寄存器中29和28位设置为11,其中29位MODE7[1]的值=1;28位MODE7[0]的值为1。即为输出模式,最大速度为50Mhz。
" N- D: a: c$ T- H+ s9 u
+ j: a- t) R' }/ Y& F
bd0b6655f914488c8b083441edf707d0.png # A) }# u6 D  ^: Q+ M4 `: H
9 u) `2 s/ L4 r+ T/ R
PB的CRL寄存器中31和30位设置为00,其中31位CNF7[1]的值=0;30位CNF7[0]的值为0;由图五可知:通用推挽式输出模式。
# u' [- ?4 O; G6 ?1 b# {) A& z————————————————) ], x0 v# C; ]7 N: u# R& F% j
版权声明:枫华雪悦v7 X! `5 z4 f) t7 {$ F/ g0 b
如有侵权请联系删除+ H' M: c( G- v; _

0 G: u/ [& s% g; m
; X% a, h& }7 N& D; R! q, Q. C
! I/ }/ D' N  W/ H
收藏 评论0 发布时间:2023-5-22 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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