基於STM32F767兩路互補SPWM波(HAL庫)


SPWM波指的是占空比呈正弦規律變化的PWM波,生成方式是在定時器中斷中調整PWM波的占空比。

對於互補的兩路SPWM波,一路為低電平 ‘0’ 時,另一路為高電平 ‘1’,即兩路是互補的。

對於STM32F7,使用高級定時器TIM1可以方便地生成互補SPWM波。步驟如下:

1、確定載波周期 Tc,也即是每個SPWM波的周期。對於逆變電路,常采用20kHz,也即 Tc =  50us;

2、確定基波周期 Tb,此處取50Hz,即 Tb = 20ms;

3、計算取點數N,Tb / Tc = 20ms/50us = 4000;半個周期內則為  N = 2000點;

4、計算占空比,Di = sin(i*pi / N), i = 1, 2, 3, ..., N;

5、確定最大最小占空比,例如最小占空比 Dmin = 0,最大占空比Dmax = 100%;

6、計算並修改定時器的比較值。將占空比為0%時,定時器的比較值設置為Cmin = 0;將占空比為100%時,定時器的比較值設為Cmax = 5399;則每中斷一次,占空比的值設為 Cmax*Di,直接在中斷里完成計算。

根據以上計算,可以修改最小占空比和最大占空比,也可以修改基波與載波頻率。

以下是具體定時器配置與中斷服務函數程序,基於STM32F767IGBT:

 

//使用高級定時器 1 完成
//Update--2019.6.3
//sin_k =    TIM1_ARR / 200.0 * (float)(spwm_max_duty - spwm_min_duty ) ;    //正弦波的比例系數,一個簡單的數學代換
//sin_b = TIM1_ARR / 200.0 * (float)(spwm_max_duty + spwm_min_duty ) ; //正弦波的截距
    
#include "timer1.h"
#include "led.h"
#include "math.h"

TIM_HandleTypeDef      TIM1_Handler;         //定時器句柄 
TIM_OC_InitTypeDef     TIM1_CH1Handler;     //定時器3通道4句柄
TIM_BreakDeadTimeConfigTypeDef BreakDeadTime_Config;

#define PWM_GPIO        GPIOA
#define PWM_PIN1        GPIO_PIN_8      
#define PWM_PIN2        GPIO_PIN_7

#define TIM1_ARR        5399

//SPWM波相關計算
//sin_points -- 一個周期內中斷計算的正弦點數,20KHz載波,Tc = 50us,基波周期 Tb = 50us * sin_points
//Tb = 20Hz  = 50ms = 50,000us, sin_points = 1000
//Tb = 100Hz = 10ms = 10,000us , sin_points =  200

//(-sin_k + sin_b ) / TIM1_ARR = spwm_min_duty %
//( sin_k + sin_b ) / TIM1_ARR = spwm_max_duty %,反解出 sin_k, sin_b
// sin_k = TIM1_ARR / 200.0 * (float)(spwm_max_duty - spwm_min_duty )
// sin_b = TIM1_ARR / 200.0 * (float)(spwm_max_duty + spwm_min_duty )        

uint8_t   spwm_min_duty    =    10;                    //SPWM波最小占空比
uint8_t   spwm_max_duty    =    90;                  //SPWM波最大占空比

uint16_t  count = 0;
uint16_t  sin_points =    200;
uint16_t  cc1_value;                                    //比較寄存器 1的值,修改改變占空比

float          sin_k,sin_b;


//TIM1 PWM部分初始化 
//PWM輸出初始化
//arr:自動重裝值
//psc:時鍾預分頻數
void TIM1_PWM_Init(u16 arr,u16 psc)
{ 
      //時鍾配置
    TIM1_Handler.Instance = TIM1;            //定時器3
    TIM1_Handler.Init.Prescaler = psc;       //定時器分頻
    TIM1_Handler.Init.CounterMode=TIM_COUNTERMODE_UP;//向上計數模式
    TIM1_Handler.Init.Period=arr;          //自動重裝載值
    TIM1_Handler.Init.ClockDivision=TIM_CLOCKDIVISION_DIV1;
    HAL_TIM_PWM_Init(&TIM1_Handler);       //初始化PWM,會調用HAL_TIM_PWM_Init(*)
    
    
      //PWM配置
    TIM1_CH1Handler.OCMode=TIM_OCMODE_PWM1; //模式選擇PWM1
    TIM1_CH1Handler.Pulse=arr/2;            //設置比較值,此值用來確定占空比,默認比較值為自動重裝載值的一半,即占空比為50%
    TIM1_CH1Handler.OCPolarity = TIM_OCPOLARITY_HIGH;//輸出比較極性為高         
    TIM1_CH1Handler.OCNPolarity = TIM_OCPOLARITY_HIGH;
    TIM1_CH1Handler.OCIdleState = TIM_OCIDLESTATE_SET;
    TIM1_CH1Handler.OCNIdleState = TIM_OCIDLESTATE_SET;
    HAL_TIM_PWM_ConfigChannel(&TIM1_Handler,&TIM1_CH1Handler,TIM_CHANNEL_1);//配置TIM1通道1
      
     //死區時間配置
     //https://blog.csdn.net/DZRYWYBL/article/details/82527889 
    BreakDeadTime_Config.OffStateRunMode = TIM_OSSR_DISABLE;  
    BreakDeadTime_Config.OffStateIDLEMode = TIM_OSSI_DISABLE;  
    BreakDeadTime_Config.LockLevel = TIM_LOCKLEVEL_OFF;  
    BreakDeadTime_Config.DeadTime = 0X00; //0x00~0xFF,當設置為0xFF時,50us周期,約有4.68us死區時間;0x0F約有100ns死區時間
    BreakDeadTime_Config.BreakState = TIM_BREAK_DISABLE;  
    BreakDeadTime_Config.BreakPolarity = TIM_BREAKPOLARITY_HIGH;  
    BreakDeadTime_Config.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;  
    HAL_TIMEx_ConfigBreakDeadTime(&TIM1_Handler, &BreakDeadTime_Config);


     //中斷配置
    HAL_NVIC_SetPriority(TIM1_CC_IRQn,1,3);    //設置中斷優先級,搶占優先級1,子優先級3
    HAL_NVIC_EnableIRQ(TIM1_CC_IRQn);          //開啟ITM3中斷  
    //開啟PWM並使能中斷
    HAL_TIM_PWM_Start_IT(&TIM1_Handler, TIM_CHANNEL_1); //開啟PWM輸出並使能中斷
    HAL_TIMEx_PWMN_Start(&TIM1_Handler, TIM_CHANNEL_1); //打開互補通道
}

//定時器底層驅動,時鍾使能,引腳配置
//此函數會被HAL_TIM_PWM_Init()調用
//htim:定時器句柄
void HAL_TIM_PWM_MspInit(TIM_HandleTypeDef *htim)
{
    GPIO_InitTypeDef GPIO_Initure;
    __HAL_RCC_TIM1_CLK_ENABLE();            //使能定時器3
    __HAL_RCC_GPIOA_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    
    GPIO_Initure.Pin=PWM_PIN1 | PWM_PIN2;   //PWM Pin
    GPIO_Initure.Mode=GPIO_MODE_AF_PP;      //復用推完輸出
    GPIO_Initure.Pull=GPIO_PULLUP;          //上拉
    GPIO_Initure.Speed=GPIO_SPEED_HIGH;     //高速
    GPIO_Initure.Alternate=GPIO_AF1_TIM1;   //PA8復用為TIM1_CH1
    HAL_GPIO_Init(PWM_GPIO,&GPIO_Initure); 
      
}

//設置TIM通道4的占空比
//compare:比較值
void TIM_SetTIM1Compare1(u32 compare)
{
    TIM1->CCR1=compare; 
}


//定時器1中斷服務函數
void TIM1_CC_IRQHandler(void)    //注意名稱與通用計時器不同,多了 CC
{
    HAL_TIM_IRQHandler(&TIM1_Handler);
}

//定時器1中斷服務函數調用
void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)
{
    if(htim==(&TIM1_Handler))
    {
          count ++;
          if(count ==  sin_points)
              count = 0;
                
          sin_k =    TIM1_ARR / 200.0 * (float)(spwm_max_duty - spwm_min_duty ) ;    //正弦波的比例系數,一個簡單的數學代換//更正為相減
          sin_b = TIM1_ARR / 200.0 * (float)(spwm_max_duty + spwm_min_duty ) ;       //正弦波的截距//更正為相加
          cc1_value = (uint16_t) (sin_k * sin( (double)count * 6.28318 / (double)sin_points) + sin_b);    //正弦值計算,得到SPWM波占空比
          TIM_SetTIM1Compare1(cc1_value);
    }
}

 主函數配置為

TIM1_PWM_Init(5400-1,2-1);     //216M / (5400 * 2 ) = 20K

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM