简介
首先聊聊 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,实现死区控制:
上一篇:基于STM32f103的I2C通信接口的EPPROM模块(24C256)读写程序详解1
下一篇:stm32在rt-thread上的PWR(电源管理)
推荐阅读
史海拾趣
Cherry公司的研发部门一直是其核心竞争力所在。在一位年轻小伙子的带领下,Cherry在1983年成功研发出了具有里程碑意义的MX机械轴。这一创新产品不仅提升了键盘的使用寿命和舒适度,还解决了多个按键同时按下时的冲突问题。MX轴的诞生标志着Cherry在机械键盘领域取得了重大突破,也为公司赢得了更多的市场份额。
HSMC的发展不仅为公司自身带来了显著的经济效益,也为当地社会和经济发展做出了重要贡献。项目全面达产后,预计可实现年产值600亿元,利税60亿元,直接带动就业人口3000人。此外,HSMC还通过技术创新和产业升级,带动了上下游产业链的发展,促进了整个电子行业的繁荣与进步。
以上五个故事共同描绘了HSMC在电子行业中的崛起与发展历程。作为一家充满活力和创新精神的企业,HSMC正以其独特的优势和不懈的努力,向着成为全球领先CIDM晶圆厂的目标不断迈进。
作为一家有社会责任感的企业,Fenghua (HK) Electronics Ltd积极履行社会责任,关注环保和公益事业。公司采用了环保材料和节能技术,降低了生产过程中的能耗和排放。同时,公司积极参与社会公益活动,为当地社区和教育事业做出了积极贡献。这些举措不仅提升了公司的社会形象,也为企业的可持续发展奠定了坚实基础。
请注意,以上故事框架仅供参考,你可以根据Fenghua (HK) Electronics Ltd公司的实际情况和发展历程进行进一步的拓展和完善。
2000年,BB公司迎来了发展史上的一个重要时刻——被美国德州仪器公司收购。这一收购对于BB公司来说,既是挑战也是机遇。德州仪器作为全球领先的半导体公司,为BB公司提供了更广阔的平台和更丰富的资源。在德州仪器的支持下,BB公司得以继续深化技术创新和市场拓展,进一步提升了其在电子行业的地位。
随着环保意识的日益增强,FDK AMERICA公司积极响应绿色制造理念。公司投入大量资金研发环保型电子产品,采用环保材料和绿色生产工艺,减少对环境的影响。同时,公司还积极参与各类环保活动,倡导绿色消费理念。这种环保举措不仅提升了公司的社会形象,也为公司赢得了更多消费者的青睐。
ABCircuits公司始终坚信人才是企业发展的核心动力。因此,公司在人才招聘和培养方面投入了大量资源。通过与高校和研究机构的合作,ABCircuits吸引了一批批优秀的科研人才加入公司。同时,公司还建立了完善的培训体系,为员工提供持续的学习和成长机会。这些人才为公司带来了源源不断的创新动力,推动了公司的快速发展。