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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-15 19:07
端口复用功能
  p8 z) J3 x4 i$ m        STM32 有很多的内置外设(比如:串口、ADC、DAC等是独立的模块和内核连接在一起),这些外设的外部引脚都是与 GPIO 复用的。也就是说,一个 GPIO如果可以复用为内置外设的功能引脚,那么当这个 GPIO 作为内置外设使用的时候,就叫做复用。+ R/ x% q5 Z. Z& @8 R
        大家都知道,MCU 都有串口,STM32 有好几个串口。比如说 STM32F103ZET6 有 5 个串口,我们可以查手册知道,串口 1 的引脚对应的 IO 为 PA9,PA10.PA9,PA10 默认功能是 GPIO,所以当PA9,PA10 引脚作为串口 1 的 TX,RX 引脚使用的时候,那就是端口复用。查看芯片资料可知道那些口是复用端口。5 d6 k2 v4 J2 x
* M' c; g' N" U7 i2 ?

$ [& ^. C( R. A6 F& i- a8 ~! p复用端口初始化有几个步骤:1 f8 F. q' q( b( c: E
% h' G8 _$ r: q4 ^

8 s- I4 z* W4 FGPIO 端口时钟使能。要使用到端口复用,当然要使能端口的时钟了。
8 `! c+ r' Q, ^* V$ h
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
    1 D% k5 p5 G, E6 _
复制代码
* l/ d* J, z* l. k# `0 j
复用的外设时钟使能。比如你要将端口 PA9,PA10 复用为串口,所以要使能串口时钟。
$ w5 D9 _9 v- N4 a" u
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);& {6 |2 B: q9 ^" ~$ p0 g! D. n  Y
复制代码

$ q, D0 s/ b0 J) M! P端口模式配置。 在 IO 复用为内置外设功能引脚的时候,必须设置 GPIO 端口的模式,至于 在复用功能下 GPIO 的模式是怎么对应的,这个可以查看手册《STM32 中文参考手册 V10》 P110 的表格“8.1.11 外设的 GPIO 配置”。这里我们拿 Usart1 举例:
  u6 p" j4 k" p+ U6 `" U- d5 O  j+ U; B4 f7 H& |

* p' |: p7 L+ e3 W' q3 w 20201204162037509.png
# m" c9 D3 A# G
3 u7 X" Z; y$ `. W5 j" o3 }

4 {' v& S' E, o7 S. d; |3 \! ~8 q从表格中可以看出,我们要配置全双工的串口 1,那么 TX 管脚需要配置为推挽复用输出,RX 管脚配置为浮空输入或者带上拉输入。
4 S3 G3 `1 T+ k& R1 Q' J4 g0 j$ H
3 A% W3 ?4 @4 R
代码如下:- q0 S4 N) v7 Y9 N1 u3 h* J
  1. //USART1_TX PA.9 复用推挽输出
    0 t* ]% C( B' ], O/ o5 F! q
  2. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9
    3 L3 W) k5 C  m* H1 ]9 Q+ b
  3. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;/ i- q/ m9 r! @: G, o7 V
  4. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出
    & {* W- u, H: |" \' O7 a# z. U5 h
  5. GPIO_Init(GPIOA, &GPIO_InitStructure);
    % N( u6 ?: s6 t- [* ^6 S
  6. //USART1_RX PA.10 浮空输入
    3 m5 d6 K+ |7 x
  7. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
    6 T# |' i% h# X: k; I& a
  8. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入
    6 }8 X6 m* _+ f
  9. GPIO_Init(GPIOA, &GPIO_InitStructure);
    8 q8 c% N/ y( f, i. f6 S
复制代码
& e- _& U) Q% X) j6 q8 ]
我们在使用复用功能的是时候,最少要使能 2 个时钟:
6 ]  g+ T+ ]3 e  E" f- ~2 V( OGPIO 时钟使能
/ T$ Q: O% |1 u1 b/ E: H复用的外设时钟使能同时要初始化 GPIO 以及复用外设功能
& O2 b3 |) I% V, Y' \3 n
6 S4 K, D1 ?, l! g
6 P/ I) Z+ E: k
端口重映射
6 b. |; `* r: w        为了使不同器件封装的外设 IO 功能数量达到最优,可以把一些复用功能重新映射到其他一些引脚上。STM32 中有很多内置外设的输入输出引脚都具有重映射(remap)的功能。我们知道每个内置外设都有若干个输入输出引脚,一般这些引脚的输出端口都是固定不变的,为了让设计工程师可以更好地安排引脚的走向和功能,在 STM32 中引入了外设引脚重映射的概念,即一个外设的引脚除了具有默认的端口外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其它的端口。
1 n4 A0 M( g: N) e- q        简单的讲就是把管脚的外设功能映射到另一个管脚,但不是可以随便映射的,具体对应关系《STM32 中文参考手册 V10》的 P116 页“8.3 复用功能和调试配置”有讲解。这里我们同样拿串口 1 为例来讲解。
8 N. F! h2 J! ]: W; y. u# v/ [+ S) K  [" U

5 `; T/ n* {, J% W, \ 20201204163136329.png / F* A) L6 o6 r5 ?
% e/ ?  S3 l5 g4 f1 J; l" L

' d% i# A1 M! o        上图是截取的中文参考手册中的重映射表,从表中可以看出,默认情况下,串口 1 复用的时候的引脚位 PA9,PA10,同时我们可以将 TX 和 RX 重新映射到管脚 PB6 和 PB7 上面去。* Q% U; v" _) k4 v6 o
        所以重映射我们同样要使能复用功能的时候讲解的 2 个时钟外,还要使能 AFIO 功能时钟,然后要调用重映射函数。详细步骤为:- G! L% k. c6 @0 j4 l: m

" b* M0 g" p; H* U$ o

$ ?. `( C$ f9 l7 Q( U9 z* O8 X5 i使能 GPIOB 时钟:
: O/ Q& ^! y3 ^8 R6 w. Q
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    $ A0 z  C- l% w! M. ?
复制代码
0 I0 ]9 m% p) j4 @! P6 l0 H0 I
使能串口 1 时钟:$ D7 Z7 }7 h' }9 B4 N
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);- A  j- z7 q' \! ]; j. [
复制代码

, `7 `) w. d8 ]! W, I  M使能 AFIO 时钟:
; y9 |3 e" [9 w  S2 K0 D, _
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);. b0 ]; G/ \2 z
复制代码
8 C# O; N. J5 o2 o+ ~) s: f
PS: 在对寄存器AFIO_MARR,AFIO_EXTICRX和AFIO_EVCP进行读写操作前,应首先打开AFIO时钟。
0 @( S0 [/ c# d1 S$ E! [4 \. r1、 AFIO_MARR:配置复用功能映射
/ A* G+ W3 c7 T/ k7 y- Q* ?0 ~2、 AFIO_EXTICRX:配置外部中断线映射
# o* x. k4 @! u' }) e& W3 P) A5 c3、 AFIO_EVCP:配置EVENTOUT事件输出; _' ~) H% u2 |9 M. y# b

9 r7 d9 X9 C- y6 ~* W
5 x( D) |6 _' e3 j, \, ]
开启重映射:5 x& h  h6 @% n* y" }
  1. GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);
    - S& g% [8 ^( o5 I
复制代码

) Z0 k4 Q% i  V3 Y$ X3 G2 N这样就将串口的 TX 和 RX 重映射到管脚 PB6 和 PB7 上面了。至于有哪些功能可以重映射,大家除了查看中文参考手册之外,还可以从 GPIO_PinRemapConfig 函数入手查看第一个入口参数的取值范围可以得知。在stm32f10x_gpio.h 文件中定义了取值范围为下面宏定义的标识符,这里我们贴一小部分:
! h; u/ M( l' v& y5 _
  1. #define GPIO_Remap_SPI1 ((uint32_t)0x00000001)
    8 g  C' {* S% _7 R9 \! G% ?
  2. #define GPIO_Remap_I2C1 ((uint32_t)0x00000002)
    ) R: V+ p, |+ r1 a% h$ v6 c
  3. #define GPIO_Remap_USART1 ((uint32_t)0x00000004)
    & y- V  C+ z7 u; A+ i9 @
  4. #define GPIO_Remap_USART2 ((uint32_t)0x00000008)
    1 U' L5 ?4 T2 i2 c6 ^9 a9 _
  5. #define GPIO_PartialRemap_USART3 ((uint32_t)0x00140010)
    7 A* \, O4 L+ U2 |; L7 K2 F/ [
  6. #define GPIO_FullRemap_USART3 ((uint32_t)0x00140030)0 H) I+ ?- ]' D" L
复制代码

. V$ u5 i  Y" w% F从上面可以看出,USART1 只有一种重映射,而对于 USART3,存在部分重映射和完全重映射。所谓部分重映射就是部分管脚和默认的是一样的,而部分管脚是重新映射到其他管脚。而完全重映射就是所有管脚都重新映射到其他管脚。看看手册中的 USART3 重映射表:5 v8 B" E! X5 K5 M
1 B' y- \0 \' ^+ b' N7 Q. `
- a6 n9 K; t. a
20201204173139398.png
1 u* n/ [( |! H
6 A; a( G/ l& u( E
. T, V1 W+ X, m2 _
部分重映射就是 PB10,PB11,PB12 重映射到 PC10,PC11,PC12 上。而 PB13 和 PB14 和没有重映射情况是一样的,都是 USART3_CTS 和 USART3_RTS 对应管脚。完全重映射就是将这两个脚重新映射到 PD11 和 PD12 上去。我们要使用 USART3 的部分重映射,我们调用函数方法为:
" A( t) F5 o  Q+ ]4 A/ |
  1. GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);2 R( I' K, J, m' _8 y, P
复制代码
6 d- P) ?' W- P2 V1 A; b; b$ q+ }
————————————————; c% h$ J+ l" t
版权声明:FHNCSDN
8 W/ O9 }6 s0 [; {3 N( h9 ^如有侵权请联系删除
# |. X) w; S4 L9 L' x$ v% h  B1 `) v, n7 M( @6 p4 n
5 ~8 j! T" i( \- O0 T4 N
赞 收藏 评论0 发布时间:2023-5-15 19:07

举报

0个回答

所属标签

相似技术帖

官网相关资源

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