使用STM32CUBEMX实现SPWM的查表法方法详解

        SPWM称为正弦波脉宽调制,其原理是采用三角波作为载波,正弦波作为调制波合成后生成的等高不等宽的PWM波。在simulink仿真中直接用三角波模块与sine wave合成即可,但对于编程来说比较麻烦,且运算较大占用CPU资源,一般采用查表法来实现正弦波。

 

 可以看到仿真的PWM信号是按照正弦规律变化。关于SPWM的知识不再赘述,下面用CUBEMX实现单片机的SPWM

        我采用了STM32F4系列单片机,主频可以到168MHZ,具体如何配置不再赘述。

        首先需要PWM通道,这里我用了TIM8定时器,SPWM编程的核心思想就是在每个PWM周期改变其占空比。

        这里有两种方法分别是TIM8自带的捕获/比较中断,在一个ARR周期内,当计数值大于CCR后触发中断,进而在中断函数中更新CCR值。而第二种是开启一个SPWM相匹配的定时器中断来实现,比如实现10khz的SPWM就可以配置其他定时器一个10khz的中断,在这个中断里改变占空比。

        这里是TIM8的配置,采用8400是因为第二种方法我采用了TIM2定时器,其APB1总线最大分频只有84MHZ。

        用第一种方法的话需要开启捕获中断,第二种不用。

 第二种方法我采用了TIM2定时器,时钟配置和TIM8一样即可。

 

 配置好后需要正弦表,利用matlab就能实现,这里我直接给出360个采样点,给后面电机电角度用。

volatile float SinTable[360] = {0.000e+00, 1.745e-02, 3.489e-02, 5.233e-02, 6.975e-02, 8.715e-02, 1.045e-01, 1.218e-01, 1.391e-01, 1.564e-01,
	1.736e-01, 1.908e-01, 2.079e-01, 2.249e-01, 2.419e-01, 2.588e-01, 2.756e-01, 2.923e-01, 3.090e-01, 3.255e-01,
	3.420e-01, 3.583e-01, 3.746e-01, 3.907e-01, 4.067e-01, 4.226e-01, 4.383e-01, 4.539e-01, 4.694e-01, 4.848e-01,
	5.000e-01, 5.150e-01, 5.299e-01, 5.446e-01, 5.591e-01, 5.735e-01, 5.877e-01, 6.018e-01, 6.156e-01, 6.293e-01,
	6.427e-01, 6.560e-01, 6.691e-01, 6.819e-01, 6.946e-01, 7.071e-01, 7.193e-01, 7.313e-01, 7.431e-01, 7.547e-01,
	7.660e-01, 7.771e-01, 7.880e-01, 7.986e-01, 8.090e-01, 8.191e-01, 8.290e-01, 8.386e-01, 8.480e-01, 8.571e-01,
	8.660e-01, 8.746e-01, 8.829e-01, 8.910e-01, 8.987e-01, 9.063e-01, 9.135e-01, 9.205e-01, 9.271e-01, 9.335e-01, 
	9.396e-01, 9.455e-01, 9.510e-01, 9.563e-01, 9.612e-01, 9.659e-01, 9.702e-01, 9.743e-01, 9.781e-01, 9.816e-01,
	9.848e-01, 9.876e-01, 9.902e-01, 9.925e-01, 9.945e-01, 9.961e-01, 9.975e-01, 9.986e-01, 9.993e-01, 9.998e-01,
	1.000e+00, 9.998e-01, 9.993e-01, 9.986e-01, 9.975e-01, 9.961e-01, 9.945e-01, 9.925e-01, 9.902e-01, 9.876e-01,
	9.848e-01, 9.816e-01, 9.781e-01, 9.743e-01, 9.702e-01, 9.659e-01, 9.612e-01, 9.563e-01, 9.510e-01, 9.455e-01,
	9.396e-01, 9.335e-01, 9.271e-01, 9.205e-01, 9.135e-01, 9.063e-01, 8.987e-01, 8.910e-01, 8.829e-01, 8.746e-01,
	8.660e-01, 8.571e-01, 8.480e-01, 8.386e-01, 8.290e-01, 8.191e-01, 8.090e-01, 7.986e-01, 7.880e-01, 7.771e-01,
	7.660e-01, 7.547e-01, 7.431e-01, 7.313e-01, 7.193e-01, 7.071e-01, 6.946e-01, 6.819e-01, 6.691e-01, 6.560e-01,
	6.427e-01, 6.293e-01, 6.156e-01, 6.018e-01, 5.877e-01, 5.735e-01, 5.591e-01, 5.446e-01, 5.299e-01, 5.150e-01,
	5.000e-01, 4.848e-01, 4.694e-01, 4.539e-01, 4.383e-01, 4.226e-01, 4.067e-01, 3.907e-01, 3.746e-01, 3.583e-01,
	3.420e-01, 3.255e-01, 3.090e-01, 2.923e-01, 2.756e-01, 2.588e-01, 2.419e-01, 2.249e-01, 2.079e-01, 1.908e-01,
	1.736e-01, 1.564e-01, 1.391e-01, 1.218e-01, 1.045e-01, 8.715e-02, 6.975e-02, 5.233e-02, 3.489e-02, 1.745e-02,
	1.224e-16,-1.745e-02, -3.489e-02, -5.233e-02, -6.975e-02, -8.715e-02, -1.045e-01, -1.218e-01, -1.391e-01, -1.564e-01, 
	-1.736e-01, -1.908e-01, -2.079e-01, -2.249e-01, -2.419e-01, -2.588e-01, -2.756e-01, -2.923e-01, -3.090e-01, -3.255e-01, 
	-3.420e-01, -3.583e-01, -3.746e-01, -3.907e-01, -4.067e-01, -4.226e-01, -4.383e-01, -4.539e-01, -4.694e-01, -4.848e-01,
	-5.000e-01, -5.150e-01, -5.299e-01, -5.446e-01, -5.591e-01, -5.735e-01, -5.877e-01, -6.018e-01, -6.156e-01, -6.293e-01, 
	-6.427e-01, -6.560e-01, -6.691e-01, -6.819e-01, -6.946e-01, -7.071e-01, -7.193e-01, -7.313e-01, -7.431e-01, -7.547e-01, 
	-7.660e-01, -7.771e-01, -7.880e-01, -7.986e-01, -8.090e-01, -8.191e-01, -8.290e-01, -8.386e-01, -8.480e-01, -8.571e-01,
	-8.660e-01, -8.746e-01, -8.829e-01, -8.910e-01, -8.987e-01, -9.063e-01, -9.135e-01, -9.205e-01, -9.271e-01, -9.335e-01, 
	-9.396e-01, -9.455e-01, -9.510e-01, -9.563e-01, -9.612e-01, -9.659e-01, -9.702e-01, -9.743e-01, -9.781e-01, -9.816e-01, 
	-9.848e-01, -9.876e-01, -9.902e-01, -9.925e-01, -9.945e-01, -9.961e-01, -9.975e-01, -9.986e-01, -9.993e-01, -9.998e-01, 
	-1.000e+00,-9.998e-01, -9.993e-01, -9.986e-01, -9.975e-01, -9.961e-01, -9.945e-01, -9.925e-01, -9.902e-01, -9.876e-01, 
	-9.848e-01, -9.816e-01, -9.781e-01, -9.743e-01, -9.702e-01, -9.659e-01, -9.612e-01, -9.563e-01, -9.510e-01, -9.455e-01, 
	-9.396e-01, -9.335e-01, -9.271e-01, -9.205e-01, -9.135e-01, -9.063e-01, -8.987e-01, -8.910e-01, -8.829e-01, -8.746e-01, 
	-8.660e-01, -8.571e-01, -8.480e-01, -8.386e-01, -8.290e-01, -8.191e-01, -8.090e-01, -7.986e-01, -7.880e-01, -7.771e-01, 
	-7.660e-01, -7.547e-01, -7.431e-01, -7.313e-01, -7.193e-01, -7.071e-01, -6.946e-01, -6.819e-01, -6.691e-01, -6.560e-01, 
	-6.427e-01, -6.293e-01, -6.156e-01, -6.018e-01, -5.877e-01, -5.735e-01, -5.591e-01, -5.446e-01, -5.299e-01, -5.150e-01, 
	-5.000e-01, -4.848e-01, -4.694e-01, -4.539e-01, -4.383e-01, -4.226e-01, -4.067e-01, -3.907e-01, -3.746e-01, -3.583e-01, 
	-3.420e-01, -3.255e-01, -3.090e-01, -2.923e-01, -2.756e-01, -2.588e-01, -2.419e-01, -2.249e-01, -2.079e-01, -1.908e-01, 
	-1.736e-01, -1.564e-01, -1.391e-01, -1.218e-01, -1.045e-01, -8.715e-02, -6.975e-02, -5.233e-02, -3.489e-02, -1.745e-02
  }; //正弦表
__IO  float SPWM_Duty1 = 0; //占空比
__IO int16_t sinTab1 = 0;   //SPWM计数值

然后开启定时器

 /* USER CODE BEGIN 2 */
    HAL_TIM_Base_Start_IT(&htim2);
    HAL_TIM_PWM_Start(&htim8,TIM_CHANNEL_1);
  /* USER CODE END 2 */

我只做了一相用于演示,三相会在电机里写。

/* USER CODE BEGIN 4 */

 void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
	 {

			SPWM_Duty1 =4200*(1+0.8*SinTable[sinTab1]); 
			TIM8->CCR1=SPWM_Duty1;
            SPWM_Duty1++;
            if(SPWM_Duty1>= 359)
            {
                  SPWM_Duty1 = 0;
               }

}

/* USER CODE END 4 */

        调制度为0.8,第一段代码的意思是正弦波从0开始对应占空比为50%,因此用4200乘上去,里面0.8是调制度,正弦表是从-1到1的一个数。也就是说PWM分频4200即占空比50%对应0,正弦的1对应8400PWM分频也就是1,如果PWM分频为0就对应-1,最后++来查表步进到360清零。

如果是采用了第一种方法用内部捕获中断将回调函数修改为

void HAL_TIM_OC_DelayElapsedCallback(TIM_HandleTypeDef *htim)

最后初始化阶段开启中断

HAL_TIM_PWM_Start_IT(&htim8,TIM_CHANNEL_1);

 这里放个效果图,是电机驱动信号放大后的,SPWM长这个样子。

物联沃分享整理
物联沃-IOTWORD物联网 » 使用STM32CUBEMX实现SPWM的查表法方法详解

发表评论