【STM32】STM32F407互补PWM进阶

您所在的位置:网站首页 互补pwm输出芯片8脚 【STM32】STM32F407互补PWM进阶

【STM32】STM32F407互补PWM进阶

2024-07-10 10:11| 来源: 网络整理| 查看: 265

上一次尝试了STM32F4的PWM互补输出,这次尝试带移相的两对PWM互补输出。

1.相位差的概念

       在这里,我把相位简单理解为延时,当然前提是两个信号彼此之间除了相位差,其他参数都一致。如下图,两信号在一个周期内,两波峰(或波谷)的时间差,就是相位差。而习惯上用弧度方式表示,如果两信号相位差位π/2,那么就是相差1/4个周期,这个很好理解,一圈为2π,π/2当然就是1/4了。

2.思路

         互补PWM使用高级定时器TIM1和TIM8产生,均使用CH1和CH1N通道,上一篇文章有提到,这里就不再赘述。这两个定时器相互之间是独立的,我把参数配置成一样的时候,可以发现他们几乎是相同的。所以大概的思路就是在TIM1产生PWM之后,延时一会再由TIM8产生PWM,当然直接使用delay_ms()肯定是有误差的,这两个波形有可能会越差越多。

        按照这个思路,继续往下走,通过查看《STM32F4xx中文参考手册》,我们发现定时器具有主从模式,即主机产生一个触发信号(TRGO)时,从机可以响应。在这里,我们可以想象成当TIM1输出PWM,时间达到1/4个周期,产生一个触发信号,使得TIM8的PWM输出被打开。可以通过寄存器配置内部触发,从TIM8到TIM1.下面两张图展示了这一段话。

       那么怎么判断达到1/4个周期呢?想到计数器和定时器其实是一样的,能不能再用一个定时器呢?大可不必,既然定时器有那么多通道,我们干脆拿出一个通道来计时不就好了吗。于是TIM1的CH2,我们用来计时。下面是OC2的配置代码。

// TIM1_OC2配置 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active; // TIM1_OC2REF的模式为高电平有效 TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; // 不需要输出 TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;// 不输出 TIM_OCInitStructure.TIM_Pulse = 12500/2; // 比较值为25000,这里四分之一就是12500/2 TIM_OC2Init(TIM1,&TIM_OCInitStructure); // OC2初始化 TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_OC2Ref); // TRGO源配置为TIM1_CH2 TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable); // 配置自动重载

       上面的代码已经帮我们搞定了触发信号来源,什么时候触发的问题,接下来就是把这个触发信号与TIM8相连接,并产生相应的事件。上代码:TIM1的OC2计数满之后,产生高电平给从定时器TIM8,TIM8配置为复位模式,重新输出PWM

//内部触发配置 void TIM8_IN_Config(void) { TIM_SelectSlaveMode(TIM8,TIM_SlaveMode_Reset); //从模式 复位模式 TIM_SelectInputTrigger (TIM8,TIM_TS_ITR0); //触发源 TIM_TS_ITR0,从TIM8到TIM1 }

3.结果及代码

    使用双通道示波器对TIM1_CH1和TIM2_CH2测量,结果如下图所示,占空比为50%,容易看出两信号相差1/4周期,我们的目标达到,通过修改通道2的比较值TIM_OCInitStructure.TIM_Pulse,可以实现不同相位差(适用于0-180°)

附上完整代码:

//TIM1-CH1 PA8 //TIM1-CHN PA7 //TIM1-OC2 触发源 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; //GPIOC6 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=168-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); //配置 // OC2配置 TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_Active; // TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Disable; // TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Disable;// TIM_OCInitStructure.TIM_Pulse = 12500/2; //相位差90度,既1/4周期 TIM_OC2Init(TIM1,&TIM_OCInitStructure); TIM_SelectOutputTrigger(TIM1,TIM_TRGOSource_OC2Ref); //TRGO输出 TIM_OC2PreloadConfig(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=0x01; //输出打开和关闭状态之间的延时 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输出 } // 定时器8 // PA5-CH1N // PC6-CH1 void TIM8_PWM_Init() { // 结构体声明 GPIO_InitTypeDef GPIO_InitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; TIM_OCInitTypeDef TIM_OCInitStructure; TIM_BDTRInitTypeDef TIM_BDTRStructure; // 时钟使能 RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM8,ENABLE); //TIM3时钟使能 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //使能PORTC时钟 RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOC, ENABLE); //使能PORTC时钟 // IO复用 GPIO_PinAFConfig(GPIOA,GPIO_PinSource5,GPIO_AF_TIM8); // GPIO_PinAFConfig(GPIOC,GPIO_PinSource6,GPIO_AF_TIM8); // // GPIOA GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; //GPIOC6 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 // GPIOC GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; //GPIOC6 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(GPIOC,&GPIO_InitStructure); //初始化PF9 //GPIO_ResetBits(GPIOA,GPIO_Pin_6); //拉低刹车 // 定时器配置 TIM_TimeBaseStructure.TIM_Prescaler=168-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(TIM8,&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(TIM8, &TIM_OCInitStructure); // OC1 TIM_OC1PreloadConfig(TIM8,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=0x01; //输出打开和关闭状态之间的延时 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(TIM8,&TIM_BDTRStructure); TIM_ARRPreloadConfig(TIM8,ENABLE);//ARPE使能 TIM_Cmd(TIM8, ENABLE); //使能TIM3 TIM_CtrlPWMOutputs(TIM8, ENABLE); //开启OC和OCN输出 } //内部触发配置 void TIM8_IN_Config(void) { TIM_SelectSlaveMode(TIM8,TIM_SlaveMode_Reset); //从模式 复位模式 TIM_SelectInputTrigger (TIM8,TIM_TS_ITR0); //触发源 TIM_TS_ITR0,从TIM8到TIM1 } //主函数 TIM1_PWM_Init(); //84M/84=1Mhz的计数频率,重装载值500,所以PWM频率为 1M/500=2Khz. 40 TIM8_PWM_Init(); TIM8_IN_Config(); //触发配置 TIM_SetCompare1(TIM1,12500); //修改比较值,修改占空比 TIM_SetCompare1(TIM8,12500); //修改比较值,修改占空比 while(1) { }

 

参考文章:

1.https://blog.csdn.net/weixin_43128823/article/details/89406246

2.正点原子PWM教程



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3