本文將詳細講解 STM32F103 系列中常見的“復用功能重映射”(Remap)機制,包括 JTAG 占用、引腳默認功能與復用功能的關系,以及如何通過寄存器或標準庫代碼實現重映射。以 TIM3 在 PB4/PB5 上輸出 PWM 為例,進行實戰講解,適合初學者與進階開發者參考
一、什么是“復用功能重映射”(Remap)
?
STM32 系列的引腳大多數都具有多種功能,比如既可以做普通 GPIO,也可以作為串口、定時器通道、SPI 等外設使用。
以 STM32F103
為例,有些引腳在芯片上電復位后默認配置為某些外設功能(主功能),而有些引腳默認不是該功能,但可以通過“功能重映射
”將該功能映射過去。
功能重映射機制允許我們在引腳資源有限或外設沖突時,將某些外設的引腳重新映射到其他引腳組,從而獲得更大的靈活性。
二、判斷是否需要重映射的邏輯
在使用某個外設功能時,我們需要判斷是否可以直接使用,還是必須進行重映射。以下是準確的判斷邏輯:
1. 如果“主功能名 == 引腳名”
例如:
PA9
是USART1\_TX
(默認功能)PA10
是USART1\_RX
(默認功能)
這類引腳默認即可作為對應外設使用,無需任何重映射設置。
2. 如果“主功能名 ≠ 引腳名”,但手冊中支持通過重映射映射到該引腳
例如:
PB4
默認是JNTRST
,但支持通過重映射成為TIM3\_CH1
則必須開啟相應的重映射配置,才可以使用該外設功能。
3. 如果手冊中未提及該引腳支持該外設
說明該引腳不支持該功能,即便使用重映射也無法達到目的。
三、JTAG默認占用問題與引腳釋放
STM32F103
系列默認啟用了全功能 JTAG
調試接口,它會占用多個引腳:
引腳 | JTAG功能 |
---|---|
PA13 | JTMS |
PA14 | JTCK |
PA15 | JTDI |
PB3 | JTDO |
PB4 | JNTRST |
如果需要將 PB4
用作其他功能(如 TIM3\_CH1
),必須首先禁用 JTAG 功能,否則該引腳將無法正常輸出或輸入信號。
禁用 JTAG(保留 SWD)
標準庫寫法如下:
// 開啟 AFIO 外設時鐘,這是使用重映射的前提
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);// 禁用 JTAG,僅保留 SWD(兩線調試),釋放 PB3、PB4、PA15
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
這行代碼會釋放 PB3、PB4、PA15
,使其恢復為普通可配置引腳。
四、重映射類型介紹(無重映射 / 部分重映射 / 完全重映射)
STM32F103
系列在設計時為部分外設功能預設了多種映射方式,主要分為以下三類:
1. 無重映射(No Remap)
使用默認引腳。例如 TIM3\_CH1
默認映射到 PA6,TIM3\_CH2
映射到 PA7。
2. 部分重映射(Partial Remap)
將部分通道映射到其他引腳,例如將 TIM3\_CH1
映射到 PB4
,TIM3\_CH2
映射到 PB5
。
標準庫代碼:
// 將 TIM3 的 CH1 和 CH2 通道映射到 PB4 和 PB5(部分重映射)
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
3. 完全重映射(Full Remap)
將所有通道映射到全新的引腳組,例如 TIM3 的所有通道映射到 PC6\~PC9
。
標準庫代碼:
// 將 TIM3 所有通道映射到 PC6-PC9(完全重映射)
GPIO_PinRemapConfig(GPIO_FullRemap_TIM3, ENABLE);
所有重映射配置都可在參考手冊(RM0008)第九章 AFIO 章節中查到。
五、實戰案例:TIM3
在PB4/PB5
輸出PWM控制電機
背景:
在使用 L9110S
電機驅動模塊時,需要控制兩個引腳(如 PB4 和 PB5
)輸出 PWM
信號,實現電機的正反轉與調速。但 PB4 默認是 JTAG
口的一部分,TIM3 默認也未映射到 PB4/PB5
。
步驟如下:
1. 釋放 PB4 的 JTAG 占用:
// 使能 AFIO 外設的時鐘
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);// 禁用 JTAG,僅保留 SWD,釋放 PB4 用作普通引腳
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
2. 打開 TIM3 并進行部分重映射:
// 將 TIM3_CH1 和 TIM3_CH2 分別重映射到 PB4 和 PB5
GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);
3. 配置 GPIO 為復用推挽輸出:
GPIO_InitTypeDef GPIO_InitStructure;// 設置為復用推挽輸出模式
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
// 設置 IO 輸出速度為最大 50MHz
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// 選擇引腳 PB4 和 PB5
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
// 初始化 GPIOB 引腳
GPIO_Init(GPIOB, &GPIO_InitStructure);
4. 配置 TIM3 輸出 PWM 到 PB4/PB5:
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;// 打開 TIM3 的時鐘(APB1總線)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);// 設置 PWM 的頻率:PWM_freq = 72MHz / (Prescaler+1) / (Period+1)
TIM_TimeBaseStructure.TIM_Period = 999; // 自動重裝載值 ARR:1000 - 1
TIM_TimeBaseStructure.TIM_Prescaler = 71; // 分頻系數:72MHz / (71+1) = 1MHz
TIM_TimeBaseStructure.TIM_ClockDivision = 0; // 時鐘分頻因子,通常為0
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; // 向上計數模式
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);// 配置通道1(PB4)為 PWM 輸出
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1; // 設置為 PWM 模式1
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable; // 使能通道輸出
TIM_OCInitStructure.TIM_Pulse = 500; // 設置占空比為 50%
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High; // 高電平有效
TIM_OC1Init(TIM3, &TIM_OCInitStructure); // 初始化 TIM3 的通道1
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable); // 使能預裝載// 配置通道2(PB5)為 PWM 輸出
TIM_OCInitStructure.TIM_Pulse = 500; // 設置占空比
TIM_OC2Init(TIM3, &TIM_OCInitStructure); // 初始化 TIM3 的通道2
TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable); // 使能預裝載// 啟動 TIM3
TIM_Cmd(TIM3, ENABLE);
六、總結與建議
STM32F103
的外設引腳不能隨意指定,必須遵守 ST 提供的默認映射或預設重映射規則。- 若默認引腳被 JTAG 或其他功能占用,應先通過
GPIO_PinRemapConfig
釋放。 - 想要使用非默認引腳的外設功能,必須啟用部分或完全重映射。
- 所有外設的映射組合、支持的重映射模式,都可以在參考手冊第九章“AFIO”中查閱。
建議在項目初期就根據引腳分布圖和重映射選項合理規劃外設引腳,避免開發中途資源沖突。
如需延伸內容(如編碼器輸入、PWM測頻、雙路電機控制等),歡迎留言討論交流。
(完)