别再死记硬背了!用STM32F103标准库函数速查表,5分钟搞定GPIO、ADC、TIM配置
·
STM32F103标准库实战速查手册:告别函数记忆负担
每次调试STM32时,面对密密麻麻的库函数手册翻找半小时,最后发现参数顺序还是写反了?这份速查表将彻底改变你的开发体验。不同于传统手册的机械罗列,我们按照 初始化-配置-读写-中断 的实战流程重组函数,并标注了90%项目都会用到的典型参数组合。当你正在调试PWM时,可以直接跳到定时器章节,5秒内复制出可用的代码片段。
1. GPIO配置:从点亮LED到中断触发
GPIO是大多数开发者接触STM32的第一个外设,但它的函数命名规则常常让人困惑。比如 GPIO_Init 和 GPIO_StructInit 有什么区别?何时需要调用 GPIO_PinLockConfig ?下面按实际使用场景分类:
1.1 初始化配置黄金组合
// 标准初始化流程(适用于80%场景)
GPIO_InitTypeDef GPIO_InitStruct = {0};
GPIO_StructInit(&GPIO_InitStruct); // 先填充默认值
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStruct.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStruct);
关键参数速查表 :
| 模式 | 典型应用场景 | 等效寄存器操作 |
|---|---|---|
| GPIO_Mode_Out_PP | LED驱动 | CRL/CRH = 0x3 |
| GPIO_Mode_Out_OD | I2C引脚 | CRL/CRH = 0x6 |
| GPIO_Mode_IN_FLOATING | 按键检测 | CRL/CRH = 0x4 |
| GPIO_Mode_IPU | 无外接上拉电阻的按键 | CRL/CRH = 0x8 |
注意:使用复用功能时(如USART),必须同时开启对应外设时钟和GPIO的复用模式
1.2 高频操作函数
-
电平控制三剑客 :
GPIO_SetBits(GPIOB, GPIO_Pin_12); // 置高 GPIO_ResetBits(GPIOB, GPIO_Pin_12); // 置低 GPIO_WriteBit(GPIOB, GPIO_Pin_12, Bit_SET); // 条件写入 -
状态读取组合 :
// 读取单个引脚(最常用) uint8_t state = GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0); // 批量读取整个端口(适用于矩阵键盘) uint16_t port_val = GPIO_ReadInputData(GPIOC);
1.3 中断配置实战示例
外部中断配置需要 跨模块协作 :
// 步骤1:配置GPIO为输入
GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU; // 上拉输入
GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
GPIO_Init(GPIOA, &GPIO_InitStruct);
// 步骤2:映射GPIO到EXTI线
GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
// 步骤3:配置EXTI触发方式
EXTI_InitTypeDef EXTI_InitStruct = {0};
EXTI_InitStruct.EXTI_Line = EXTI_Line0;
EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Falling; // 下降沿触发
EXTI_InitStruct.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStruct);
// 步骤4:配置NVIC优先级
NVIC_InitTypeDef NVIC_InitStruct = {0};
NVIC_InitStruct.NVIC_IRQChannel = EXTI0_IRQn;
NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = 0x0F;
NVIC_InitStruct.NVIC_IRQChannelSubPriority = 0x0F;
NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStruct);
2. 定时器应用:PWM生成与输入捕获
定时器是STM32最复杂的外设之一,TIM1和TIM8(高级定时器)支持死区控制等特殊功能,而TIM2-TIM5(通用定时器)更适合基础应用。
2.1 PWM输出标准模板
生成1kHz、占空比50%的PWM:
// 时基配置
TIM_TimeBaseInitTypeDef TIM_TimeBaseStruct = {0};
TIM_TimeBaseStruct.TIM_Prescaler = 72 - 1; // 72MHz/72 = 1MHz
TIM_TimeBaseStruct.TIM_Period = 1000 - 1; // 1MHz/1000 = 1kHz
TIM_TimeBaseStruct.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStruct);
// PWM通道配置
TIM_OCInitTypeDef TIM_OCStruct = {0};
TIM_OCStruct.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCStruct.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCStruct.TIM_Pulse = 500; // 50%占空比
TIM_OCStruct.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM2, &TIM_OCStruct);
// 启动定时器
TIM_Cmd(TIM2, ENABLE);
TIM_CtrlPWMOutputs(TIM2, ENABLE); // 高级定时器需要此命令
PWM参数速查表 :
| 参数 | 计算公式 | 典型值示例 |
|---|---|---|
| TIM_Prescaler | 时钟频率/目标计数频率 - 1 | 72MHz/1MHz → 71 |
| TIM_Period | 计数频率/PWM频率 - 1 | 1MHz/1kHz → 999 |
| TIM_Pulse | TIM_Period * 占空比百分比 | 999*0.5 → 499 |
2.2 输入捕获测量频率
测量方波频率的完整流程:
// 时基配置(1us计数)
TIM_TimeBaseStruct.TIM_Prescaler = 72 - 1; // 1MHz
TIM_TimeBaseStruct.TIM_Period = 0xFFFF;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStruct);
// 输入捕获配置
TIM_ICInitTypeDef TIM_ICStruct = {0};
TIM_ICStruct.TIM_Channel = TIM_Channel_2;
TIM_ICStruct.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICStruct.TIM_ICSelection = TIM_ICSelection_DirectTI;
TIM_ICStruct.TIM_ICPrescaler = TIM_ICPSC_DIV1;
TIM_ICStruct.TIM_ICFilter = 0x0;
TIM_ICInit(TIM3, &TIM_ICStruct);
// 启用捕获中断
TIM_ITConfig(TIM3, TIM_IT_CC2, ENABLE);
TIM_Cmd(TIM3, ENABLE);
// 在中断服务程序中计算频率
void TIM3_IRQHandler(void) {
static uint16_t last_capture = 0;
if(TIM_GetITStatus(TIM3, TIM_IT_CC2)) {
uint16_t current_capture = TIM_GetCapture2(TIM3);
uint32_t freq = 1000000 / (current_capture - last_capture); // 单位Hz
last_capture = current_capture;
TIM_ClearITPendingBit(TIM3, TIM_IT_CC2);
}
}
3. ADC采样:多通道与DMA传输
STM32F103的ADC最高采样率1MHz,但实际性能受制于时钟配置。以下是多通道采样的最优实践:
3.1 多通道轮询采样
// ADC初始化
ADC_InitTypeDef ADC_InitStruct = {0};
ADC_InitStruct.ADC_Mode = ADC_Mode_Independent;
ADC_InitStruct.ADC_ScanConvMode = ENABLE; // 多通道必须开启扫描模式
ADC_InitStruct.ADC_ContinuousConvMode = ENABLE;
ADC_InitStruct.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;
ADC_InitStruct.ADC_DataAlign = ADC_DataAlign_Right;
ADC_InitStruct.ADC_NbrOfChannel = 3; // 通道数量
ADC_Init(ADC1, &ADC_InitStruct);
// 配置采样通道和顺序
ADC_RegularChannelConfig(ADC1, ADC_Channel_0, 1, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_1, 2, ADC_SampleTime_55Cycles5);
ADC_RegularChannelConfig(ADC1, ADC_Channel_2, 3, ADC_SampleTime_55Cycles5);
// 启动ADC
ADC_Cmd(ADC1, ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1, ENABLE);
// 读取采样值
uint16_t adc_values[3];
for(int i=0; i<3; i++) {
while(!ADC_GetFlagStatus(ADC1, ADC_FLAG_EOC));
adc_values[i] = ADC_GetConversionValue(ADC1);
}
3.2 DMA传输配置(高效方案)
// DMA配置
DMA_InitTypeDef DMA_InitStruct = {0};
DMA_InitStruct.DMA_PeripheralBaseAddr = (uint32_t)&ADC1->DR;
DMA_InitStruct.DMA_MemoryBaseAddr = (uint32_t)adc_buffer;
DMA_InitStruct.DMA_DIR = DMA_DIR_PeripheralSRC;
DMA_InitStruct.DMA_BufferSize = 4; // 4个通道
DMA_InitStruct.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStruct.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStruct.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStruct.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStruct.DMA_Mode = DMA_Mode_Circular; // 循环模式
DMA_InitStruct.DMA_Priority = DMA_Priority_High;
DMA_InitStruct.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA1_Channel1, &DMA_InitStruct);
// 启用DMA
DMA_Cmd(DMA1_Channel1, ENABLE);
ADC_DMACmd(ADC1, ENABLE);
ADC采样时间选择指南 :
| 采样周期 | 适用场景 | 典型转换时间(12位) |
|---|---|---|
| 1.5 cycles | 高速信号 | 1.07μs |
| 7.5 cycles | 一般用途 | 1.57μs |
| 55.5 cycles | 高阻抗信号源 | 4.57μs |
4. 时钟树配置:RCC关键函数解析
STM32的时钟配置直接影响所有外设性能,以下是核心配置函数组合:
4.1 72MHz系统时钟配置
// 1. 复位时钟配置
RCC_DeInit();
// 2. 启用HSE(8MHz外部晶振)
RCC_HSEConfig(RCC_HSE_ON);
while(!RCC_WaitForHSEStartUp());
// 3. 配置PLL
RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); // 8MHz*9=72MHz
RCC_PLLCmd(ENABLE);
while(RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
// 4. 切换系统时钟
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while(RCC_GetSYSCLKSource() != 0x08);
// 5. 配置APB分频
RCC_HCLKConfig(RCC_SYSCLK_Div1); // AHB=72MHz
RCC_PCLK1Config(RCC_HCLK_Div2); // APB1=36MHz
RCC_PCLK2Config(RCC_HCLK_Div1); // APB2=72MHz
4.2 外设时钟使能速查
必须开启的外设时钟 :
// GPIO端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// USART1时钟(APB2)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1, ENABLE);
// TIM2时钟(APB1)
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);
// ADC1时钟(需先配置PCLK2分频)
RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
常见坑点:忘记开启AFIO时钟会导致GPIO重映射功能失效,使用
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE)
更多推荐



所有评论(0)