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

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

[复制链接]
攻城狮Melo 发布时间:2023-5-15 19:07
端口复用功能! |4 X/ ^5 ~( j, ?! w/ s2 B+ v; `& j7 ?
        STM32 有很多的内置外设(比如:串口、ADC、DAC等是独立的模块和内核连接在一起),这些外设的外部引脚都是与 GPIO 复用的。也就是说,一个 GPIO如果可以复用为内置外设的功能引脚,那么当这个 GPIO 作为内置外设使用的时候,就叫做复用。- T2 J- |% y9 N% O/ G/ {: m' C
        大家都知道,MCU 都有串口,STM32 有好几个串口。比如说 STM32F103ZET6 有 5 个串口,我们可以查手册知道,串口 1 的引脚对应的 IO 为 PA9,PA10.PA9,PA10 默认功能是 GPIO,所以当PA9,PA10 引脚作为串口 1 的 TX,RX 引脚使用的时候,那就是端口复用。查看芯片资料可知道那些口是复用端口。6 E- i  j) H/ H/ y7 _* g  |
- H+ A: T6 {% [, u$ D
4 y7 u& k4 U! \1 c- x0 M: R
复用端口初始化有几个步骤:2 a3 a- K: h  {( x# }( h
& E' s( A1 S+ X# g) u

. _; l  \+ M; z- R2 |GPIO 端口时钟使能。要使用到端口复用,当然要使能端口的时钟了。1 Q6 T) O, S# [3 ]" p- C
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);5 G0 L" r- r2 X- D; C" e
复制代码
  G  M( o% H- a* d0 m) Y9 K! R& V
复用的外设时钟使能。比如你要将端口 PA9,PA10 复用为串口,所以要使能串口时钟。
, o5 C+ F+ ^' Z$ x4 N: g. \1 V
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);. ?, _# F; I- b. X* z9 l1 F
复制代码
! c. x! M, k: q- e0 E* q- p! M. ?4 H
端口模式配置。 在 IO 复用为内置外设功能引脚的时候,必须设置 GPIO 端口的模式,至于 在复用功能下 GPIO 的模式是怎么对应的,这个可以查看手册《STM32 中文参考手册 V10》 P110 的表格“8.1.11 外设的 GPIO 配置”。这里我们拿 Usart1 举例:. c9 ~# u; Q8 A9 k

6 a- M# i0 f8 z; I; B
, L/ A+ O. P2 i' K8 s: Y" c) [
20201204162037509.png
& k, A/ v$ e4 V& K( c, f& F5 W
  [3 J( \+ F, ^1 T* s" Q6 p

7 C! {0 v# H; U: [. @从表格中可以看出,我们要配置全双工的串口 1,那么 TX 管脚需要配置为推挽复用输出,RX 管脚配置为浮空输入或者带上拉输入。
, n4 G' j  V$ I2 g% F, b- \0 E" K$ y4 B2 O( O. e. W- z
: ?/ {7 H- I5 S
代码如下:
8 a0 ?- K  t  S" U9 n  M0 |/ a
  1. //USART1_TX PA.9 复用推挽输出
    % n/ G; L- E6 s% W$ R
  2. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9& y$ M6 l2 a( ]- f- f, P7 O
  3. GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    ! ^, z( `' ]/ K/ r' q9 E; x
  4. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出4 S" y# y  N. a+ @5 n' B9 U
  5. GPIO_Init(GPIOA, &GPIO_InitStructure);
    : G  Q, y$ E" f9 ~# H  U
  6. //USART1_RX PA.10 浮空输入
    8 K1 k: U$ O3 z! Q* m
  7. GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10
    0 C3 [+ x" y, ?
  8. GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入, W, H/ a7 K" V5 I
  9. GPIO_Init(GPIOA, &GPIO_InitStructure);( t" N$ z; K, R0 `' ~1 ]
复制代码

. {, B% K1 A3 E( B5 f4 q我们在使用复用功能的是时候,最少要使能 2 个时钟:
6 L+ e! s2 }$ k8 q! ?! d# m* l& vGPIO 时钟使能
8 [8 c+ x5 Z% G+ N/ U# s% s复用的外设时钟使能同时要初始化 GPIO 以及复用外设功能
6 T1 S: U9 r5 ]& q6 ?- {; K# l9 q  H9 P0 q+ A, Z
6 u, c. X9 l5 Q, \
端口重映射
1 U$ g  x2 h+ S  g2 D; F        为了使不同器件封装的外设 IO 功能数量达到最优,可以把一些复用功能重新映射到其他一些引脚上。STM32 中有很多内置外设的输入输出引脚都具有重映射(remap)的功能。我们知道每个内置外设都有若干个输入输出引脚,一般这些引脚的输出端口都是固定不变的,为了让设计工程师可以更好地安排引脚的走向和功能,在 STM32 中引入了外设引脚重映射的概念,即一个外设的引脚除了具有默认的端口外,还可以通过设置重映射寄存器的方式,把这个外设的引脚映射到其它的端口。
6 s: v& j) b1 O6 n( L; J4 r        简单的讲就是把管脚的外设功能映射到另一个管脚,但不是可以随便映射的,具体对应关系《STM32 中文参考手册 V10》的 P116 页“8.3 复用功能和调试配置”有讲解。这里我们同样拿串口 1 为例来讲解。: q9 T$ w& J' ?/ w
7 r- a4 |! b% Q# Z( K: {

& e/ }6 o$ u; c' g) p. }! W3 c 20201204163136329.png 3 {- T8 g% _& r$ m  y2 h3 w
5 s: B% n: q% u, F1 t0 G- k9 r

( X7 }9 z- M' J/ E; K6 S2 d        上图是截取的中文参考手册中的重映射表,从表中可以看出,默认情况下,串口 1 复用的时候的引脚位 PA9,PA10,同时我们可以将 TX 和 RX 重新映射到管脚 PB6 和 PB7 上面去。
8 |4 W/ N% n, m' m# V7 m        所以重映射我们同样要使能复用功能的时候讲解的 2 个时钟外,还要使能 AFIO 功能时钟,然后要调用重映射函数。详细步骤为:' K1 N/ b8 M6 _! \3 |( j4 ]% S

$ b% u  p/ y3 c
% D/ h0 C, i3 u1 g. W0 ^4 R
使能 GPIOB 时钟:6 _. y6 j4 ]& ]; I
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
    0 }6 A" _5 T7 o7 X) A/ o- A0 \
复制代码

5 ?) ~4 }4 Q4 B5 @9 p2 o使能串口 1 时钟:
) Y% [' R4 M$ u' r$ p. E
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
    - f/ M8 d* e0 x- C( m4 F# ?% W
复制代码
# L- P% J+ h; g2 O6 w9 M1 E
使能 AFIO 时钟:
& J4 e  D# s6 U9 e3 |
  1. RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
    / p! t  r3 L& E, c& d
复制代码
3 C# @3 c7 _" ^. w; j, E9 G
PS: 在对寄存器AFIO_MARR,AFIO_EXTICRX和AFIO_EVCP进行读写操作前,应首先打开AFIO时钟。: F9 Q1 m6 S6 P/ h: _! i- H. f
1、 AFIO_MARR:配置复用功能映射
! p/ L5 H* Q0 H! w. q2、 AFIO_EXTICRX:配置外部中断线映射
1 G8 g" C+ }$ ^3、 AFIO_EVCP:配置EVENTOUT事件输出, ^7 X5 m* h, |4 Y- Y- B/ J- B9 o

7 ?) U! m% Z6 W1 O& S" X

% o* F  Q( \* W开启重映射:
6 c. u$ w* w& [/ ^2 `6 h  M" d+ _
  1. GPIO_PinRemapConfig(GPIO_Remap_USART1, ENABLE);1 U, K# D: k" B: i' s; Y8 B8 B
复制代码
  P! H  u0 j* @0 X, j3 y: S
这样就将串口的 TX 和 RX 重映射到管脚 PB6 和 PB7 上面了。至于有哪些功能可以重映射,大家除了查看中文参考手册之外,还可以从 GPIO_PinRemapConfig 函数入手查看第一个入口参数的取值范围可以得知。在stm32f10x_gpio.h 文件中定义了取值范围为下面宏定义的标识符,这里我们贴一小部分:% K  a3 `+ \$ z
  1. #define GPIO_Remap_SPI1 ((uint32_t)0x00000001) 9 a6 r# x# t  c) B! b6 \( l1 [
  2. #define GPIO_Remap_I2C1 ((uint32_t)0x00000002)
    % `, \- n" r' `( e- I# o' \5 Y
  3. #define GPIO_Remap_USART1 ((uint32_t)0x00000004)
    . z/ ]0 n8 d# ]# T# ?2 Q; b
  4. #define GPIO_Remap_USART2 ((uint32_t)0x00000008) 1 a9 y. Y& U1 t' d
  5. #define GPIO_PartialRemap_USART3 ((uint32_t)0x00140010)
    + w4 Z" J2 f- O4 a9 U, H! V" ?* F% {- w
  6. #define GPIO_FullRemap_USART3 ((uint32_t)0x00140030)
    ( g2 e# \$ I" `( J) s
复制代码

% d2 v2 s% ?9 b; v! U' E从上面可以看出,USART1 只有一种重映射,而对于 USART3,存在部分重映射和完全重映射。所谓部分重映射就是部分管脚和默认的是一样的,而部分管脚是重新映射到其他管脚。而完全重映射就是所有管脚都重新映射到其他管脚。看看手册中的 USART3 重映射表:
' x# f! }; ]8 p: \! n  r6 d8 {. y% r4 D3 G5 x$ n* L

( T6 k* Q/ V5 O8 w 20201204173139398.png
& }$ H: [) K. O5 ^  P( }* o
3 H# P: g: e5 u& l
  o- b( P2 s2 A, n! {- V" Z
部分重映射就是 PB10,PB11,PB12 重映射到 PC10,PC11,PC12 上。而 PB13 和 PB14 和没有重映射情况是一样的,都是 USART3_CTS 和 USART3_RTS 对应管脚。完全重映射就是将这两个脚重新映射到 PD11 和 PD12 上去。我们要使用 USART3 的部分重映射,我们调用函数方法为:- _3 g+ g4 V6 \: H
  1. GPIO_PinRemapConfig(GPIO_PartialRemap_USART3, ENABLE);
    ! [; D8 h4 V, ?% U7 A
复制代码

8 Z/ u/ y6 b+ f; ]  ?————————————————
# A2 }# t, n: U  \4 F( F版权声明:FHNCSDN
' f6 F, n$ E2 z' ^( F如有侵权请联系删除
/ _0 k1 k0 i: n
! [* X2 W* V9 ^6 Y) [8 X
$ o4 B  h8 B$ l' U. i0 n2 v
赞 收藏 评论0 发布时间:2023-5-15 19:07

举报

0个回答

所属标签

相似技术帖

官网相关资源

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