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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-15 19:07
端口复用功能
6 x1 C5 r/ R9 ]& o        STM32 有很多的内置外设(比如:串口、ADC、DAC等是独立的模块和内核连接在一起),这些外设的外部引脚都是与 GPIO 复用的。也就是说,一个 GPIO如果可以复用为内置外设的功能引脚,那么当这个 GPIO 作为内置外设使用的时候,就叫做复用。6 U2 p. I' O! @9 ]( g
        大家都知道,MCU 都有串口,STM32 有好几个串口。比如说 STM32F103ZET6 有 5 个串口,我们可以查手册知道,串口 1 的引脚对应的 IO 为 PA9,PA10.PA9,PA10 默认功能是 GPIO,所以当PA9,PA10 引脚作为串口 1 的 TX,RX 引脚使用的时候,那就是端口复用。查看芯片资料可知道那些口是复用端口。* H$ m; O# X' e3 ^& M3 U' u5 {
: j- s' q9 o$ T) y8 u6 W+ G
4 P; C- k* F# _  c( Z! h$ o
复用端口初始化有几个步骤:/ D* e( V8 j  a

4 i0 h8 V3 O- _8 i- _0 Q- H- Q

; \0 k/ `& b+ n' tGPIO 端口时钟使能。要使用到端口复用,当然要使能端口的时钟了。* I- l  z9 I/ c( d0 i
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);* ^4 d3 Y8 m! u6 U
复制代码
* G4 f. ?( K/ z% j7 d0 _0 z  p
复用的外设时钟使能。比如你要将端口 PA9,PA10 复用为串口,所以要使能串口时钟。
$ r1 }, \7 W7 V' t
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    8 t: \+ f" K+ Q7 D( K9 i
复制代码

! Z" a" F- V9 a' B+ Q" P端口模式配置。 在 IO 复用为内置外设功能引脚的时候,必须设置 GPIO 端口的模式,至于 在复用功能下 GPIO 的模式是怎么对应的,这个可以查看手册《STM32 中文参考手册 V10》 P110 的表格“8.1.11 外设的 GPIO 配置”。这里我们拿 Usart1 举例:# _6 Z  E: A6 m
6 W% k5 h1 p  X) s+ U6 b& F

) A( Q( A4 B- l 20201204162037509.png
$ O7 u: R0 w( Y4 m8 _6 Y/ t- r9 ]1 q' I1 p! P0 d" [: r
# ?' u6 _* h1 D4 b
从表格中可以看出,我们要配置全双工的串口 1,那么 TX 管脚需要配置为推挽复用输出,RX 管脚配置为浮空输入或者带上拉输入。
& p) U! d# L, t. a6 a2 a: G& l1 ^0 `3 x. R( u0 i" P
$ Z4 N0 J2 {8 r
代码如下:
! f0 Z. r0 @1 x. @% l+ @
  1. //USART1_TX PA.9 复用推挽输出
    4 ~4 v, F/ T' ~9 O7 e- Q7 N0 x
  2. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9/ e: X) t- F% \8 _1 N( x# S
  3. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;/ i/ ~/ J7 `6 ]9 Q% x7 n0 G
  4. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
    " t% p; s& f5 v
  5. GPIO_Init(GPIOA, &GPIO_InitStructure);
    $ Q3 a1 d7 ?( g; C3 V
  6. //USART1_RX PA.10 浮空输入* b6 f8 k7 |( V* |( C" G' A. i
  7. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10/ ?/ x8 a3 `& k1 q# a; P
  8. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    $ ^' k# J! w4 x  L$ V
  9. GPIO_Init(GPIOA, &GPIO_InitStructure);3 m) r% B$ n, e+ L
复制代码

- _6 C9 Z7 @5 O" Q' e我们在使用复用功能的是时候,最少要使能 2 个时钟:
& ^, Q8 Z+ I  W+ x  J/ QGPIO 时钟使能
4 L& y" J$ z7 j% N' I" g, p7 i复用的外设时钟使能同时要初始化 GPIO 以及复用外设功能
+ A) r2 s2 f9 r) `# `& G6 X, o9 P3 e
7 K6 h" k1 d7 {

2 j+ s- l( X2 K- g0 Z: f1 R端口重映射+ V* r4 S! ^1 P! v2 Q0 j0 F$ G
        为了使不同器件封装的外设 IO 功能数量达到最优,可以把一些复用功能重新映射到其他一些引脚上。STM32 中有很多内置外设的输入输出引脚都具有重映射(remap)的功能。我们知道每个内置外设都有若干个输入输出引脚,一般这些引脚的输出端口都是固定不变的,为了让设计工程师可以更好地安排引脚的走向和功能,在 STM32 中引入了外设引脚重映射的概念,即一个外设的引脚除了具有默认的端口外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其它的端口。
8 L- S) R7 R8 Q8 V        简单的讲就是把管脚的外设功能映射到另一个管脚,但不是可以随便映射的,具体对应关系《STM32 中文参考手册 V10》的 P116 页“8.3 复用功能和调试配置”有讲解。这里我们同样拿串口 1 为例来讲解。  m/ F" \, z1 b& a& a9 D: K' S! t/ h+ o
, ]- g2 z1 r9 S  M0 {" `3 \* L

' n# {. T+ X5 z7 v. ]2 f 20201204163136329.png / }7 k9 B/ d% r- V  m8 H, i
) Z7 q5 g% I; c. P6 \) d
" O7 w6 N4 f) u) l! s& G
        上图是截取的中文参考手册中的重映射表,从表中可以看出,默认情况下,串口 1 复用的时候的引脚位 PA9,PA10,同时我们可以将 TX 和 RX 重新映射到管脚 PB6 和 PB7 上面去。
, \4 H7 ]1 ]% s' D7 ~        所以重映射我们同样要使能复用功能的时候讲解的 2 个时钟外,还要使能 AFIO 功能时钟,然后要调用重映射函数。详细步骤为:0 e3 x! c; k# E4 a/ Y- @# }

  M% J5 ?% {6 i) q

" I' Y9 [$ K4 c  W% C2 a使能 GPIOB 时钟:
( |9 Q! Q' Q; C- ^# E1 Y' ~  [' O# g1 Q
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);+ k) f+ Y# y9 a! y& F( R
复制代码

0 r* u! y4 D1 a7 W2 S) I使能串口 1 时钟:
; i* V" }+ @2 K
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    ( X2 J7 b" w6 h
复制代码

; B6 s- Q1 P2 e使能 AFIO 时钟:
' L6 K5 w0 a, R& B
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);4 }5 t* |* o  l9 |# \, |) ^  g
复制代码
. g, O7 L. a/ ]: B. _6 L
PS: 在对寄存器AFIO_MARR,AFIO_EXTICRX和AFIO_EVCP进行读写操作前,应首先打开AFIO时钟。
) W7 e- m7 y* @' X7 j6 \1、 AFIO_MARR:配置复用功能映射
3 m) Q8 i* d3 q2、 AFIO_EXTICRX:配置外部中断线映射
/ A5 ?/ L5 b. [2 `3、 AFIO_EVCP:配置EVENTOUT事件输出
, @; U; Q! k* q: }5 E) [6 d# I4 P
# _; J3 U! F- v, T
开启重映射:" w! Q4 I, T0 a3 Q& h7 O2 K/ M
  1. GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);/ U* r$ A5 D- j* E# q  a
复制代码
) i9 Z/ H$ n; A1 Z
这样就将串口的 TX 和 RX 重映射到管脚 PB6 和 PB7 上面了。至于有哪些功能可以重映射,大家除了查看中文参考手册之外,还可以从 GPIO_PinRemapConfig 函数入手查看第一个入口参数的取值范围可以得知。在stm32f10x_gpio.h 文件中定义了取值范围为下面宏定义的标识符,这里我们贴一小部分:
, r1 _; n' U% [7 q
  1. #define GPIO_Remap_SPI1 ((uint32_t)0x00000001)
    . P$ I1 g* Y1 R' Y& o0 m
  2. #define GPIO_Remap_I2C1 ((uint32_t)0x00000002) . N# s8 L! v# _" W+ d0 E2 v
  3. #define GPIO_Remap_USART1 ((uint32_t)0x00000004)
    : y4 s  w5 _3 l+ ?/ z& f" E2 P. s
  4. #define GPIO_Remap_USART2 ((uint32_t)0x00000008)
    / p( H9 S* `. B$ l
  5. #define GPIO_PartialRemap_USART3 ((uint32_t)0x00140010) - b9 U1 G& D) }) `- c" F. W, }7 E' E
  6. #define GPIO_FullRemap_USART3 ((uint32_t)0x00140030)8 L. t/ ?5 t3 ~, e0 k
复制代码
' z! {$ Y6 C8 M& g1 I- s& Z  U+ ^
从上面可以看出,USART1 只有一种重映射,而对于 USART3,存在部分重映射和完全重映射。所谓部分重映射就是部分管脚和默认的是一样的,而部分管脚是重新映射到其他管脚。而完全重映射就是所有管脚都重新映射到其他管脚。看看手册中的 USART3 重映射表:
$ ~" z: I- l+ c  r* O" d! W# b
5 N' Y  c$ k$ B% c- a2 s# L
/ J3 U# Z( H# x9 z; H
20201204173139398.png
# u# l: ^: [; o, Z7 r& e4 f6 b( m
. }0 m) c$ K4 B
- F; j+ w- r, s, S! A% P9 K) v2 I
部分重映射就是 PB10,PB11,PB12 重映射到 PC10,PC11,PC12 上。而 PB13 和 PB14 和没有重映射情况是一样的,都是 USART3_CTS 和 USART3_RTS 对应管脚。完全重映射就是将这两个脚重新映射到 PD11 和 PD12 上去。我们要使用 USART3 的部分重映射,我们调用函数方法为:
% Z6 F1 A% q9 {
  1. GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);
    3 z2 ~' k/ {! L, [0 T) b$ ~
复制代码

% S$ e3 ?5 |; D7 Z4 `————————————————
: G4 l& p: j5 N4 i4 h! |2 ^3 Q版权声明:FHNCSDN1 F( e. b0 }1 R3 \
如有侵权请联系删除
+ q) J- h; m. P" ]5 A- D7 N
; y! ~) D( H3 i: _1 h% T
' [6 e& C& A% ?% u( L
赞 收藏 评论0 发布时间:2023-5-15 19:07

举报

0个回答

所属标签

相似技术帖

官网相关资源

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