搜了一大堆,网上基本都是F103的例子,F4的很少,然而又需要用到,这里发一下调试过程吧
首先看一下什么是互补的PWM,直接上图,第二张是把Y轴移动了一下,方便理解(Multisim仿真截图),我的简单理解就是当A输出1B输出0,我高的时候你低,你低的时候我高。他们两的频率是一样的,振幅也是一样的。
1.关于输出通道问题
由《STM32F4xx中文参考手册》可知(见下图),只有高级定时器TIM1和TIM8可以输出两路互补信号。其中OCx为主输出,OCxN为互补输出。这句话的意思是:如果我用TIM1输出两路互补的PWM信号。TIM1_CH1为主输出,那么TIM1_CH1N为互补输出。这是固定的。
我在这里使用的是TIM1的通道1,查数据手册可知,用到的引脚为PA8(主输出),PA7(互补输出)。注:我的芯片为STM32F407VET6.
2.库函数配置
step1:结构体
// 结构体声明
GPIO_InitTypeDef GPIO_InitStructure; // GPIO
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; // 定时器
TIM_OCInitTypeDef TIM_OCInitStructure; // 通道
TIM_BDTRInitTypeDef TIM_BDTRStructure; // 刹车与死区
step2:时钟配置
// 时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); // TIM1时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); // 使能GPIOA时钟
step3:时钟配置
// IO复用
GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_TIM1); // GPIOA7_8复用为定时器1
// IO复用
GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_TIM1); // GPIOA7_8复用为定时器1
step4:GPIO配置
// GPIO配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8; // 引脚
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; // 复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; // 速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; // 推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; // 上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); // 配置
step5:定时器1配置
// 定时器配置
TIM_TimeBaseStructure.TIM_Prescaler=84-1; // 定时器分频84M/84=1M
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; // 向上计数模式
TIM_TimeBaseStructure.TIM_Period=25000-1; // 自动重装载值25000,1M / 25000 =40Hz
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);// 初始化定时器1
step6:死区和刹车配置
死区:在这里理解为翻转变化时给的一个延时,如下图所示,
刹车: 这里没有用到,不做赘述,大概意思是可以通过这个功能切断所有输出。
// 刹车死区配置
TIM_BDTRStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable;// 自动输出功能使能
TIM_BDTRStructure.TIM_Break=TIM_Break_Disable;//失能刹车输入
//TIM_BDTRStructure.TIM_BreakPolarity=TIM_BreakPolarity_High; //刹车输入管脚极性高
TIM_BDTRStructure.TIM_DeadTime=168; //输出打开和关闭状态之间的延时 84M/84=1us,84M/168=2us
TIM_BDTRStructure.TIM_LOCKLevel=TIM_LOCKLevel_OFF;// 锁电平参数: 不锁任何位
TIM_BDTRStructure.TIM_OSSIState=TIM_OSSIState_Disable; //设置在运行模式下非工作状态选项
TIM_BDTRStructure.TIM_OSSRState=TIM_OSSRState_Disable; //设置在运行模式下非工作状态选项
TIM_BDTRConfig(TIM3,&TIM_BDTRStructure);
死区时间配置及计算见下图:
TIM_BDTRStructure.TIM_DeadTime=0x01; //死区时间1us
通过查找STM32F4的应用手册,我们可以看到,死区时间由寄存器BDTR的位UTG[7:0]控制,如下图所示,死区时间等于步长(Tdts)乘以用户设定的数字。
step7:PWM输出配置
// 定时器比较输出通道配置
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_Pulse=0; //占空比:12500/25000*100%=50%
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; //输出极性高
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; //输出使能
TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Reset; // 输出空闲电平低
// 互补输出配置
TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Enable; //互补输出使能
TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_High; // 互补端输出极性高
TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Reset; //互补输出空闲电平低
TIM_OC1Init(TIM1, &TIM_OCInitStructure); // OC1
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable); //配置
3.实验结果
使用示波器对IO口进行测量,调至合适位置,用手机拍照记录如下:
全部代码如下:
// 函数名:TIM1_PWM_Init
// 参 数:None
// 返回值:None
// 描 述:使用TIM1的通道1输出两路互补的PWM
// 说 明:参考正点原子,野火论坛,在此感谢
void TIM1_PWM_Init()
{
// 结构体声明
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRStructure;
// 时钟使能
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE); //TIM3时钟使能
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTC时钟
// IO复用
GPIO_PinAFConfig(GPIOA,GPIO_PinSource8,GPIO_AF_TIM1); //
GPIO_PinAFConfig(GPIOA,GPIO_PinSource7,GPIO_AF_TIM1); //
// IO配置
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7 | GPIO_Pin_8;//6脚未使用
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; //复用功能
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; //速度100MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; //推挽复用输出
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP; //上拉
GPIO_Init(GPIOA,&GPIO_InitStructure); //初始化PF9
GPIO_ResetBits(GPIOA,GPIO_Pin_6); //拉低刹车
// 定时器配置
TIM_TimeBaseStructure.TIM_Prescaler=84-1; //自动重装载值1M / 25000 =40Hz
TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式
TIM_TimeBaseStructure.TIM_Period=25000-1; //定时器分频84M/84=1M
TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1;
TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure);//初始化定时器1
// 定时器比较输出通道配置
TIM_OCInitStructure.TIM_OCMode=TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_Pulse=0; //占空比:12500/25000*100%=50%
TIM_OCInitStructure.TIM_OCPolarity=TIM_OCPolarity_High; //输出极性高
TIM_OCInitStructure.TIM_OutputState=TIM_OutputState_Enable; //输出使能
TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Reset; // 输出空闲电平低
// 互补输出配置
TIM_OCInitStructure.TIM_OutputNState=TIM_OutputNState_Enable; //互补输出使能
TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_High; // 互补端输出极性高
TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Reset; //互补输出空闲电平低
TIM_OC1Init(TIM1, &TIM_OCInitStructure); // OC1
TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable); //配置
// 刹车死区配置
TIM_BDTRStructure.TIM_AutomaticOutput=TIM_AutomaticOutput_Enable;// 自动输出功能使能
TIM_BDTRStructure.TIM_Break=TIM_Break_Disable;//失能刹车输入
TIM_BDTRStructure.TIM_BreakPolarity=TIM_BreakPolarity_High; //刹车输入管脚极性高
TIM_BDTRStructure.TIM_DeadTime=0; //输出打开和关闭状态之间的延时 84-1us 168-2us
TIM_BDTRStructure.TIM_LOCKLevel=TIM_LOCKLevel_OFF;// 锁电平参数: 不锁任何位
TIM_BDTRStructure.TIM_OSSIState=TIM_OSSIState_Disable; //设置在运行模式下非工作状态选项
TIM_BDTRStructure.TIM_OSSRState=TIM_OSSRState_Disable; //设置在运行模式下非工作状态选项
TIM_BDTRConfig(TIM1,&TIM_BDTRStructure);
TIM_ARRPreloadConfig(TIM1,ENABLE);//ARPE使能
TIM_Cmd(TIM1, ENABLE); //使能TIM3
TIM_CtrlPWMOutputs(TIM1, ENABLE); //开启OC和OCN输出
}
//主函数
int main(void)
{
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200);//初始化串口波特率为115200
TIM1_PWM_Init(); //84M/84=1Mhz的计数频率,重装载值500,所以PWM频率为 1M/500=2Khz. 40
while(1)
{
TIM_SetCompare1(TIM1,12500); //修改比较值,修改占空比50%
}
}