STM32 TIM 多通道互补PWM波形输出配置快速入门

2024-05-18 18:32

本文主要是介绍STM32 TIM 多通道互补PWM波形输出配置快速入门,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

platformstm32f10xxx
libSTM32F10x_StdPeriph_Lib_V3.5.0

前言

在做三相逆变的时候,需要软件生成SVPWM波形,具体的算法需要产生三对互补的PWM,这样可以驱动六个开关元件,stm32f103中的TIM1高级定时器支持产生三路互补PWM波形,下面进一步学习。

PWM产生的原理

TIM1OC模块,可以产生PWM波形,具体步骤;

  • 寄存器TIMx CNT每过一个时钟周期就会加1
  • 然后TIMx CNT的值与TIMx CCER进行比较;
  • 最终改变OC上的有效电平;
    以上只需要配置好TIM1的寄存器即可,无需再编程干预,当然可以动态修改TIMx CCER的值,从而改变占空比。可以参考下图;
    在这里插入图片描述

PWM模式

这里主要对PWM模式进行配置的时候做一下区分,存在以下两种情况;

  • TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
  • TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM2;

那么TIM_OCMode_PWM1TIM_OCMode_PWM2有什么区别呢?

  • TIM_OCMode_PWM1 PWM模式1
    在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平
    在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效 电平(OC1REF=1)。
  • TIM_OCMode_PWM2 PWM模式2
    在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平
    在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。

死区插入和刹车功能

互补PWM还支持插入死区时间,最主要的寄存器是TIMx_BDTR,在标准库中把相关的变量封装到TIM_BDTRInitTypeDef结构体中;具体如下;

typedef struct
{uint16_t TIM_OSSRState;        /*!< Specifies the Off-State selection used in Run mode.This parameter can be a value of @ref OSSR_Off_State_Selection_for_Run_mode_state */uint16_t TIM_OSSIState;        /*!< Specifies the Off-State used in Idle state.This parameter can be a value of @ref OSSI_Off_State_Selection_for_Idle_mode_state */uint16_t TIM_LOCKLevel;        /*!< Specifies the LOCK level parameters.This parameter can be a value of @ref Lock_level */ uint16_t TIM_DeadTime;         /*!< Specifies the delay time between the switching-off and theswitching-on of the outputs.This parameter can be a number between 0x00 and 0xFF  */uint16_t TIM_Break;            /*!< Specifies whether the TIM Break input is enabled or not. This parameter can be a value of @ref Break_Input_enable_disable */uint16_t TIM_BreakPolarity;    /*!< Specifies the TIM Break Input pin polarity.This parameter can be a value of @ref Break_Polarity */uint16_t TIM_AutomaticOutput;  /*!< Specifies whether the TIM Automatic Output feature is enabled or not. This parameter can be a value of @ref TIM_AOE_Bit_Set_Reset */
} TIM_BDTRInitTypeDef;

相关的含义看注释可以知道大概意思;这里整理了几个比较重要的变量;

  • 死区时间TIM_DeadTime的计算;TIMx_BDTR的低八位的配置决定了死区的时间;
    UTG[7:0]: 死区发生器设置 (Dead-time generator setup)
    这些位定义了插入互补输出之间的死区持续时间。假设DT表示其持续时间:
DTG[7:5]=0xx => DT=DTG[7:0] × TdtgTdtg = TDTS;
DTG[7:5]=10x => DT=(64+DTG[5:0]) × TdtgTdtg = 2 × TDTS;
DTG[7:5]=110 => DT=(32+DTG[4:0]) × TdtgTdtg = 8 × TDTS;
DTG[7:5]=111 => DT=(32+DTG[4:0])× TdtgTdtg = 16 × TDTS;

例:若TDTS = 125ns(8MHZ),可能的死区时间为:
0到15875ns,若步长时间为125ns;
16us到31750ns,若步长时间为250ns;
32us到63us,若步长时间为1us;
64us到126us,若步长时间为2us;
注:一旦LOCK级别(TIMx_BDTR寄存器中的LOCK位)设为1、 2或3,则不能修改这些位。

  • TIM_Break 则表示是否决定使用刹车,如果发生错误,则可以通过刹车,第一时间停止PWM波形的产生,从而保证了系统的安全性;

代码实现

#include "stm32f10x.h"
#include "svpwm_driver.h"
#include "stm32f10x_tim.h"
#include "stm32f10x_it.h"
#include <stdio.h>#define SVPWM_USE_BDT 	1
#define USE_HARD_PWM 	1
/*** @brief  Configures the different system clocks.* @param  None* @retval None*/
void pwm_rcc_init(void)
{/* TIM1, GPIOA, GPIOB, GPIOE and AFIO clocks enable */RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_GPIOA | RCC_APB2Periph_AFIO |RCC_APB2Periph_GPIOB, ENABLE);
}void pwm_cnt_irq_init(void)
{}/*** @brief  Configure the TIM1 Pins.* @param  None* @retval None* @note*			PA8 /T1_CH1  ---> HIn3*			PA9 /T1_CH2  ---> HIn2*			PA10/T1_CH3  ---> HIn1*										Out2 ---> PA0/ADC0*										Out3 ---> PA1/ADC1*			PB15/T1_CHN3 ---> LIn1*			PB14/T1_CHN2 ---> LIn2*			PB13/T1_CHN1 ---> LIn3*/
void pwm_pin_init(void)
{GPIO_InitTypeDef GPIO_InitStructure;/* GPIOA Configuration: Channel 1, 2 and 3 as alternate function push-pull */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 ;GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOA, &GPIO_InitStructure);/* GPIOB Configuration: Channel 1N, 2N and 3N as alternate function push-pull */GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;GPIO_Init(GPIOB, &GPIO_InitStructure);
}void pwm_tim_init(void){TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;TIM_OCInitTypeDef  TIM_OCInitStructure;TIM_BDTRInitTypeDef      TIM_BDTRInitStructure;
//	NVIC_InitTypeDef 	NVIC_InitStructure;uint16_t TimerPeriod = 0;uint16_t Channel1Pulse = 0, Channel2Pulse = 0, Channel3Pulse = 0;/* TIM1 Configuration ---------------------------------------------------Generate 7 PWM signals with 4 different duty cycles:TIM1CLK = SystemCoreClock, Prescaler = 0, TIM1 counter clock = SystemCoreClockSystemCoreClock is set to 72 MHz for Low-density, Medium-density, High-densityand Connectivity line devices and to 24 MHz for Low-Density Value line andMedium-Density Value line devicesThe objective is to generate 7 PWM signal at 17.57 KHz:- TIM1_Period = (SystemCoreClock / 17570) - 1The channel 1 and channel 1N duty cycle is set to 50%The channel 2 and channel 2N duty cycle is set to 50%The channel 3 and channel 3N duty cycle is set to 50%The Timer pulse is calculated as follows:- ChannelxPulse = DutyCycle * (TIM1_Period - 1) / 100----------------------------------------------------------------------- */TimerPeriod = (SYS_FRQ / PWM_FRQ ) - 1;/* Compute CCR1 value to generate a duty cycle at 50% for channel 1 and 1N */Channel1Pulse = (uint16_t) (((uint32_t) PWM_DUTY * (TimerPeriod - 1)) / 100);/* Compute CCR2 value to generate a duty cycle at 37.5%  for channel 2 and 2N */Channel2Pulse = (uint16_t) (((uint32_t) PWM_DUTY * (TimerPeriod - 1)) / 100);/* Compute CCR3 value to generate a duty cycle at 25%  for channel 3 and 3N */Channel3Pulse = (uint16_t) (((uint32_t) PWM_DUTY * (TimerPeriod - 1)) / 100);//TIM_DeInit(TIM1);/* Time Base configuration */TIM_TimeBaseStructure.TIM_Prescaler = TIM_PSCReloadMode_Update;//TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;//TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned2;TIM_TimeBaseStructure.TIM_Period = TimerPeriod;TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;TIM_TimeBaseStructure.TIM_RepetitionCounter = 0;TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);/*TIM_ClearFlag(TIM1, TIM_FLAG_Update);TIM_ITConfig(TIM1,TIM_IT_Update, ENABLE);NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x02;NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;NVIC_Init(&NVIC_InitStructure);	*//* Channel 1, 2, 3 Configuration in PWM mode */#if USE_HARD_PWM/**	TIM_OCMode_PWM1	PWM模式1在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为有效电平,否则为无效电平在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为无效电平(OC1REF=0),否则为有效 电平(OC1REF=1)。TIM_OCMode_PWM2 PWM模式2在向上计数时,一旦TIMx_CNT<TIMx_CCR1时通道1为无效电平,否则为有效电平在向下计数时,一旦TIMx_CNT>TIMx_CCR1时通道1为有效电平,否则为无效电平。*/	TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;TIM_OCInitStructure.TIM_Pulse = Channel1Pulse;TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCPolarity_High;TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Reset;TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCIdleState_Reset;TIM_OC1Init(TIM1, &TIM_OCInitStructure);TIM_OCInitStructure.TIM_Pulse = Channel2Pulse;TIM_OC2Init(TIM1, &TIM_OCInitStructure);TIM_OCInitStructure.TIM_Pulse = Channel3Pulse;TIM_OC3Init(TIM1, &TIM_OCInitStructure);TIM_OC1PreloadConfig(TIM1,TIM_OCPreload_Enable);TIM_OC2PreloadConfig(TIM1,TIM_OCPreload_Enable);TIM_OC3PreloadConfig(TIM1,TIM_OCPreload_Enable);#endif	#if SVPWM_USE_BDTTIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_OFF;TIM_BDTRInitStructure.TIM_DeadTime = 30;TIM_BDTRInitStructure.TIM_Break = TIM_Break_Disable;			   TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_Low;TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Disable;TIM_BDTRConfig(TIM1, &TIM_BDTRInitStructure);
#endif	TIM_CCPreloadControl(TIM1,ENABLE);/* TIM1 counter enable */	TIM_Cmd(TIM1, ENABLE);/* TIM1 Main Output Enable */TIM_CtrlPWMOutputs(TIM1, ENABLE);
}void pwm_init(void){pwm_rcc_init();pwm_pin_init();pwm_cnt_irq_init();pwm_tim_init();
}int32_t get_pwm_period(void){return (int32_t)((SYS_FRQ / PWM_FRQ ) - 1);
}void pwm_reset_duty_cnt(uint8_t index, int16_t cnt){if(cnt <= 0){cnt = get_pwm_period()/2;}switch(index){case 1:TIM1->CCR1 = (uint16_t)cnt;break;case 2:TIM1->CCR2 = (uint16_t)cnt;break;case 3:TIM1->CCR3 = (uint16_t)cnt;		break;}	
}void pwm_disable(void){TIM_CtrlPWMOutputs(TIM1, DISABLE);
}void pwm_enable(void){TIM_CtrlPWMOutputs(TIM1, ENABLE);
}

以上代码主要实现以下几个功能;

  • IM1定时器时钟,使用中央对齐模式1,则会产生上溢信号;
  • PWM模式设置为TIM_OCMode_PWM1
  • 加入了死区;
  • 占空比 50%;
    具体如下图所示;
    在这里插入图片描述
    在这里插入图片描述

参考

http://www.stmcu.org.cn/module/forum/thread-613602-1-1.html

这篇关于STM32 TIM 多通道互补PWM波形输出配置快速入门的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/995652

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

Zookeeper安装和配置说明

一、Zookeeper的搭建方式 Zookeeper安装方式有三种,单机模式和集群模式以及伪集群模式。 ■ 单机模式:Zookeeper只运行在一台服务器上,适合测试环境; ■ 伪集群模式:就是在一台物理机上运行多个Zookeeper 实例; ■ 集群模式:Zookeeper运行于一个集群上,适合生产环境,这个计算机集群被称为一个“集合体”(ensemble) Zookeeper通过复制来实现

CentOS7安装配置mysql5.7 tar免安装版

一、CentOS7.4系统自带mariadb # 查看系统自带的Mariadb[root@localhost~]# rpm -qa|grep mariadbmariadb-libs-5.5.44-2.el7.centos.x86_64# 卸载系统自带的Mariadb[root@localhost ~]# rpm -e --nodeps mariadb-libs-5.5.44-2.el7

hadoop开启回收站配置

开启回收站功能,可以将删除的文件在不超时的情况下,恢复原数据,起到防止误删除、备份等作用。 开启回收站功能参数说明 (1)默认值fs.trash.interval = 0,0表示禁用回收站;其他值表示设置文件的存活时间。 (2)默认值fs.trash.checkpoint.interval = 0,检查回收站的间隔时间。如果该值为0,则该值设置和fs.trash.interval的参数值相等。

NameNode内存生产配置

Hadoop2.x 系列,配置 NameNode 内存 NameNode 内存默认 2000m ,如果服务器内存 4G , NameNode 内存可以配置 3g 。在 hadoop-env.sh 文件中配置如下。 HADOOP_NAMENODE_OPTS=-Xmx3072m Hadoop3.x 系列,配置 Nam

wolfSSL参数设置或配置项解释

1. wolfCrypt Only 解释:wolfCrypt是一个开源的、轻量级的、可移植的加密库,支持多种加密算法和协议。选择“wolfCrypt Only”意味着系统或应用将仅使用wolfCrypt库进行加密操作,而不依赖其他加密库。 2. DTLS Support 解释:DTLS(Datagram Transport Layer Security)是一种基于UDP的安全协议,提供类似于

电脑桌面文件删除了怎么找回来?别急,快速恢复攻略在此

在日常使用电脑的过程中,我们经常会遇到这样的情况:一不小心,桌面上的某个重要文件被删除了。这时,大多数人可能会感到惊慌失措,不知所措。 其实,不必过于担心,因为有很多方法可以帮助我们找回被删除的桌面文件。下面,就让我们一起来了解一下这些恢复桌面文件的方法吧。 一、使用撤销操作 如果我们刚刚删除了桌面上的文件,并且还没有进行其他操作,那么可以尝试使用撤销操作来恢复文件。在键盘上同时按下“C

【Python编程】Linux创建虚拟环境并配置与notebook相连接

1.创建 使用 venv 创建虚拟环境。例如,在当前目录下创建一个名为 myenv 的虚拟环境: python3 -m venv myenv 2.激活 激活虚拟环境使其成为当前终端会话的活动环境。运行: source myenv/bin/activate 3.与notebook连接 在虚拟环境中,使用 pip 安装 Jupyter 和 ipykernel: pip instal

数论入门整理(updating)

一、gcd lcm 基础中的基础,一般用来处理计算第一步什么的,分数化简之类。 LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; } <pre name="code" class="cpp">LL lcm(LL a, LL b){LL c = gcd(a, b);return a / c * b;} 例题:

Java 创建图形用户界面(GUI)入门指南(Swing库 JFrame 类)概述

概述 基本概念 Java Swing 的架构 Java Swing 是一个为 Java 设计的 GUI 工具包,是 JAVA 基础类的一部分,基于 Java AWT 构建,提供了一系列轻量级、可定制的图形用户界面(GUI)组件。 与 AWT 相比,Swing 提供了许多比 AWT 更好的屏幕显示元素,更加灵活和可定制,具有更好的跨平台性能。 组件和容器 Java Swing 提供了许多