嵌入式大厂面经 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分辨率的方法:

  1. 使用更大的ARR值:增加自动重装载值可以提高分辨率,但会降低PWM频率
  2. 使用更高位数的定时器:如使用32位定时器(TIM2/TIM5)
  3. 降低PWM频率:在允许的范围内降低频率可以提高分辨率
  4. 使用更高的时钟频率:提高定时器时钟频率可以同时保持较高的频率和分辨率
// 高分辨率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编程等)、开发工具(交叉编译、调试工具等)以及实际项目经验分享。专栏将采用理论结合实践的方式,每个知识点都会附带相关的面试真题和答案解析。

全部评论

相关推荐

05-07 13:29
已编辑
门头沟学院 Java
北斗导航Compass低仿版:能不能先搞清楚优先级啊,怎么可能是项目问题,项目很重要吗?又没学历 又没实习大厂凭啥约面?那玩具项目 没应用在真实生产环境下的 就算做上天又有什么用?早点找个小公司实习 拿小公司实习去投大厂实习,这才是你现在该做的
投递美团等公司10个岗位 简历被挂麻了,求建议
点赞 评论 收藏
分享
04-03 22:39
重庆大学 Java
点赞 评论 收藏
分享
评论
1
6
分享

创作者周榜

更多
牛客网
牛客企业服务