端口复用的定义 STM32有许多的内置外设(如串口、ADC、DCA等等),这些外设的外部引脚都是和GPIO复用的。也就是说,一个GPIO如果可以复用为内置外设的功能引脚,那么当这个GPIO作为内置外设使用的时候,就叫复用。详细的可以参考《STM32F103ZET6数据手册》p30的内容,表格的倒数第二栏就表示端口复用功能。 比如说,STM32的串口1的引脚对应的I/O位PA9、PA10。而PA9、PA10默认的功能都是GPIO,所以说当PA9、PA10引脚作为串口1使用的时候就是端口复用。 在配置GPIO引脚功能时需要打开对应端口(port)所在的总线时钟,例如: - #define RCC_AHB1Periph_GPIOA ((uint32_t)0x00000001)1 {. M$ a; W! D
- #define RCC_AHB1Periph_GPIOB ((uint32_t)0x00000002)
! P- F P; B; U7 ~. v7 h6 M - #define RCC_AHB1Periph_GPIOC ((uint32_t)0x00000004)' |1 D- @: u- e2 q
- #define RCC_AHB1Periph_GPIOD ((uint32_t)0x00000008)
2 I: Z4 k, r5 ?- ?* w+ S2 f3 @ - #define RCC_AHB1Periph_GPIOE ((uint32_t)0x00000010)
1 [8 Y9 @" @1 V( N+ v0 s2 F - #define RCC_AHB1Periph_GPIOF ((uint32_t)0x00000020)5 c6 R3 M5 r% x0 i
- #define RCC_AHB1Periph_GPIOG ((uint32_t)0x00000040)+ ~5 ?9 p& K8 i/ O. T: Y
- #define RCC_AHB1Periph_GPIOH ((uint32_t)0x00000080)9 T* L5 O4 d5 A$ A5 ?
- #define RCC_AHB1Periph_GPIOI ((uint32_t)0x00000100), v4 O$ y% q/ z1 j
- #define RCC_AHB1Periph_GPIOJ ((uint32_t)0x00000200)
9 ^" n% V/ }5 y# S- Q8 s: W* H* G - #define RCC_AHB1Periph_GPIOK ((uint32_t)0x00000400) h% t- _4 k! B) [0 g0 b+ M
- #define RCC_AHB1Periph_CRC ((uint32_t)0x00001000)
1 [/ m! K% z4 b& M" X - #define RCC_AHB1Periph_FLITF ((uint32_t)0x00008000)! G) T+ t2 o6 e9 f; u) F( J, N1 e$ p
- #define RCC_AHB1Periph_SRAM1 ((uint32_t)0x00010000)' v9 G: w/ _8 q: O. T9 ]
- #define RCC_AHB1Periph_SRAM2 ((uint32_t)0x00020000)* l4 w2 m( N- F; K4 Z; r1 ?
- #define RCC_AHB1Periph_BKPSRAM ((uint32_t)0x00040000)
/ Y6 R9 k P5 g3 j: W. l; Z0 j$ [ - #define RCC_AHB1Periph_SRAM3 ((uint32_t)0x00080000)
9 t+ o, C# Q, a1 k$ N6 r/ A; o - #define RCC_AHB1Periph_CCMDATARAMEN ((uint32_t)0x00100000)
2 u" i" T' w0 X! W; Y% c! _ - #define RCC_AHB1Periph_DMA1 ((uint32_t)0x00200000)
5 J4 ]! H* w6 a: P1 l - #define RCC_AHB1Periph_DMA2 ((uint32_t)0x00400000)
+ p! I, g! \) n3 K8 R* B9 R& z! | - #define RCC_AHB1Periph_DMA2D ((uint32_t)0x00800000)
0 ] W# H# N( Q* Q) H+ ] - #define RCC_AHB1Periph_ETH_MAC ((uint32_t)0x02000000)
+ t2 m9 F" E# ~ Y3 O - #define RCC_AHB1Periph_ETH_MAC_Tx ((uint32_t)0x04000000)/ G; k7 q Q( n' J3 R
- #define RCC_AHB1Periph_ETH_MAC_Rx ((uint32_t)0x08000000)
1 B/ ^, j$ ]+ X- G) }. Z - #define RCC_AHB1Periph_ETH_MAC_PTP ((uint32_t)0x10000000)& Y" s* [6 {8 c* k3 f `+ F: z
- #define RCC_AHB1Periph_OTG_HS ((uint32_t)0x20000000)
+ R( o0 ^6 T; H0 X - #define RCC_AHB1Periph_OTG_HS_ULPI ((uint32_t)0x40000000)
复制代码 5 C x; D% R1 g9 m+ K6 _2 P; d
端口复用初始化过程接下来看一下端口复用初始化过程的步骤,拿串口1为例: 1、GPIO端口时钟使能。要使用到端口复用,首先是要使能端口的时钟了; RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); 2、复用的外设时钟使能。比如要将PA9、PA10引脚复用成串口,必须也要使能串口时钟; / c0 |8 S `5 m1 a& V
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE); 3、端口模式配置。在I/O复用位内置外设功能引脚的时候,必须设置GPIO端口的模式。至于在复用功能下,GPIO的模式怎么设置,可以查看手册《STM32中文参考手册》p110的内容。这里拿USART1为例,进行配置,要配置全双工的串口1,TX引脚需要推挽复用输出,RX引脚需要浮空输入或者上拉输入; : `# D. |0 l3 f/ U3 w* F7 j f1 t
- <div align="left">GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9; //PA.9//复用推挽输出</div><div align="left">GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;</div><div align="left">GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用推挽输出</div><div align="left">GPIO_Init(GPIOA, &GPIO_InitStructure);</div>% X) [5 W( U2 k# ~ e7 E' `. e2 D
- <div align="left">GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;//PA10 PA.10 浮空输入</div><div align="left">GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;//浮空输入</div><div align="left">GPIO_Init(GPIOA, &GPIO_InitStructure);</div>
复制代码
& V* g# A3 m, ?总而言之,使用复用功能的时候至少要使能2时钟:GPIO时钟使能、复用的外设时钟使能。同时还要初始化GPIO以及复用外设功能(端口模式配置)。 b2 g/ ~% L" W# m
|