基于STM32芯片三路互补PWM输出的设计实现

发布者:DelightWish123最新更新时间:2024-09-02 来源: elecfans关键字:STM32芯片  PWM输出 手机看文章 扫描二维码
随时随地手机看文章

硬件:Stm32f103c8t6最小系统。

开发平台:MDK-Arm。

目的:使用Stm32高级定时器TIM1。配置中心对齐模式输出三路互补PWM。

(1)Stm32的高级定时器:

Stm32f103c8t6有一个高级定时器TIM1。STM32的高级定时器比通用定时器增加了可编程死区互补输出,重复计数器,带刹车(短路)功能。这些功能为电机控制提供了便利。其中重复计数器下篇文章单独讲。

TIM1的IO分配:

1.jpg?imageView2/2/w/1000

(2)高级定时器框图分析:

图片

图1

图1高级定时器框图,可分为6部分,①时钟源选择,②控制器,③时基单元,④输入捕获,⑤输出比较,⑥刹车断路。

①时钟选择:

时钟源有:内部时钟(CK_INT),外部时钟模式1,外部时钟模式2,内部触发输入(ITRx)。具体可以看TIMx_SMCR寄存器SMS位和ECE位这里我们使用内部时钟64MHz(没使用外部晶振,系统时钟是64MHz)。

②控制器

控制器部分包含触发控制器,从模式控制器,编码器接口。触发控制器可以为片内外设提供触发信号。

③⑤时基单元和输出比较

时基单元的计数模式选中心对齐模式和比较输出的比较模式选PWM模式来讲解。

首先时钟源通过预分频寄存器PSC分频得到CK_CNT,得到计数器CNT计数频率,计数器开始从0向上计数,每计一次,和CCR比较一次,当CRR>CNT, 输出高电平,反之输出低电平,计数器CNT继续计数,当计数器等于ARR值时,计数器向下计数,当计数器CNT>CCR时,输出低电平,反之输出高电平。计数器周而复始向上向下计数并不断的和CRR值比较,参考图2。

图片

图2

实际此过程我们可以看成一个比较器,CRR作为参考电压,接到比较器同相输入端,CNT作为信号电压,接到比较器反相输入端,这样根据比较输出PWM。反之把CNT和CRR调换位置,会输出相反极性的PWM,参考图2.

计数器计数模式有:向上计数,向下计数,中心对齐计数。

比较输出比较模式:冻结,匹配时设置通道x为有效电平,匹配时设置通道x为无效电平,翻转,强制为无效电平,强制为有效电平,PWM1,PWM2。

死区发生器:

通过寄存器BDTR的位UTG[7:0]来配置死区时间,关于死区时间设置可以这篇文章:

⑥短路功能

断路功能用于电控的刹车功能,可以通过寄存器BDTR的BKE位使能断路功能,BKP位设置断路输入引脚的有效电平

④输入捕获

输入捕获可以对输入的信号的上升沿,下降沿或者双边沿进行捕获,常用的有测量输 入信号的脉宽和测量 PWM 输入信号的频率和占空比这两种。

输入捕获的大概的原理就是,当捕获到信号的跳变沿的时候,把计数器 CNT 的值锁存 到捕获寄存器 CCR 中,把前后两次捕获到的 CCR 寄存器中的值相减,就可以算出脉宽或者频率。如果捕获的脉宽的时间长度超过你的捕获定时器的周期,就会发生溢出,这个我 们需要做额外的处理。

(3)程序设计

程序使用ST官方固件库,编程步骤:

①GPIO初始化;

②时基结构体TIM_TimeBaseInitTypeDef 初始化;

③比较结构体 TIM_OCInitTypeDef 初始化;

④刹车和死区结构体 TIM_BDTRInitTypeDef 初始化。


程序分析:


①宏定义:


#define   RCC_TIMGPIO_CLK      RCC_APB2Periph_GPIOA|RCC_APB2Periph_GPIOB

#define   TIM_CHxGPIO_Pinx     GPIO_Pin_8|GPIO_Pin_9|GPIO_Pin_10|GPIO_Pin_11

#define   TIM_CHxGPIOx         GPIOA

#define   TIM_CHxNGPIO_Pinx    GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15

#define   TIM_CHxNGPIOx        GPIOB

#define   TIM_BKINGPIO_Pinx    GPIO_Pin_2

#define   TIM_BKINGPIOx        GPIOB

//TIM1 macro definition


/ PWM频率和死区时间计算 */


//电机控制载波频率一般配置在15-20KHz,频率配置低了电机噪声大,配置高了,对MOS


//管开关频率要求高,且开关损耗大,这里载波配置为20KHz。


//计数器频率计算CK_CNT = 64MHz/(PSC+1) = 64MHz/1=64MHz


//中心对齐PWM频率=CK_INT/2(ARR+1)=64M/2(1599+1)=20KHz。


//死区时间配置为2us


//64M/(CKD+1)/ UTG = 500KHz,换算成时间位2us


// TIMx_CR1寄存器CKD 位,TIMx_BDTR寄存器UTG位。


#define   TIMx                 TIM1

#define   RCC_TIM_CLK          RCC_APB2Periph_TIM1

#define   TIM_ARR              1599

#define   TIM_CK_PSC           0

#define   TIM_RCR              0

#define   TIM_CCRx             799

#define   PWM_DeadTime         128

②GPIO初始化:


static void GPIO_TIM_Config(void){

   GPIO_InitTypeDef GPIO_InitStructure;

   RCC_APB2PeriphClockCmd(RCC_TIMGPIO_CLK, ENABLE);

   //TIM1_PA8CH1 PA9CH2 PA10CH3 PA11CH4

   GPIO_InitStructure.GPIO_Pin =  TIM_CHxGPIO_Pinx;

   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;

   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;

   GPIO_Init(GPIOA, &GPIO_InitStructure);

   //PB13CH1N PB14CH2N PB15CH3N PB12BKIN      

   GPIO_InitStructure.GPIO_Pin =  TIM_CHxNGPIO_Pinx; 

   GPIO_Init(TIM_CHxNGPIOx, &GPIO_InitStructure);      

   //PB12BKIN

   GPIO_InitStructure.GPIO_Pin =  TIM_BKINGPIO_Pinx; 

   GPIO_Init(TIM_BKINGPIOx, &GPIO_InitStructure);          

   GPIO_ResetBits(TIM_BKINGPIOx,TIM_BKINGPIO_Pinx);//刹车

}

③定时器时基单元,输出比较,刹车死区初始化:


static void AdvanceTIM1_Config(void){

  //开启定时器时钟,即内部时钟CK_INT=64MHz

  RCC_APB2PeriphClockCmd(RCC_TIM_CLK,ENABLE);

/*--------------------时基结构体初始化-------------------------*/

  TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;     

  TIM_TimeBaseStructure.TIM_Period = TIM_ARR;   //自动重装载寄存器的值,累计TIM_Period+1个频率后产生一个更新或者中断      

  TIM_TimeBaseStructure.TIM_Prescaler = TIM_CK_PSC;   //驱动CNT计数器的时钟 = Fck_int/(psc+1)

  TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;  //时钟分频因子 ,配置死区时间时需要用到             

  TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_CenterAligned1; //中心对齐1             

  TIM_TimeBaseStructure.TIM_RepetitionCounter = TIM_RCR;  //重复计数器的值,没用到不用管      

  TIM_TimeBaseInit(TIMx, &TIM_TimeBaseStructure);  //初始化定时器

/*--------------------输出比较结构体初始化-------------------*/             

  TIM_OCInitTypeDef  TIM_OCInitStructure;     

  TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;                //PWM1模式

  TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;    //输出使能

  TIM_OCInitStructure.TIM_OutputNState = TIM_OutputNState_Enable;  //互补输出使能       

  TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;        //输出通道电平极性配置

  TIM_OCInitStructure.TIM_OCNPolarity = TIM_OCNPolarity_High;      //互补输出通道电平极性配置

  TIM_OCInitStructure.TIM_OCIdleState = TIM_OCIdleState_Set;       //输出通道空闲电平极性配置

  TIM_OCInitStructure.TIM_OCNIdleState = TIM_OCNIdleState_Reset;   //互补输出通道空闲电平极性配置                  

  TIM_OCInitStructure.TIM_Pulse = TIM_CCRx;                        //设置占空比大小    

  TIM_OC1Init(TIMx, &TIM_OCInitStructure);

  TIM_OC1PreloadConfig(TIMx, TIM_OCPreload_Enable);

  TIM_OC2Init(TIMx, &TIM_OCInitStructure);

  TIM_OC2PreloadConfig(TIMx, TIM_OCPreload_Enable); 

  TIM_OC3Init(TIMx, &TIM_OCInitStructure);

  TIM_OC3PreloadConfig(TIMx, TIM_OCPreload_Enable);               

/*-------------------刹车和死区结构体初始化-------------------*/

  //有关刹车和死区结构体的成员具体可参考BDTR寄存器的描述

  TIM_BDTRInitTypeDef TIM_BDTRInitStructure;

  TIM_BDTRInitStructure.TIM_OSSRState = TIM_OSSRState_Enable;

  TIM_BDTRInitStructure.TIM_OSSIState = TIM_OSSIState_Enable;

  TIM_BDTRInitStructure.TIM_LOCKLevel = TIM_LOCKLevel_1;

  //输出比较信号死区时间配置,具体如何计算可参考 BDTR:UTG[7:0]的描述

  //这里配置的死区时间为2uS

  TIM_BDTRInitStructure.TIM_DeadTime = 128;

  TIM_BDTRInitStructure.TIM_Break = TIM_Break_Enable;

  //当BKIN引脚检测到高电平的时候,输出比较信号被禁止,就好像是刹车一样

  TIM_BDTRInitStructure.TIM_BreakPolarity = TIM_BreakPolarity_High;

  TIM_BDTRInitStructure.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;

  TIM_BDTRConfig(TIMx, &TIM_BDTRInitStructure);

  TIM_Cmd(TIMx, ENABLE);      

  //主输出使能,当使用的是通用定时器时,这句不需要

  TIM_CtrlPWMOutputs(TIMx, ENABLE);                  

}


(4)程序烧录验证:图3是一对PWM互补输出波形。

图片

图3


关键字:STM32芯片  PWM输出 引用地址:基于STM32芯片三路互补PWM输出的设计实现

上一篇:STM32模数转换器 (ADC)介绍
下一篇:硬件电路设计之STM32最小系统电路设计

推荐阅读最新更新时间:2026-03-24 11:49

STM32 Cubemx 输出可调频率与占空比的PWM
  这里就不对STM32的PWM进行讲解了,想要了解的可以百度一下,这里主要说怎么实现。   1、建立工程,我选的是STM32F103zet6芯片,选择定时器的PWM功能      2、配置时钟,我这里配的是内部时钟,没有配外部时钟,而且不是最大时钟,有需要的可以自己改      3、配置定时器,这里的话默认就可以,因为代码里面需要对配置的初始化代码进行修改的,而修改后才可以实现该功能    4、生成代码后,修改代码,找到PWM初始化函数,修改为如下代码,注意要把初始化函数前面的 static 关键字也去掉,而且函数声明也要跟着修改 void MX_TIM4_Init(uint16_t pre,uint16_t pul)
[单片机]
<font color='red'>STM32</font> Cubemx <font color='red'>输出</font>可调频率与占空比的<font color='red'>PWM</font>
GD32F103C8单片机的PWM输出试验
在国产化芯片浪潮崛起的今天,给大家介绍一款国产单片机,它就是兆易创新“GD”,今天主要给大家介绍的是关于这款单片机官方DEMO的PWM输出试验,重点是使用keil仿真输出波形。 大家在使用keil的Debug模式时,可能看到过下面这个图标,它就是用来观察波形的,输入特定的GPIO引脚,就可以直观看出波形。 来自keil帮助文档介绍内容 下面以GD32F10x系列的一款单片机GD32F103C8T6的DEMO程序来给大家演示这个功能怎么使用。 首先,我们进入兆易创新官网,然后找到下图中的官方DEMO,点击下载。 官网下载 用到的文件 然后将上图中的文件复制到Template文件夹下,再用keil打开工程文件即可。 打开
[单片机]
GD32F103C8单片机的<font color='red'>PWM</font><font color='red'>输出</font>试验
STM32F4_TIM输出PWM波形 (可调频率、占空比)
Ⅰ、概述 上一篇文章关于STM32基本的计数原理明白之后,该文章是在其基础上进行拓展,讲述关于STM32比较输出的功能,以输出PWM波形为实例来讲述。 提供实例工程中比较实用的函数:只需要调用该函数,参数为频率和占空比 void TIM2_CH2_PWM(uint32_tFreq, uint16_tDutycycle); 先看一下实例中1KHz、20%占空比波形图 TIM2_CH2_PWM(1000, 20); 关于本文的更多详情请往下看。 Ⅱ、实例工程下载 笔者针对于初学者提供的例程都是去掉了许多不必要的功能,精简了官方的代码,对初学者一看就明白,以简单明了的工程供大家学习。 笔者提供的实例工程都是在板子上经过多次测试并
[单片机]
STM32F4_TIM<font color='red'>输出</font><font color='red'>PWM</font>波形 (可调频率、占空比)
STM32无法正常输出PWM信号的原因及解决方法
PWM(Pulse Width Modulation)脉宽调制技术在嵌入式系统中应用广泛,可以控制电流或电压的大小,从而实现对电机转速、亮度等的调节。然而,在使用STM32系列微控制器时,有时会遇到无法正常输出PWM信号的问题。本文将探讨STM32无法正常输出PWM信号的原因,并提供解决方法。 一、引脚配置错误 STM32微控制器的每个IO引脚都有多个功能,包括GPIO、UART、SPI、PWM等。正确配置PWM功能的引脚是实现PWM输出的第一步。首先,检查引脚是否使用了正确的模式和功能。其次,确认引脚的时钟使能是否正确。通过使用寄存器操作来确保引脚的正确配置。例如,通过RCC/APBxENR和GPIOx_MODER等相关寄存
[单片机]
STM32定时器(一)PWM输出
一、 STM32定时器分类众多,按照内核、外核标准分为两部分:核内定时器+核外定时器 1)核内定时器:Systick 2)外设定时器:特定应用定时器+常规定时器 3)特定应用定时器:LPTIM,RTC,WTD,HRTIM 4)常规定时器:基本定时器TIM6&TIM7)、通用定时器(TIM2TIM5,TIM9TIM14)、高级定时器(TIM1&TIM8) 【常规定时器: 基本定时器:计划没有任何对外输入/输出,常用作时基,实现基本的计数和定时功能。 通用定时器:除了基本的定时器的时基功能外,还可以对外作输入捕获、输出比较以及连接其他传感器接口(除了编码器和霍尔传感器) 高级定时器:此类的定时器功能强大,除了具备通用的定时器的功
[单片机]
<font color='red'>STM32</font>定时器(一)<font color='red'>PWM</font><font color='red'>输出</font>
STM32PWM波形输出配置的大神总结
本文分享STM32之PWM波形输出配置总结。 一. TIMER分类: STM32中一共有11个定时器,其中TIM6、TIM7是基本定时器;TIM2、TIM3、TIM4、TIM5是通用定时器;TIM1和TIM8是高级定时器,以及2个看门狗定时器和1个系统嘀嗒定时器。其中系统嘀嗒定时器是前文中所描述的SysTick。 其中TIM1和TIM8是能够产生3对PWM互补输出,常用于三相电机的驱动,时钟由APB2的输出产生。TIM2-TIM5是普通定时器,TIM6和TIM7是基本定时器,其时钟由APB1输出产生。 二、PWM波形产生的原理: 通用定时器可以利用GPIO引脚进行脉冲输出,在配置为比较输出、PWM输出功能时,捕获/比较寄存器T
[单片机]
<font color='red'>STM32</font>的<font color='red'>PWM</font>波形<font color='red'>输出</font>配置的大神总结
用TIM的PWM输出模式写一个步进电机的Stepper库函数
这是之前写平衡小车时自己用 TI M的PWM输出模式写了一个 步进电机 的Stepper库函数。 1 调用顺序 1.1 init函数 1.2 begin函数 1.3 setSpeed函数 2 Stepper类结构 3 TIM结构框图 Stm32手册中的结构框图很重要,只要理解了外设的运行逻辑,按照逻辑一步一步给寄存器设值就可以让外设按我们的要求运行。 #ifndef __STEPPER_H #define __STEPPER_H #include peripheral.h #include math.h #ifdef __cplusplus extern C { #endif
[嵌入式]
用TIM的<font color='red'>PWM</font><font color='red'>输出</font>模式写一个步进电机的Stepper库函数
SMT32的PWM波形输出配置总结
本文分享 STM32 之PWM波形输出配置总结。 一. TI MER分类: STM32中一共有11个 定时器 ,其中TIM6、TIM7是基本定时器;TIM2、TIM3、TIM4、TIM5是通用定时器;TIM1和TIM8是高级定时器,以及2个 看门狗 定时器和1个系统嘀嗒定时器。其中系统嘀嗒定时器是前文中所描述的SysT ic k。 其中TIM1和TIM8是能够产生3对PWM互补输出,常用于三相 电机 的驱动, 时钟 由APB2的输出产生。TIM2-TIM5是普通定时器,TIM6和TIM7是基本定时器,其时钟由APB1输出产生。 二、PWM波形产生的原理: 通用定时器可以利用GPIO引脚进行脉冲输出,在配置为比较输出、PWM
[单片机]
SMT32的<font color='red'>PWM</font>波形<font color='red'>输出</font>配置总结
小广播
最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

厂商技术中心

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

 
机器人开发圈

电子工程世界版权所有 京ICP证060456号 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2026 EEWORLD.com.cn, Inc. All rights reserved