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

【经验分享】stm32f1的IO,推挽与开漏

[复制链接]
STMCU小助手 发布时间:2021-11-29 22:20
stm32的引脚有两种用途:GPIO(general purpose io)和AFIO(alternate function io)
- c" [- E* m3 _7 O$ Q' ?/ H; h- d. }) W$ C
对于一些引脚(视芯片而定),这两种用途都没有,如在64脚产品中,OSC_IN/OSC_OUT与作为GPIO端口的PD0/PD1共用一样的引脚,而在100、144引脚产品中,这四个功能各有引脚与之对应,不互相冲突,所以OSC_IN/OSC_OUT既不作GPIO也不作AFIO,当然,这样的引脚不是讨论重点。4 H! X1 X) c& m- }4 d
2 d3 X( q& w! |8 ]
1、引脚的配置
/ c( h9 E. R/ z2 a) Q. ~* g8 ]2 X7 ^4 b
不论是作GPIO还是做AFIO,都要对引脚进行配置。在固件库函数中,用GPIO_Init()函数对引脚进行配置,并不是说这个函数带了“GPIO”字样就是要当做GPIO来用,而是把它纳入GPIO的范畴来讨论。
3 K0 H8 ?" y6 ]$ [& f- p, ]6 i6 s. d6 n( e- G
所谓配置,就是引脚上的片上资源连接方式,如上拉电阻、密特触发等等。理解了配置,也就能明白配置与模式的区别。
3 k; L! A9 Z5 I; ^9 p
' j% F8 n4 p# T& }特别得,在下文中将会专门讨论一下输出配置中的推挽与开漏。
3 X( C$ N) ~9 u$ y! }" E' e; H
+ y( c' `1 q! Q1 w" L1 X5 ]: i2、复用功能
/ o$ N7 Z8 ~' d5 _' E; S$ G: X$ F7 `& W
复用功能有两种:没有重映像、重映像(包括部分重映像、完全重映像),使用引脚用作AFIO功能,同样需要对其进行配置。
$ S# A, J2 L7 t1 @3 i) ?# h4 u+ {2 X( A4 I+ U  v2 ]& S
1341810945_5803.jpg

6 E8 O, I' w& V, o这三句话来自参考手册,但我对第一句和注意有疑问,第三节讲。如果把端口配置成复用输出功能,则引脚和输出寄存器断开,并和片上外设的输出信号连接。输入配置则与GPIO没有区别。  W; z# H6 Z; A: D- S. j) D" ]

, u* G$ p1 l1 f3 H* ^, H为什么输出模式有专门的复用模式而输入则没有呢。因为输出是由芯片内部电路驱动的,必须选择这个驱动来自哪一个外设,是GPIO还是复用此管脚的其他外设,也就是选择该管脚在内部是与哪个外设相连的,不说明这个就会发生信号的错乱。而输入则不同了,输入信号是由芯片外的信号驱动的,虽然该信号进入芯片内部后可能有不同的去向,但不需要对此进行配置,因为不会发生信号的冲突,最坏的情况就是多驱动了个寄存器而已。事实上,当将引脚作为GPIO输入时,相应的AFIO外设是处在关闭的状态,并不会耗电;当引脚作为AFIO的输入时,可能GPIO是读不进来的,这是我猜的,没有验证,能不能读进来无所谓的,不必纠结于此。
7 Z7 L9 \7 `) L- o  |
% b1 g+ Y) B; Z" m
1341809146_6021.jpg
" h. `7 x+ B! U/ i, u
若选择了复用,则默认是没有重映像的,可以直接使用外设,不需要再软件做设置。7 E" u+ L: f/ f" g& \3 e) T0 L

6 q8 [7 L- e& z1 v8 P, y但若要重映射,则需要简单设置一下,# V! z4 [/ Q0 X# _
+ `  h9 ~, y! N9 r" y" G' c& W
先要配置重映射后对应的管脚,可参看参考手册或数据手册引脚定义章节,开AFIO时钟,使能重映射。例如重映射USART1,全部代码如下:3 v5 j5 S9 ^# M) x
3 ?& t# d; L# A, \) F
  RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
* i4 D8 \( [$ z: T3 V5 S8 `
0 _  [7 {) i" G* t1 e  /*对寄存器AFIO_EVCR,AFIO_MAPR和AFIO_EXTICRX进行读写操作前,即重映射和选择外部中断线前,应当首先打开AFIO的时钟*/. i- P% w) {, l2 x
! w4 g' a: m7 B7 m. i( X# `
  1. <p>  /* Configure USART1 Tx (PA.09) as alternate function push-pull */</p><p>
    - P  F9 U$ m  [, V6 _
  2. </p><p>  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;</p><p>& w& j3 U! {' T
  3. </p><p>  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;</p><p>
    4 n+ v* M, ?" R0 G6 a) B
  4. </p><p>  GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;</p><p>
    , }4 ?, O; f) o+ \. _
  5. </p><p>  GPIO_Init(GPIOB, &GPIO_InitStructure);</p><p>- m$ {, {. z0 }# X) \
  6. </p><p>    </p><p>4 s. B& M+ w8 R' b
  7. </p><p>  /* Configure USART1 Rx (PA.10) as input floating */</p><p>8 A) J7 n1 v2 A8 H: k
  8. </p><p>  GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;</p><p>- v6 y& S$ ]: b& t) ^3 X3 B- J1 X' {8 B/ k
  9. </p><p>  GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;</p><p>
    + I* D* O6 u% v% B" [
  10. </p><p>  GPIO_Init(GPIOB, &GPIO_InitStructure);</p><p>
    & q7 F/ \( {5 f0 h8 h/ N- ~5 K
  11. </p><p>  GPIO_PinRemapConfig(GPIO_Remap_USART1,ENABLE);</p>
复制代码

" e& y5 `/ [" X3 b; W! n8 `/ T5 x* c这就完成了IO口的配置和重映射,下边再配置相关的外设(USART1)就可以使用了。
3 G. r! N. D. F! v# ?' z$ [# A, J% G) _: e( G5 `7 p! T7 c! q( z3 ^
外部中断线也是可以映射的,并且需要开AFIO时钟,不用GPIO_PinRemap函数,用GPIO_EXTILineConfig重映射引脚到中断线。其实与其说是映射,不如说是选择,选择引脚连接到外部中断线。
: L9 E3 ^( H: |  ?) c$ V" @' b6 Z) d) u( s$ q: |# @
重映射不是任意的,只能重映射到指定的管脚。! z1 Q( R( {1 S" b6 O) L
& D4 ~) l4 q3 b7 }+ c3 k
3、关于第二节讲到那个疑问,为甚么不能配置成模拟输入?模拟输入与浮空什么区别?
; y& L: E7 n2 u6 H) T0 w# w4 Y
) j) O! `' T- `: z6 |6 M2 H答案是可以配置成模拟输入,官方3.5版固件库例子和alientek例程都是将ADC输入引脚配置成GPIO_Mode_AIN
5 ~4 v' ?; t3 E1 N* B* _, v; t; k6 b7 u( Y0 a% V
那么配置成浮空行么,还能ADC么?# H) l2 c! ]& W
  1. <p><span style="background-color: rgb(255, 255, 255);"> </span>   //例程</p><p>" o1 X4 }, ^3 u3 ?( V
  2. </p><p>    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;</p><p>    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;</p><p>    GPIO_Init(GPIOC, &GPIO_InitStructure);</p><p>
    % s0 e$ T: o3 B: O/ a, e4 T
  3. </p><p>     //修改</p><p>5 @. A$ X: n- \' B& e+ n5 f
  4. </p><p>    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;</p><p>    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;</p><p>    GPIO_Init(GPIOC, &GPIO_InitStructure);</p><p></p>
复制代码

! l; J- K# }6 T" h实验证明,这两种配置都能实现ADC。那么USART的Tx应配置成GPIO_Mode_IN_FLOATING,如果配置成GPIO_Mode_AIN,还能接受数据么?金牛板实验结果是不能,ST不我欺也。总之:  f6 K1 J7 `; [$ M' G
) Y+ O3 a  u" J( I- H3 u5 l
可以将引脚配置成模拟输入,使用相应的复用功能;
2 i7 d& y. d- L3 e* X* }( {* {0 \6 t  j" U) Z* g' Y
浮空与模拟这两种配置是不同的。7 N/ k4 z; \% D/ g4 a; ^

8 f& A8 c6 M; c9 e7 w关于第二节里那个“注意“,我也不知道是什么意思。我猜测是这样的:打开某外设,这个外设将某引脚当做输入,我们偏偏把这个引脚配置为GPIO输出,这样可以操作GPIO来”欺骗“这个外设,这种用法应该是很微妙的。
4 r" G$ q) u" V8 B( W
; o; {$ c' r6 ?2 ?4、推挽与开漏
3 u, a  P0 Q1 u% \0 i5 A# k# |; D4 x7 d5 ^
不仅仅stm32有这种配置,实际上,这两种已经广泛应用在很多场合。
$ x% w" n1 T/ p% v9 T# Q8 J
& x" }, t& y  `# t' C7 D5 L) k推挽,又叫做推拉,是个很形象的名字,一般是指两个三极管(MOS管)分别受两互补信号(或者一个信号,但是用互补对管)的控制,总是在一个三极管导通的时候另一个截止,这样的电路被称为推挽式(互补式):
# @* W) @3 s+ U7 ?
* J* H5 f5 r" m( w7 L
1346657973_9578.png
  X: U2 M# B4 ]0 J5 l  U
这种电路在放大中通常被用作输出级,在STM32中,推挽配置就是这种,如图:
/ V5 x9 ?7 m$ q2 h& ~( Z
9 E' Z+ u7 d5 J2 r
1346657791_8272.jpg
" c& ~" V5 @. z% y7 o: c! t
在相应位置1时,P-MOS导,通N-MOS截止,输出电压为VDD;在相应位置0时,N-MOS导通,P-MOS截止,输出电压为VSS,这就是所谓的推挽。是比较简单的。
0 I. l/ a/ Q' p( ~5 o
; |) ?* o4 g, H  ^而所谓的开漏(对三极管而言是开集,一样的原理),则要巧妙一些。所谓开漏电路概念中提到的“漏”就是指MOS FET的漏极。同理,开集电路中的“集”就是指三极管的集电极。开漏电路就是指以MOS FET的漏极为输出的电路。一般的用法是会在漏极外部的电路添加上拉电阻。完整的开漏电路应该由开漏器件和开漏上拉电阻组成。5 V! s' Y6 w+ m

1 P4 S+ n9 t  h( J. T对于stm32,开漏就是失能了P-MOS,这样,当相应位置1时,引脚实际上是处在了浮空的状态,而通过外接的上拉电阻,将其拉高。$ O# p, E1 D* o0 Y  ~  I

: G4 V* l) T9 \0 F3 b这么做有如下的好处:
+ d* ~  i. g( u: _% ?: `  O( j
6 f- n! `" O1 u; S# _0 f1、可以将多个开漏输出的引脚,连接到一条线上。形成“与逻辑”关系。当多个引脚任意一个变低后,开漏线上的逻辑就为0了。这也是I2C,SMBus等总线判断总线占用状态的原理。/ P3 |* v# U* I' Z
2、 可以利用改变上拉电源的电压,改变传输电平。这样我们就可以用低电平逻辑控制输出高电平逻辑了。想想当初认为stm32输出3.3v电压带不动IRF540,就直接断定要重新选型,是错误的想法,只要将推挽输出变为开漏,再加上上拉到5v的电阻,就能解决这个问题。, h- l2 r: m" T8 ~; Q: K5 n

( W8 `1 p# b* s; q( i3 I顺便一提,上拉电阻的阻值决定了逻辑电平转换的沿的速度。阻值越大,速度越低功耗越小。反之亦然。- r3 |0 r2 e; g1 i, M
" k7 I6 b* o! V4 p, Q+ i( r
4 V! Y7 W* d5 }8 U+ W3 P* P1 u
收藏 评论0 发布时间:2021-11-29 22:20

举报

0个回答
关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版