嵌入式大厂面经 STM32 PWM常见面试题(持续更新中!)
这是一个嵌入式大厂面试题专栏,每天更新高频面试题。专栏将包含题目描述、详细解析、相关知识点扩展以及实际代码示例。内容涵盖操作系统、驱动开发、通信协议等核心领域,并结合实际项目经验进行分析。每道题目都会附带面试官可能的追问方向,帮助大家更好地准备面试!
STM32 PWM常见面试题
PWM(脉宽调制)是STM32微控制器中非常重要的功能,广泛应用于电机控制、LED调光、信号生成等场景。以下是STM32 PWM相关的常见面试题及解答:
1. PWM基本原理
什么是PWM?
PWM(Pulse Width Modulation)是一种通过调节脉冲宽度来控制输出功率的技术。通过改变高电平在一个周期内的占比(占空比),可以实现对负载功率的精确控制。
PWM的关键参数
- 频率:PWM信号的周期性变化速率,决定了PWM的基本时间单位
- 占空比:高电平时间占整个周期的比例,决定了输出的平均功率
- 分辨率:PWM可以调节的最小步进值,通常由定时器位数决定
// PWM关键参数计算 PWM频率 = 时钟频率 / ((预分频值+1) * (自动重装载值+1)) 占空比 = 比较值 / 自动重装载值 * 100%
2. STM32 PWM实现原理
定时器通道配置
STM32使用定时器的输出比较功能实现PWM输出。当计数器值与比较寄存器值相等时,输出引脚状态会根据PWM模式设置发生变化。
// 基本PWM配置示例
void PWM_Config(void) {
// 时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
// GPIO配置
GPIO_InitTypeDef GPIO_InitStructure;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // TIM3_CH1
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
// 定时器基本配置
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 999; // ARR值,决定PWM周期
TIM_TimeBaseStructure.TIM_Prescaler = 71; // PSC值,决定计数频率
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);
// PWM配置
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 500; // CCR值,决定占空比
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OC1Init(TIM3, &TIM_OCInitStructure);
TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);
TIM_ARRPreloadConfig(TIM3, ENABLE);
// 启动定时器
TIM_Cmd(TIM3, ENABLE);
}
PWM模式
STM32定时器支持两种PWM模式:
- PWM模式1:计数器值 < CCR值时,通道输出有效电平;计数器值 ≥ CCR值时,通道输出无效电平
- PWM模式2:与PWM模式1相反的输出逻辑
3. 高级PWM功能
互补输出与死区时间
高级定时器(如TIM1/TIM8)支持互补输出和死区时间插入,主要用于电机驱动等应用。
// 互补输出与死区时间配置
void PWM_AdvancedConfig(void) {
// 基本配置省略...
// PWM配置
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable; // 互补输出使能
TIM_OCInitStructure.TIM_Pulse = 500;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;
TIM_OC1Init(TIM1, &TIM_OCInitStructure);
// 死区时间配置
TIM_BDTRInitTypeDef TIM_BDTRInitStructure;
TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStructure.TIM_DeadTime = 100; // 死区时间设置
TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;
TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
// 主输出使能
TIM_CtrlPWMOutputs(TIM1, ENABLE);
}
中心对齐模式
中心对齐模式下,计数器在0和ARR之间来回计数,产生对称的PWM波形,适用于电机控制等应用。
// 中心对齐模式配置 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1;
4. 常见应用场景
1. LED调光
// LED亮度控制
void LED_SetBrightness(uint16_t brightness) {
// brightness范围:0-1000
TIM_SetCompare1(TIM3, brightness);
}
// LED呼吸灯效果
void LED_Breathing(void) {
static uint16_t brightness = 0;
static int8_t direction = 1;
brightness += direction * 10;
if(brightness >= 1000) {
brightness = 1000;
direction = -1;
} else if(brightness <= 0) {
brightness = 0;
direction = 1;
}
LED_SetBrightness(brightness);
delay_ms(20);
}
2. 电机控制
// 直流电机速度控制
void Motor_SetSpeed(uint16_t speed) {
// speed范围:0-1000
TIM_SetCompare1(TIM1, speed);
}
// 伺服电机角度控制
void Servo_SetAngle(uint8_t angle) {
// 标准舵机:0.5ms-2.5ms脉冲对应0-180度
// 假设PWM周期为20ms(50Hz)
uint16_t pulse = 50 + (angle * 100 / 180); // 50-150对应0.5ms-1.5ms
TIM_SetCompare2(TIM3, pulse);
}
3. DAC模拟输出
// 使用PWM模拟DAC输出
void PWM_DAC_SetVoltage(uint16_t voltage) {
// voltage范围:0-3300 (mV)
uint16_t pwm_value = voltage * 1000 / 3300;
TIM_SetCompare3(TIM3, pwm_value);
}
5. 常见面试问题
1. 如何计算PWM频率和占空比?
PWM频率和占空比的计算公式:
// 频率计算 PWM频率 = 时钟频率 / ((PSC+1) * (ARR+1)) // 占空比计算 占空比 = CCR / ARR * 100%
例如,对于72MHz的系统时钟:
// 配置1kHz, 50%占空比的PWM PSC = 71; // 预分频系数 ARR = 999; // 自动重装载值 CCR = 500; // 比较值 // 计算 PWM频率 = 72MHz / ((71+1) * (999+1)) = 1kHz 占空比 = 500 / 999 * 100% ≈ 50%
2. 如何提高PWM分辨率?
提高PWM分辨率的方法:
- 使用更大的ARR值:增加自动重装载值可以提高分辨率,但会降低PWM频率
- 使用更高位数的定时器:如使用32位定时器(TIM2/TIM5)
- 降低PWM频率:在允许的范围内降低频率可以提高分辨率
- 使用更高的时钟频率:提高定时器时钟频率可以同时保持较高的频率和分辨率
// 高分辨率PWM配置示例
void HighResolution_PWM_Config(void) {
// 使用32位定时器TIM2
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Period = 100000 - 1; // 更大的ARR值
TIM_TimeBaseStructure.TIM_Prescaler = 7 - 1; // 较小的预分频值
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_C
剩余60%内容,订阅专栏后可继续查看/也可单篇购买
嵌入式面试八股文全集 文章被收录于专栏
这是一个全面的嵌入式面试专栏。主要内容将包括:操作系统(进程管理、内存管理、文件系统等)、嵌入式系统(启动流程、驱动开发、中断管理等)、网络通信(TCP/IP协议栈、Socket编程等)、开发工具(交叉编译、调试工具等)以及实际项目经验分享。专栏将采用理论结合实践的方式,每个知识点都会附带相关的面试真题和答案解析。

腾讯成长空间 6025人发布
查看1道真题和解析