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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-22 20:00
  1. #define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}
    . g7 L# s; U1 A2 X( `' C! i
  2. #define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
    # Y0 W4 l0 W; X) ]
复制代码

4 _/ r2 T, m- `2 V( [
- q) J: a' e1 S$ B7 i对于我们学的STM32都是习惯性的调用库函数,操作GPIO直接对结构体成员直接赋值即可。学到I2C通信时,看到以上代码中突如其来的寄存器操作,对于我这个新手小白来说是一脸懵逼状态,经过一个下午的学习,也算是搞懂了GPIO寄存器操作。分享一下个人学结,有错误的地方欢迎各路大佬指正。
+ w  D& O% `- `. _! I1 f6 ^; m: ?
# T: ]' k( D! z3 k# r; F
4 E7 ^/ k- O- a* ?" D# n
1、所需基础知识回顾
2 I/ g9 N+ ^3 T  V, U由参考手册可知,GPIO端口每个位可以由软件分别配置为:1 E+ Q9 n. T, U. b1 E1 p2 r" y# _( b* u
输入浮空
" r! X! {0 Q' x  u( Z$ M. x: L: i输入上拉" U- W# W  t" t# P( G
输入下拉3 x. R6 K- U* s. ^: h
模拟输入
: V6 K$ Y$ `( I3 }推挽式输出
6 u8 g% l. C" }! y& p  a/ z( z推挽式复用功能
% ]% h9 \, t5 j" @开漏复用功能# E- y7 `6 u# z9 v, A
每个GPIO端口由七个寄存器来控制,分别为:+ _# u& V) T& y2 ]' R) F: g
端口配置低寄存器(GPIOx_CRL), n1 K) O2 m$ V( N
端口配置高寄存器(GPIOx_CRH)
2 q8 X( ?6 a4 c/ F端口输入数据寄存器(GPIOx_IDR)
. O5 @) y0 i2 C' R  x& p- X端口输出数据寄存器(GPIOx_ODR)
9 r( K# U2 w$ h, W! A端口位设置/清除寄存器(GPIOx_BSRR)1 O2 H. ]6 C6 T+ l' b
端口位清除数据寄存器(GPIOx_BRR)
- O- m6 \) W- u  I, l0 z! }" D端口配置锁定寄存器(GPIOx_LCKR)# a, s0 `. b" g2 u+ \3 L* d2 Q( e
注:其中GPIOx_CRL配置GPIOx_Pin0——GPIOx_Pin7引脚,GPIOx_CRH配置GPIOx_Pin8——GPIOx_Pin15引脚(这个必须要明白)
! f) Q7 N/ q" V. k& r% r7 O! F4 C( D% ]( a9 Z5 ]8 k  j2 L8 r
8 o6 b; R/ X! J" R  c
逻辑运算6 ?9 r  S8 q* K
左移运算/ m' f8 E; Y/ I7 R: P# N9 {; r4 ?
Value << num8 i+ R$ y+ ?6 ~. M0 q5 q' U
num:指定要移位值Value移动的位数) y$ X! w5 M, m- Y/ ]& J- }
丢弃最高位,0补在最低位
9 G+ d- d3 D$ `2 n' V5 [1 o% m左移一位相当于乘以2的1次方,左移n位相当于乘以2的n次方/ N" H! D& ?' G
例如:8<<28,即:8向左移动28位
1 H/ Q* @/ W2 s+ L7 u, R与运算:1 & A = A ;可得出1跟任意数进行”与“运算不会改变其值5 V- _2 {* r& @% G) C0 K+ _
STM32寄存器描述

+ x8 G) m- ~- Y5 D+ rGPIOx_CRL寄存器,也就是低位寄存器。配置:Pin0—Pin7。图一如下:
, f2 R) H! U- H+ m: B  }/ X3 z4 e5 ]+ p+ h( Z# J
8d0b99d571a841a0898e4f19d8fd4894.png , Y9 I$ d0 }' m, J( o4 `
# `6 a% B& `# A; _4 ~) V. x6 q
GPIOx_CRH寄存器,也就是高位寄存器.配置:Pin8—Pin15。图二如下:
0 i7 @& p5 @/ ^+ G( A" d/ T% v' n! n
812f052b961547b4817ee64b743310f7.png
" W9 k4 n( ^5 a
; y0 L4 J0 O2 C0 |( B0 _
也就是一个GPIOx端口分为GPIOx_CRL寄存器和GPIOx_CRH寄存器,其中MODE0[1:0]和CNF7[1:0]一起表示Pin0的配置值,以下依此类推,MODE7[1:0]和CNF7[1:0]一起表示Pin7的配置值。6 W7 Z/ `# G7 _6 |0 M
( i6 l) ^2 m# \
2、代码详解
3 _& D9 }/ N& H' I2 u! v( r5 G对于文章开头提到的两个宏定义分开两条解释,SDA_IN()如下:
4 }. ^+ D8 q4 L7 N) w: R1 {+ G' C( w( ?
#define SDA_IN()  {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)8<<28;}" F& J) M/ |6 s% x& d& V. Y

5 }% E& B5 I3 ~5 A" ^其中GPIOB->CRL&=0X0FFFFFFF 等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF
9 @( {5 W# d+ o! p3 J7 ]/ j含义为:由于上述提到的CRL为低位寄存器,意思是把GPIOB端口的CRL寄存器的28、29、30、31位清0,即将PB7中CNF7[1:0]和MODE[1:0]四位都置零。(这里应该还是蛮好理解的)) m& U+ D: }7 Y" u7 n: S6 a
( |# j- y& r" \& Z
其中GPIOB->CRL|=(u32)8<<28等价于GPIOB->CRL = GPIOB->CRL | (u32)(8<<28)% x0 P1 ]) k& ?4 B2 R
由于u32强制类型转换为32位,则8的二进制为:0000 0000 0000 0000 0000 0000 0000 1000
3 e/ Q: p/ Z2 T" [* E% Q将8左移28位得:1000 0000 0000 0000 0000 0000 0000 0000
2 g( N3 j, W0 U% k# O8 h9 C3 v$ o' F由左移之后的数据可知:将31、30、29、28位设置为1000。下面对上图中的CNF和MODE解析
  @: ^, ^2 t$ W; a* W/ l/ T2 i' T& Z+ D7 O4 }
即将PB的CRL寄存器中29和28位设置为00,由图一可知,其中29位MODE7[1]的值=0;28位MODE7[0]的值为0;图三如下:6 c; l0 I' V! k# ^
$ O% v* Q. _6 S( G3 I* r$ q) W

# z! ?6 _, |+ a0 C; d) P% z/ w2 B( K) f 57bdb75cf48a484d836d20a6a31f7923.png
9 W& ]/ k& N3 t. Y: v: p+ Z9 ]2 J, F
. Y, F  n: ?/ l, C% @
由上图得知:29:28位配置为00,由下表得知,MODE1和MODE0为00时为输入模式。图四如下:
8 A% R- ^  H( o
+ p9 V: M2 o* m+ H

- |0 k% x" \( x. E& n0 A/ k+ o baf0dd61a6b348b6a47dfd6ecc295fc4.png
6 ]4 a* O, @2 Q+ k8 q8 j& m' `7 T9 ^/ n0 [: G
接下来分析31:30位的值:10,由图一可知,其中31位CNF7[1]的值=1;30位CNF7[0]的值为0。图五如下:" |( q) G+ ^( c$ C

- [( k* t0 N% f8 z  Y& V' n
56323f282da24b1dbd2150136a292c37.png 0 ]. H8 ~8 \8 _& `, T7 Q  t1 Z- }5 |" Q

  R5 w  w! t: i9 }" A5 Q8 D由29:28位得知:为输入模式,且31:30位的值为10,对照图四亦可得出,即为上下拉输入模式6 R2 \2 R4 B% b  N4 U0 j
SDA_OUT()如下:0 W1 W; ]" @" W& S$ _
  t9 e/ u" H- q" d
#define SDA_OUT() {GPIOB->CRL&=0X0FFFFFFF;GPIOB->CRL|=(u32)3<<28;}
: Y& J- g3 P" W4 [
! ~3 }* h$ O9 x# j. z其中(GPIOB->CRL) &= 0X0FFFFFFF等价于 (GPIOB->CRL) = (GPIOB->CRL) & 0X0FFFFFFF0 M. q" X' _( y2 a, b9 g
其含义为:把PB端口的CRL寄存器的第28、29、30和31位清空,把GPIOB端口中的CNF7[1:0]和MODE7[1:0]置零, h& s( o; t, ^& z+ [

: k- g3 P+ ?; r8 C) N
其中GPIOB->CRL |= (u32)3<<28 等价于 GPIOB->CRL = GPIOB->CRL | (u32)(3<<12)
* n" ?$ }" z7 R! c& e8 P3转换为2进制为:0000 0000 0000 0000 0000 0000 0000 0011
" J$ `- {% O4 R; t6 U9 d$ ^将3左移28位得:0011 0000 0000 0000 0000 0000 0000 00008 [% T9 V: u) |  R
分析左移之后的数据为,将31、30、29、28位设置为00 11
6 C$ {4 U: l) s1 w% D7 g+ UPB的CRL寄存器中29和28位设置为11,其中29位MODE7[1]的值=1;28位MODE7[0]的值为1。即为输出模式,最大速度为50Mhz。! i- }$ u4 T" O7 n$ [& F
  @  b# n8 O) P. p& j& Z
bd0b6655f914488c8b083441edf707d0.png
2 {+ Y  ~+ g1 N+ W
7 B$ d' _7 W9 }6 J
PB的CRL寄存器中31和30位设置为00,其中31位CNF7[1]的值=0;30位CNF7[0]的值为0;由图五可知:通用推挽式输出模式。1 T" L. L4 c0 v6 ]4 Q% L7 T; {
————————————————4 M7 {& }& q& z, w6 x0 c4 _! }
版权声明:枫华雪悦v
4 b8 L6 ^' D8 k! h. Z如有侵权请联系删除4 P* ?3 _  F3 P! ?
8 K; j& |  s( H7 ]

; c9 i" k" _! C& j4 q! T! b# M$ }& Y+ ~3 s; z, T
收藏 评论0 发布时间:2023-5-22 20:00

举报

0个回答

所属标签

相似技术帖

官网相关资源

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