基于STM32F103实现两路PWM输出

一、硬件连接方案

1. 引脚分配(以TIM3为例)

通道 默认引脚 重映射引脚 适用场景
CH1 PA6 PB4 电机控制/LED调光
CH2 PA7 PB5 伺服电机/呼吸灯

2. 电路设计要点

  • 电机驱动:需外接H桥电路(如TB6612)保护GPIO

  • LED限流:串联220Ω电阻防止烧毁

  • 滤波电路:在电源端添加0.1μF陶瓷电容


二、软件实现代码

1. 定时器初始化(TIM3双通道PWM)

#include "stm32f10x.h"

void TIM3_PWM_Init(u16 arr, u16 psc) {
    GPIO_InitTypeDef GPIO_InitStructure;
    TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
    TIM_OCInitTypeDef TIM_OCInitStructure;

    // 使能时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM3, ENABLE);
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO, ENABLE);

    // 引脚重映射配置
    GPIO_PinRemapConfig(GPIO_PartialRemap_TIM3, ENABLE);  // PA6→PB4, PA7→PB5

    // GPIO初始化
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4 | GPIO_Pin_5;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;      // 复用推挽输出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);

    // 定时器基础配置
    TIM_TimeBaseStructure.TIM_Period = arr;             // 自动重装载值
    TIM_TimeBaseStructure.TIM_Prescaler = psc;          // 预分频系数
    TIM_TimeBaseStructure.TIM_ClockDivision = 0;
    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
    TIM_TimeBaseInit(TIM3, &TIM_TimeBaseStructure);

    // PWM模式配置
    TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;   // PWM模式1
    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
    TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

    // 通道1配置
    TIM_OCInitStructure.TIM_Pulse = 0;                  // 初始占空比0%
    TIM_OC1Init(TIM3, &TIM_OCInitStructure);
    TIM_OC1PreloadConfig(TIM3, TIM_OCPreload_Enable);

    // 通道2配置
    TIM_OCInitStructure.TIM_Pulse = 0;
    TIM_OC2Init(TIM3, &TIM_OCInitStructure);
    TIM_OC2PreloadConfig(TIM3, TIM_OCPreload_Enable);

    // 使能定时器
    TIM_Cmd(TIM3, ENABLE);
}

2. 占空比动态调整

// 设置通道1占空比(0-100%)
void Set_PWM1_DutyCycle(u8 percent) {
    u16 compare_val = (arr + 1) * percent / 100;
    TIM_SetCompare1(TIM3, compare_val);
}

// 设置通道2占空比(0-100%)
void Set_PWM2_DutyCycle(u8 percent) {
    u16 compare_val = (arr + 1) * percent / 100;
    TIM_SetCompare2(TIM3, compare_val);
}

3. 主函数示例

int main(void) {
    // 初始化PWM(周期20ms,频率50Hz)
    TIM3_PWM_Init(19999, 71);  // 72MHz/(72)=1MHz → 1MHz/(19999+1)=50Hz

    while(1) {
        // 通道1从0%到100%渐变
        for(u8 i=0; i<=100; i++) {
            Set_PWM1_DutyCycle(i);
            Delay_ms(10);
        }
        
        // 通道2从100%到0%渐变
        for(u8 i=100; i>=0; i--) {
            Set_PWM2_DutyCycle(i);
            Delay_ms(10);
        }
    }
}

三、关键参数计算

1. PWM频率公式

频率 = 72MHz / (预分频系数 + 1) / (自动重装载值 + 1)
  • 示例:psc=71, arr=19999 → 72/(72)/(20000)=50Hz

2. 占空比计算

占空比(%) = (CCR值 / (ARR+1)) × 100

四、调试技巧

1. 示波器观察要点

  • 上升沿对齐:确保两路PWM上升沿同步

  • 占空比精度:检查实际值与设定值偏差(应<1%)

  • 死区时间:电机控制需添加死区(建议0.1-0.5μs)

2. 常见问题解决

现象 原因 解决方案
无输出 GPIO未正确映射 检查AFIO时钟和重映射配置
占空比失真 中断干扰 关闭相关中断或提高优先级
频率漂移 系统时钟异常 验证PLL配置和外部晶振

五、扩展功能实现

1. 输入捕获同步

// 配置TIM3_CH1为输入捕获(用于编码器)
TIM_ICInitTypeDef TIM_ICInitStructure;
TIM_ICInitStructure.TIM_Channel = TIM_Channel_1;
TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
TIM_ICInitStructure.TIM_ICFilter = 10;
TIM_ICInit(TIM3, &TIM_ICInitStructure);

2. 硬件PWM刹车

// 紧急停止时强制输出低电平
void PWM_Brake() {
    GPIO_ResetBits(GPIOB, GPIO_Pin_4 | GPIO_Pin_5);
}

参考代码 STM32F103控制的两路PWM输出 www.youwenfan.com/contentcnr/103639.html

六、完整工程配置

  1. CubeMX配置流程

    • 选择STM32F103C8T6

    • 启用TIM3定时器

    • 配置通道1和2为PWM模式

    • 设置时钟树(HSE=8MHz, PLL=9倍频)

  2. Keil工程结构

    Project/
    ├── Core/
    │   ├── Inc/ (头文件)
    │   └── Src/ (源文件)
    ├── Drivers/
    │   ├── CMSIS/
    │   └── STM32F1xx_HAL_Driver/
    └── Middlewares/
        └── USB_Device/
    
posted @ 2026-02-26 16:16  小前端攻城狮  阅读(3)  评论(0)    收藏  举报