历史上的今天

今天是:2024年08月24日(星期六)

2019年08月24日 | STM32F103ZET6 — PWM(TIM1)

发布者:HappyHearted 来源: eefocus关键字:STM32F103ZET6  PWM  TIM1 手机看文章 扫描二维码
随时随地手机看文章

简介

首先聊聊 PWM 输出。脉宽调制(PWM,Pulse Width Modulation)是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术,广泛应用在从测量、通信到功率控制与变换的许多领域中。尤其是电机控制。


PWM 的主要参数包括频率和占空比。


死区的概念是在 PWM 控制电机引入的。由于 H 桥的存在,每个桥的上半桥和下半桥是绝对不能同时导通的,但高速的PWM驱动信号在达到功率元件的控制端时,往往会由于各种各样的原因产生延迟的效果,造成某个半桥元件在应该关断时没有关断,造成功率元件烧毁。


死区就是在互补的输出中,人为的插入 Delay,以致 H 桥不至于出现同时导通的情况。类似于 DTPHx 和 DTPHx_ 信号 :

STM32 的定时器功能十分强大,不仅仅实现了定时器的基本功能,对于高级定时器 TIM1/TIM8,更是能够输出 PWM,波形,同时还带插入死区的互补输出。天生就是拿来做电机控制的一把好手。


TIM1 对应的 Pin

TIM1 能够输出 4 路 PWM 信号,所有逻辑全部做在了硬件里面,也就是说, TIM1/TIM8 的硬件逻辑中,绑定了几个引脚,不单纯的只是 Timer:

如图所示,TIM1 的四个 Channel 1 ~ Channel 4 分别对应着 PA8 ~ PA11,互补输出的信号 Channel 1 N ~ Channel 3 N 分别对应到了 PB13 ~ PB15 管脚。


对应到单板上:

     

好了,然后连接逻辑分析仪上去:


环境准备 Ready!!!



TIM1 功能

TIM1 的功能能强大,不仅仅支持计数器,同时可以支持 4 个独立通道的:


输入捕获

输出比较

PWM 生成

单脉冲输出

死区时间可编程的互补输出

刹车输入信号可以将定时器输出信号置于复位状态或者一个已知状态

支持针对定位的增量(正交)编码器和霍尔传感器电路

触发输入作为外部时钟或者按周期的电流管理

这里关注 PWM 相关的逻辑。


TIM1 时钟

TIM1 的时钟来源于 APB2 的时钟输入:


需要开启 TIM 的时钟输入。这里配置的 APB2 时钟为 72MHz。


TIMxCLK 输入到 TIM1 模块后,会有一个预分频器(TIMx_PSC),对其进行分频,分出来的频率就供给 TIM1 的频率 (上限 65536)。同时存在一个自动装载寄存器 (TIMx_ARR) ,这个寄存器的作用是当计数器以预分频后的时钟进行计数后,达到这个装载寄存器的值,就完成一次 Timer 事件。


TIM1 还包含一个重复计数器,灵活的配置这个寄存器,能够使得多次达到 TIMx_ARR 的值后,才产生对应的事件。


TIM1 有一个预装载的功能,如果打开这个功能,代表更新 TIMx_ARR 寄存器的值,将在下一次完成事件后,才对 TIMx_ARR 进行更新,否则,立即更新 TIMx_ARR。


计数器的方式有三种:向上计数,向下计数,以及中央对齐模式(向上/向下计数) ,非常灵活。具体的详见 DataSheet。



TIM1 的 PWM 功能

TIM1 的支持的配置相当繁多,这里仅仅以向上计数的方式介绍。


在 PWM 模式中,主要是控制波形的周期和占空比:


周期的控制方式由,TIMx_ARR寄存器确定


由TIMx_CCRx寄存器确定占空比的信号。


这里引入了一个 TIMx_CCRx 寄存器,他是一个比较输出的寄存器:


下面是一个PWM模式1的例子。当 TIMx_CNT < TIMx_CCRx 时,PWM 输出的参考信号 OCxREF 为高,否则为低。以此来达到控制占空比的要求。


针对这个, STM32 有一个有效电平的概念,即先定义有效电平是 1 还是 0,然后根据和比较寄存器的比较情况,来输出有效电平。(够繁琐)。


TIM1 的配置过程

1. 当然,还是需要首先开启管脚的时钟和配置管脚的 mode


2. 配置 NVIC (如果有中断需要)


3. 开启 TIM1/TIM8 的时钟


4. 配置 TIMx_ARR 寄存器,来确定周期


5. 配置分频寄存器,确定分频参数


6. 配置计数方式(向上,向下,中央)


7. 配置 PWM1 模式


8. 开启输出和互补输出


9. 配置 TIMx_CCRx ,比较寄存器的值(后面可以更改)


10. 配置输出信号的极性


11. 开启每个输出通道的预装入功能


12. 配置死区时间


13. 开启 TIM1 的整个模块的预装入功能


14. 打开 PWM 输出


15. 开启 TIM1 的使能位


#include "stm32f10x.h"

#include "stm32f10x_rcc.h"

#include "stm32f10x_gpio.h"

#include "stm32f10x_dma.h"

#include "stm32f10x_tim.h"

#include "stm32f10x_pwr.h"

 

#include "sk_pwm.h"

 

#define TIMx_DEFAULT_PERIOD     (1000)

#define CCRx_DEFAULT_VALUE      (TIMx_DEFAULT_PERIOD / 2)

#define TIMx_DEFAULT_PRE        (72)

 

static void SK_PWM_PortInit(void)

{

    GPIO_InitTypeDef  stGpioInit;

 

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB, ENABLE);

 

    stGpioInit.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11;

    stGpioInit.GPIO_Mode = GPIO_Mode_AF_PP;

    stGpioInit.GPIO_Speed = GPIO_Speed_50MHz;

 

    GPIO_Init(GPIOA, &stGpioInit);

 

    stGpioInit.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;

    GPIO_Init(GPIOB, &stGpioInit);

}

 

static void SK_PWM_NvicInit(void)

{

    NVIC_InitTypeDef NVIC_InitStructure;

 

    NVIC_InitStructure.NVIC_IRQChannel = TIM1_UP_IRQn;

    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;

    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_InitStructure);

}

 

static void SK_PWM_ClockInit(void)

{

    RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1 | RCC_APB2Periph_TIM8, ENABLE);

}

 

static void SK_PWM_ModeInit(void)

{

    TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;

    TIM_OCInitTypeDef  TIM_OCInitStructure;

    TIM_BDTRInitTypeDef      TIM1_BDTRInitStruct;

 

    // Configure the period and prescaler

    TIM_TimeBaseStructure.TIM_Period = (TIMx_DEFAULT_PERIOD - 1);

    TIM_TimeBaseStructure.TIM_Prescaler = (TIMx_DEFAULT_PRE - 1);

    TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;

    TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;

    TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);

 

    // Configure the Output mode

    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 = CCRx_DEFAULT_VALUE;

    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_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);

 

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_Pulse = CCRx_DEFAULT_VALUE / 2;

    TIM_OC2Init(TIM1, &TIM_OCInitStructure);

    TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);

 

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_Pulse = CCRx_DEFAULT_VALUE / 4;

    TIM_OC3Init(TIM1, &TIM_OCInitStructure);

    TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);

 

    TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;

    TIM_OCInitStructure.TIM_Pulse = CCRx_DEFAULT_VALUE / 10;

    TIM_OC4Init(TIM1, &TIM_OCInitStructure);

    TIM_OC4PreloadConfig(TIM1, TIM_OCPreload_Enable);

 

    TIM1_BDTRInitStruct.TIM_OSSRState = TIM_OSSRState_Disable;

    TIM1_BDTRInitStruct.TIM_OSSIState = TIM_OSSIState_Disable;

    TIM1_BDTRInitStruct.TIM_LOCKLevel = TIM_LOCKLevel_OFF;

    TIM1_BDTRInitStruct.TIM_DeadTime = 205;

    TIM_BDTRConfig(TIM1, &TIM1_BDTRInitStruct);

 

    TIM_ARRPreloadConfig(TIM1, ENABLE);

    TIM_CtrlPWMOutputs(TIM1, ENABLE);

 

    TIM_ClearFlag(TIM1, TIM_FLAG_Update);

    TIM_ITConfig(TIM1, TIM_IT_Update, ENABLE);

}

 

static void SK_PWM_Enable(void)

{

    TIM_Cmd(TIM1, ENABLE);

}

 

void SK_PWM_Init(void)

{

    SK_PWM_PortInit();

    SK_PWM_ClockInit();

    SK_PWM_NvicInit();

    SK_PWM_ModeInit();

    SK_PWM_Enable();

}

 

void TIM1_UP_IRQHandler(void)

{

    static uint32_t cnt = 0;

    if (TIM_GetITStatus(TIM1, TIM_IT_Update) != RESET)

    {

        TIM_ClearITPendingBit(TIM1, TIM_IT_Update);

    }

}

 


测试结果

使用逻辑分析仪抓到的结果如下:


1. 不带死区控制的互补输出

互补输出时间 delta 测量为 0,即几乎是同时输出翻转:

2. 带死区控制的互补输出

互补输出时间 delta 测量为 5us,实现死区控制:


关键字:STM32F103ZET6  PWM  TIM1 引用地址:STM32F103ZET6 — PWM(TIM1)

上一篇:基于STM32f103的I2C通信接口的EPPROM模块(24C256)读写程序详解1
下一篇:stm32在rt-thread上的PWR(电源管理)

推荐阅读

   安卓和iOS用户为啥转换阵营新浪手机讯 8月24日上午消息,国外媒体PCMag对2500人进行了一项调查,探究iOS和Android系统用户互相转换阵营的原因。结果是,价格和体验是两方用户都比较在意的因素。安卓转iOS:为了更好体验在每季度财报电话会上,苹果CEO库克(Tim Cook)都会讲,从Android设备转向iPhone的用户比例很高等等,以显示iPhone手机和iOS系...
大家都知道,美国的科技领域一直都是处在世界的顶端,很多市场上的高科技都有人家的专利。新型自动驾驶技术前一段时间,苹果公司的“Project Titan”自动驾驶汽车项目又有了新的研发进展,特别是在用于辅助在恶劣天气或道路状况上安全行驶的航向校正系统,汽车的滑动门已经配备额外的传感器,不管是碰到什么样的路况,都会很好的去适应不同的道路状况。“...
智能建筑/家居/工厂、个人物联网(IoT)、智慧医疗的不断发展正极大地改变人们的工作和生活,提供舒适和便利,减少对环境的不利影响,甚至提高整个经济体系的净收益。推动高能效创新的安森美半导体提供广泛的IoT赋能方案,包括基于行业最低功耗的蓝牙低功耗(BLE)5.0 RSL10的一系列方案、先进的机器视觉及安防成像方案、更快更广更高效的Wi-Fi联接方案等,采...
近日,TCL X12 8K Mini LED 领曜智屏(以下简称 TCL X12 )正式上市。作为 TCL Mini LED 旗舰级产品,除了为消费者带来顶级的音画质,还基于地平线旭日 3 芯片及算法方案打造了更为自然的人机交互体验,可谓一款真正秀外“慧”中的智能电视。 作为 TCL 推出的高端电视产品,TCL X12 售价高达 99999 元,在音画质的表现均达到了行业顶...

史海拾趣

问答坊 | AI 解惑

技术支持

我公司是芯片的原封装工序,现在通过最后一道电镀,经常会产生电镀不均匀,或颜色褪色,造成产品报废。现需求解决之道.…

查看全部问答∨

求助无线识别装置

本帖最后由 paulhyde 于 2014-9-15 09:48 编辑 哪位好心人帮帮我啊,我现在要做无线识别装置的应答器部分的毕业设计,现在没有思路,尤其是无源部分怎么实现?题目要求就是2007年电子大赛B题的要求,求求大家帮帮我,大家有什么资料最好是有论文能不能给 ...…

查看全部问答∨

Linux内核完全注释

Linux内核完全注释 内核版本0.11(0.95) 赵炯著 …

查看全部问答∨

allegro怎么显示铜皮?

本信息来自合作QQ群:电子工程师技术交流(12425841) 群主在坛子ID:Kata allegro怎么显示铜皮?…

查看全部问答∨

那位高手能提供定时器T2向下计数的C51程序

我现在用到定时器T2的向下计数程序,RCAP2H=0x0B;  RCAP2L=0xDC; 系统如何初始化,脉冲如何从T2引脚输入才能实现向下计数.…

查看全部问答∨

wince5.0操作系统支持的图片格式

[b]有那位兄弟知道RTK手簿(wince5.0操作系统)支持那些图片格式? 我想在其嵌入的软件中进行简单的绘图!用什么绘图引擎比较好? 需要相关的工具包吗?…

查看全部问答∨

VxWorks是否支持XML协议,应该如何使用?

VxWorks是否支持XML协议,应该如何使用?望各位大侠赐教。…

查看全部问答∨

周工SmartCortex M3-1700资料

最近找资料,感谢网友的帮忙:…

查看全部问答∨

我的天啊!是哪个家伙设计STM的库的!?

这个STM32库真TMD的 恶心! 应该把它扔到垃圾堆。既没有 高级语言的面向对象编程的思想,例如 JAVA,C# !也不能体现 硬件的 特性!例如 【位定义】等!真一团糟!…

查看全部问答∨
小广播
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

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