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

基于STM32F1端口复用、端口重映射经验分享

[复制链接]
攻城狮Melo 发布时间:2023-5-15 19:07
端口复用功能
& T0 N9 ?9 p0 r" _" ]        STM32 有很多的内置外设(比如:串口、ADC、DAC等是独立的模块和内核连接在一起),这些外设的外部引脚都是与 GPIO 复用的。也就是说,一个 GPIO如果可以复用为内置外设的功能引脚,那么当这个 GPIO 作为内置外设使用的时候,就叫做复用。0 y# k# E4 E5 `* V2 j9 ]; Q$ [
        大家都知道,MCU 都有串口,STM32 有好几个串口。比如说 STM32F103ZET6 有 5 个串口,我们可以查手册知道,串口 1 的引脚对应的 IO 为 PA9,PA10.PA9,PA10 默认功能是 GPIO,所以当PA9,PA10 引脚作为串口 1 的 TX,RX 引脚使用的时候,那就是端口复用。查看芯片资料可知道那些口是复用端口。3 F5 g1 K" H+ X; `+ H; O

* F: G" c" g. F& v* E
2 Y6 `+ f: b' v' J, T
复用端口初始化有几个步骤:
" \+ _# d9 l, h$ G3 C2 v( k( z7 P8 ?1 D
3 D' N8 b! [% Z2 C4 S$ D0 J2 |
GPIO 端口时钟使能。要使用到端口复用,当然要使能端口的时钟了。
5 V( ~8 L4 n/ F; e7 K6 T) `
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);5 r7 ?2 ?. ~; f! H
复制代码

- w/ [0 w% |) w9 g复用的外设时钟使能。比如你要将端口 PA9,PA10 复用为串口,所以要使能串口时钟。7 p  g( R( ~$ ^  E$ S- ~9 |
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);2 ]0 r5 H1 T4 ]# x8 m2 e# A1 a. r
复制代码

9 O0 p9 j8 v. `( y端口模式配置。 在 IO 复用为内置外设功能引脚的时候,必须设置 GPIO 端口的模式,至于 在复用功能下 GPIO 的模式是怎么对应的,这个可以查看手册《STM32 中文参考手册 V10》 P110 的表格“8.1.11 外设的 GPIO 配置”。这里我们拿 Usart1 举例:
7 w! C( y* L6 I6 g- U! a& g: S/ w: t( L; s7 }, y0 B+ p

, V" s7 Y+ U: y5 Z 20201204162037509.png 3 k" d2 J3 w' w! z7 d

, V" e" ~6 I% r; s& \. F
3 O  Q& X* q$ T+ s
从表格中可以看出,我们要配置全双工的串口 1,那么 TX 管脚需要配置为推挽复用输出,RX 管脚配置为浮空输入或者带上拉输入。! i* o1 S# C0 `% M# A

" Z2 c( Q  \2 A+ C8 M, e
# k0 h, t% Y2 Y) O6 D4 x
代码如下:
7 s6 Y; {0 ?; N! k# V! Q' U
  1. //USART1_TX PA.9 复用推挽输出
    " u! V  ?2 J1 B, ]  y
  2. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9- s+ s2 N; x9 z. L+ C1 ?' k& N
  3. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    & V+ |2 j% d: Y/ z
  4. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
    ; T* s5 a( Z) P  z6 L! X
  5. GPIO_Init(GPIOA, &GPIO_InitStructure);# u) W4 c0 r7 X2 Q7 w" N* k
  6. //USART1_RX PA.10 浮空输入* }& l( r. f$ T/ G
  7. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10! K, o+ L% X6 _6 ]( Y6 p+ E
  8. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入+ z+ w# M, B  f' _$ x$ w- ^
  9. GPIO_Init(GPIOA, &GPIO_InitStructure);$ }; e1 k) ]6 S# B! d% j/ D
复制代码
6 I& O& `4 @5 k1 m' b5 _
我们在使用复用功能的是时候,最少要使能 2 个时钟:
  }0 `$ y" o  U6 U9 pGPIO 时钟使能
' @4 E/ |9 [$ p- I' _6 P- K复用的外设时钟使能同时要初始化 GPIO 以及复用外设功能6 z1 R, n# j# g- @; B7 n$ Y7 z

  {. P; n( T. W! h  r

8 c* T9 e/ @  h1 K: _+ G8 [+ T4 r端口重映射8 U7 I, N& f" t7 L$ F
        为了使不同器件封装的外设 IO 功能数量达到最优,可以把一些复用功能重新映射到其他一些引脚上。STM32 中有很多内置外设的输入输出引脚都具有重映射(remap)的功能。我们知道每个内置外设都有若干个输入输出引脚,一般这些引脚的输出端口都是固定不变的,为了让设计工程师可以更好地安排引脚的走向和功能,在 STM32 中引入了外设引脚重映射的概念,即一个外设的引脚除了具有默认的端口外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其它的端口。
; N7 k# E2 g6 @4 x, G& A' S7 G        简单的讲就是把管脚的外设功能映射到另一个管脚,但不是可以随便映射的,具体对应关系《STM32 中文参考手册 V10》的 P116 页“8.3 复用功能和调试配置”有讲解。这里我们同样拿串口 1 为例来讲解。4 G* [, P1 R& Y9 X5 B
& e2 o& r' B( Q0 [" J, R9 f, H2 t
& r% \% R5 F1 A3 e+ S
20201204163136329.png ! S/ f+ }/ L/ g* P* \+ k6 D& A, ?

  f5 W2 T, q$ l: W8 s0 C( k
. u4 P+ s$ f- h3 t+ p  Q0 D
        上图是截取的中文参考手册中的重映射表,从表中可以看出,默认情况下,串口 1 复用的时候的引脚位 PA9,PA10,同时我们可以将 TX 和 RX 重新映射到管脚 PB6 和 PB7 上面去。- p9 C  H. G+ z/ d2 x5 J
        所以重映射我们同样要使能复用功能的时候讲解的 2 个时钟外,还要使能 AFIO 功能时钟,然后要调用重映射函数。详细步骤为:  G9 W# {, n0 t8 E( S
1 @1 E* j% k' n1 K! u

) M8 n% A- B1 e4 c) C2 A使能 GPIOB 时钟:
" W7 P( B' W2 t, v8 C, ]+ \* p
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);0 t. w, ]5 Y% V1 S8 u& e# b
复制代码
$ Q3 z" @  {7 I; a2 h  e
使能串口 1 时钟:" g# H5 c! @( \6 Q/ E0 c
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);7 n- x4 }7 `% V2 G0 `" m
复制代码

; w) L6 W8 \- v2 a使能 AFIO 时钟:
0 M. X5 h2 c* y5 _
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
      b" r1 K) ]; s& t, M% h
复制代码
" Q( W1 q. E8 J6 w
PS: 在对寄存器AFIO_MARR,AFIO_EXTICRX和AFIO_EVCP进行读写操作前,应首先打开AFIO时钟。9 e% F- N! b1 K# w
1、 AFIO_MARR:配置复用功能映射4 P2 y' l& P) ~- U: _( T, g
2、 AFIO_EXTICRX:配置外部中断线映射
) B( T5 F; C3 \3 r4 {, [! L) J; O3、 AFIO_EVCP:配置EVENTOUT事件输出3 O. e- f0 \$ @6 m/ H& S
! V3 t5 L. f; M9 F# @1 o8 g
; i6 C: q& |1 V6 T" L# [! p
开启重映射:
' {4 x9 _3 m7 E. ]1 r8 v2 m" A
  1. GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);4 y2 k+ I4 ]  ^' m- i
复制代码
# i3 W4 C8 e7 \- N: I# b9 Q
这样就将串口的 TX 和 RX 重映射到管脚 PB6 和 PB7 上面了。至于有哪些功能可以重映射,大家除了查看中文参考手册之外,还可以从 GPIO_PinRemapConfig 函数入手查看第一个入口参数的取值范围可以得知。在stm32f10x_gpio.h 文件中定义了取值范围为下面宏定义的标识符,这里我们贴一小部分:
: S7 X9 t8 c" E! f8 G
  1. #define GPIO_Remap_SPI1 ((uint32_t)0x00000001)
    2 T, o1 `: a3 ?8 i% l
  2. #define GPIO_Remap_I2C1 ((uint32_t)0x00000002)
    3 B/ `+ H; ~8 N2 q
  3. #define GPIO_Remap_USART1 ((uint32_t)0x00000004)
    * Q3 P/ C) s4 h6 q
  4. #define GPIO_Remap_USART2 ((uint32_t)0x00000008) % B* Z$ ?0 Q# l9 `( e5 k  y5 q
  5. #define GPIO_PartialRemap_USART3 ((uint32_t)0x00140010) 2 k# H( p1 Y4 S" r
  6. #define GPIO_FullRemap_USART3 ((uint32_t)0x00140030)
      o- ~: y' h( O% }2 B6 v+ r
复制代码
* f3 J* j) q1 R+ q  \. L4 b
从上面可以看出,USART1 只有一种重映射,而对于 USART3,存在部分重映射和完全重映射。所谓部分重映射就是部分管脚和默认的是一样的,而部分管脚是重新映射到其他管脚。而完全重映射就是所有管脚都重新映射到其他管脚。看看手册中的 USART3 重映射表:' `" t1 d8 Z( ]  l0 P
8 `) J2 [7 `5 p" [/ w
: G8 k, v0 P9 e6 K7 c
20201204173139398.png $ z. t' e& t* j. `
+ D5 M. E9 L- o( ]) M% Z- ^
/ a. ~2 D+ J0 X
部分重映射就是 PB10,PB11,PB12 重映射到 PC10,PC11,PC12 上。而 PB13 和 PB14 和没有重映射情况是一样的,都是 USART3_CTS 和 USART3_RTS 对应管脚。完全重映射就是将这两个脚重新映射到 PD11 和 PD12 上去。我们要使用 USART3 的部分重映射,我们调用函数方法为:! A$ ~4 s4 y) e. G2 t4 B2 D
  1. GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);
    ) {/ f; k* }, c( s+ s
复制代码
, X$ v2 s0 I- b7 ^/ D
————————————————
! u& [9 z4 ^& ~6 |版权声明:FHNCSDN
2 p) v5 l3 E# ^9 z如有侵权请联系删除
7 e* R+ b( Q+ v7 R( M0 i% }( e' b! @% Q5 }! B+ P4 K
3 d7 j  W( }! F! \8 L
赞 收藏 评论0 发布时间:2023-5-15 19:07

举报

0个回答

所属标签

相似技术帖

官网相关资源

关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版