嵌入式大厂面经 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编程等)、开发工具(交叉编译、调试工具等)以及实际项目经验分享。专栏将采用理论结合实践的方式,每个知识点都会附带相关的面试真题和答案解析。