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 = ; //SPWM波最小占空比
uint8_t spwm_max_duty = ; //SPWM波最大占空比 uint16_t count = ;
uint16_t sin_points = ;
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/; //设置比较值,此值用来确定占空比,默认比较值为自动重装载值的一半,即占空比为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
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 = ; 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(-,-);     //216M / (5400 * 2 ) = 20K

基于STM32F767两路互补SPWM波(HAL库)的更多相关文章

  1. STM32高级定时器TIM1产生两路互补的PWM波(带死区)

    测试环境:Keil 5.20.0.0 STM32F103RBT6 固件库版本:STM32F10x_StdPeriph_Lib_V3.5.0(2011) 本文使用TIM1的通道1,通道2,产生两路1kh ...

  2. 【书籍连载】《STM32 HAL 库开发实战指南—基于F7》-第一章

    从今天起,每天开始连载一章<STM32 HAL 库开发实战指南—基于F7>.欢迎各位阅读.点评.学习. 第1章  如何使用本书 1.1  本书的参考资料 本书参考资料为:<STM32 ...

  3. stm32电机控制之控制两路直流电机

    小车使用的电机是12v供电的直流电机,带编码器反馈,这样就可以采用闭环速度控制,这里电机使用PWM驱动,速度控制框图如下: 由以上框图可知,STM32通过定时器模块输出PWM波来控制两个直流电机的转动 ...

  4. STM32 ADC多通道转换DMA模式与非DMA模式两种方法(HAL库)

    一.非DMA模式(转) 说明:这个是自己刚做的时候百度出来的,不是我自己做出来的,因为感觉有用就保存下来做学习用,原文链接:https://blog.csdn.net/qq_24815615/arti ...

  5. 125-FMC125-两路125Msps AD,两路160Msps DA FMC子卡模块

    FMC125-两路125Msps AD,两路160Msps DA FMC子卡模块 1.板卡概述  该板卡可实现2路14bit 250Msps AD 和2路16bit 160MspsDA功能,FMC连接 ...

  6. 新建基于STM32F103ZET6的工程-HAL库版本

    1.STM32F103ZET6简介 STM32F103ZET6的FLASH容量为512K,64K的SRAM.按照STM32芯片的容量产品划分,STM32F103ZET6属于大容量的芯片. 2.下载HA ...

  7. stm32电机控制之控制两路直流电机!看完你会了吗

    手头上有一个差分驱动的小车,使用两个直流电机驱动,要实现小车的在给定速度下运动,完成直线行驶,转向,加速,刹车等复杂运动. 使用的电机是12v供电的直流电机,带编码器反馈,这样就可以采用闭环速度控制, ...

  8. STM32基于HAL库通过DMA读写SDIO

    通过STM32CUBEMX生成DMA读写sdio的工程,再读写过程中总会卡死在DMA中断等待读写完成的while中,最终发现while等待的标志在SDIO的中断里置位的,而SDIO中断优先级如果小于或 ...

  9. FPGA图像处理 两路sensor的色调不一致

    怎么调?可以让两路sensor的色调一致.

随机推荐

  1. gethostname、gethostbyname

    gethostname():返回本地主机的标准主机名 原型: #include<unistd.h> int gethostname(char *name, size_t len); 参数说 ...

  2. Mongoose 数据校验

    什么是mongoose数据校验 用户通过mongoose给mongodb数据库增加数据的时候,对数据的合法性进行的验证 mongoose里面定义Schema:字段类型,修饰符.默认参数 .数据校验都是 ...

  3. K8S集群搭建——基于CentOS 7系统

    环境准备集群数量此次使用3台CentOS 7系列机器,分别为7.3,7.4,7.5 节点名称 节点IPmaster 192.168.0.100node1 192.168.0.101node2 192. ...

  4. layui之table.render使用(含后台详细代码实现)

    效果图如下: 前端实现代码如图(完整代码): <!DOCTYPE html> <html> <head> <meta charset="utf-8& ...

  5. Mysql中联合索引的最左匹配原则(百度)

    创建联合索引时列的选择原则 经常用的列优先(最左匹配原则) 离散度高的列优先(离散度高原则) 宽度小的列优先(最少空间原则) 在Mysql建立多列索引(联合索引)有最左前缀的原则,即最左优先.如果我们 ...

  6. Python3+mitmproxy安装使用教程(Windows)(转载)

    mitmproxy 是用于MITM的proxy,MITM中间人攻击.说白了就是服务器和客户机中间通讯多增加了一层.跟Fiddler和Charles最大的不同就是,mitmproxy可以进行二次开发,尤 ...

  7. Cesium原理篇:GroundPrimitive【转】

    今天来看看GroundPrimitive,选择GroundPrimitive有三个目的:1 了解GroundPrimitive和Primitive的区别和关系 2 createGeometry的特殊处 ...

  8. Druid: A Real-time Analytical Data Store

    Druid一种实时数仓,针对的场景和目的,如下比较明确 Druid was originally designed to solve problems around ingesting and exp ...

  9. spring boot允许跨域(CORS)的配置

    添加@Configuration配置类即可. @Configuration public class WebMvcConfig extends WebMvcConfigurationSupport { ...

  10. PHP 简易网页访问统计

    传统的网页访问统计,已经有很多,如 51la.百度统计.站长统计 一般都需要引用JS,在你的网页内嵌入JS,这个操作存在风险,并且不可控. 可以考虑使用 [img src.css src.link h ...