PWM

有客户需要用到高精度的DAC模块,MM32L0系列产品内部没有集成DAC模块,考虑到外接DAC芯片会增加成本,所以在本实验中将为大家介绍使用PWM输出,经过简单的变换电路即可实现DAC,这将大量降低电子设备的成本、减少体积,并提高精度。本实验在PWM到DAC转换关系的理论分析基础上,设计出输出为0~5V电压的DAC。

MM32L0系列产品包含1个高级控制定时器、5个通用定时器(1个32 位定时器和5个16 位定时器),以及 2个看门狗定时器和1个系统嘀嗒定时器。

每个定时器都有 PWM 输出或单脉冲模式输出,所以MM32L0系列产品任意一款型号都可以用PWM做DAC输出功能。

PWM波形的分段函数:

MM32 基于PWM做DAC输出设计

其中:k为谐波次数,N是PWM波一个周期的计数脉冲个数,T是单片机中计数脉冲的基本周期,即MCU每隔T时间记一次数(计数器的值增加或者减少1),t为时间, n是PWM波一个周期中高电平的计数脉冲个数,VH和VL分别是PWM波中高低电平的电压值。

PWM的高低电平分别为VH和VL,理想的情况VL等于0,但是实际中一般不等于0,所以用户在处理PWM的VL时需注意,出现较大误差一般都是因为这个地方。

将上述函数展开成傅里叶级数得到:

MM32 基于PWM做DAC输出设计

从上式可以看出,上式中第1个方括弧为直流分量,第2项为1次谐波分量,第3项为大于1次的高次谐波分量。上式中的直流分量与n成线性关系,并随着n从0到N,直流分量从VL到VL+VH之间变化,这正是电压输出的DAC所需要的。因此,如果能把式中除直流分量的谐波过滤掉,则可以得到从PWM波到电压输出DAC的转换,即:PWM波可以通过一个低通滤波器进行解调。式中的第2项的幅度和相角与n有关,频率为1/(NT),该频率是设计低通滤波器的依据。如果能把1次谐波很好过滤掉,则高次谐波就应该基本不存在了。

在DAC的应用中,分辨率是一个很重要的参数,傅里叶级数公式中的分辨率计算直接与N和n的可能变化有关:

MM32 基于PWM做DAC输出设计

从上式中可看出:
N越大DAC的分辨率越高,但是NT也越大,即 PWM的周期或者傅里叶级数公式中的1次谐波周期也越大,相当于1次谐波的频率也越低,需要截止频率很低的低通滤波器,DAC输出的滞后也将增加。为了使T减少,即减少单片机的计数脉冲宽度(这往往需要提高单片机的工作频率),达到不降低1次谐波频率的前提下提高精度。

MM32L0系列产品最高工作频率可达 48MHz,TIM2是32位的定时器,PWM频率计算公式:
Fpwm = 48M / ((arr+1)*(psc+1))(单位:Hz)
公式中psc就是分频系数,arr就是计数值。预分频器可以将计数器的时钟频率按 1 到 65536 之间的任意值分频。计数值可以从1-4294967295(2的32次方减1)中任意选取。

本次实验采用两阶RC滤波,使用两个电阻和两个电容组成一个具有DAC功能的引脚,PB10是32位的定时器TIM2_CH3通道,PA3和PA4两个通道分别去采集1阶RC滤波和2阶RC滤波后的电压值。

MM32 基于PWM做DAC输出设计

R29和C10的具体参数可根据傅里叶级数公式的第2部分的一次谐波频率来选择,实际应用中一般选择阻容滤波器的截止频率为傅里叶级数公式的基波频率的1/4左右。

RC滤波器的截止频率计算公式:

f = 1/(2πRC)

滤波器是频率选择电路,只允许输入信号中的某些频率成分通过,而阻止其他频率成分到达输出端。在电路中需要考虑到芯片引脚输出端到RC滤波电路之间的存在阻值等问题,上图中的电阻和电容值需要根据实际情况计算调整。

PB10引脚能将不同占空比的PWM信号转换为不同电压值的模拟信号。为了能更准确的获取DAC转换值,电路中还使用了2个ADC通道用来检测DAC转换值。在转换过程中PWM信号频率越快DAC输出的电压值越稳定,PWM位数越高DAC输出的电压值精度越高,32位PWM比16位PWM精度高。

实验程序:

TIM2定时器配置:
u32 OutCnt;

void InitTIM2_PWM(u16 t1, u16 t2, u16 psc)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOB, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10; //TIM2_CH3
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; //TIM2_CH4
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);

GPIO_PinAFConfig(GPIOB, GPIO_PinSource10,GPIO_AF_2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11,GPIO_AF_2);

TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure;
TIM_TimeBaseStructure.TIM_Prescaler =psc;
TIM_TimeBaseStructure.TIM_Period = t1;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);

TIM_OCInitTypeDef TIM_OCInitStructure;
TIM_OCInitStructure.TIM_OCMode = TIM_OCMode_PWM1;
TIM_OCInitStructure.TIM_OutputState = TIM_OutputState_Enable;
TIM_OCInitStructure.TIM_Pulse = 0;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;

TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC4Init(TIM2, &TIM_OCInitStructure);

TIM_OCInitStructure.TIM_Pulse = t2;
TIM_OC3Init(TIM2, &TIM_OCInitStructure);
TIM_OC3PreloadConfig(TIM2, TIM_OCPreload_Enable);

TIM_OCInitStructure.TIM_Pulse = t2;
TIM_OC4Init(TIM2, &TIM_OCInitStructure);
TIM_OC4PreloadConfig(TIM2, TIM_OCPreload_Enable);

TIM_ARRPreloadConfig(TIM2, ENABLE);
TIM_Cmd(TIM2, ENABLE);
}

获取 SysTick 计数器的值:
u32 GetSysTickCount(void)
{
return SysTick_Count;
}

设置 SysTick 重装载值:
void SysTick_Configuration(void)
{
SysTick_Config(48000);
}

SysTick中断配置:
u32 pwm = 150;
void SysTick_Handler(void)
{
if (SysTick_Count ++ > 500)
{
SysTick_Count = 0;
InitTIM2_PWM(1024, pwm, 1);
}
}

主函数:
int main(void)
{
SystemInit();
SysTick_Count = 0;
SysTick_Configuration();
while(1)
{
}
}

操作方法:按照上述硬件搭建实验环境后,上电接上调试器,进入Debug状态,在IAR的Live watch窗口修改pwm值可以实现占空比可调。

实验结果:

MM32 基于PWM做DAC输出设计MM32 基于PWM做DAC输出设计

根据实验现象:
从PWM到DAC输出的信号处理有许多电路实现方法,上述电路实现方法DAC输出的负载能力比较差,适合具有高输入阻抗的后续电路连接,对精度和负载能力要求较高的场合,建议增加基准电压、负载驱动等电路。在MCU的应用中还可以通过软件的方法进行精度调整和误差的进一步校正。

PWM 外设结合本电路所实现DAC 有非常好的差分非线性(DNL)、线性度(INL),8位分辨率的情况下,PWM 频率为50KHz,实测精度在 0.5LSB 以内,适合于输出低频、高精度的模拟信号。

转自: 灵动微电子

围观 13
78

理解PWM需要知道的知识

(1)脉冲

解释:电子设备中电平状态发生的突变,通常突变时间很短,突变后极短时间后重新变为为原来的电平状态.(突变状态很短,两次突变间的时间相对较长)

(2)脉冲循环

解释:可以理解为一次突变到下一次突变所花的时间如下图:

浅析LED呼吸灯的实现和PWM的关系

(3)*(重点)占空比

解释:一个脉冲循环内通电时间所占的比例.,如下图:

浅析LED呼吸灯的实现和PWM的关系

举个例子:脉冲宽度1μs,信号周期5μs的脉冲序列即t=1,T=5,经过公式-占空比=t/T可以得到占空比为0.2.

(4)滤波器

解释:滤波器的组成为电感,电容,电阻等元器件.虽然PWM能通过通过改变占空比的方法.使电压的平均值达到稳压值,但输出稳定电压是靠PWM之后接的的滤波器来实现的。

(5)平均电压/输出电压

解释:
平均电压电压在一个周期T内积分之后再除以T.
也可以等同于写成:
输出电压 = (接通时间 / 脉冲时间)* 最大电压值

计算方式(平均电压)的示意图如下:

浅析LED呼吸灯的实现和PWM的关系

PWM的定义

PWN(Pulse-width modulation)的中文名是脉冲宽度调制.那么我们来看一下wikipedia对它的定义:

脉冲宽度调制(英语:Pulse Width Modulation,缩写:PWM),简称脉宽调制,是将模拟信号变换为脉冲的一种技术,一般变换后脉冲的周期固定,但脉冲的占空比会依模拟信号的大小而改变.在模拟电路中,模拟信号的值可以连续进行变化,在时间和值的幅度上都几乎没有限制,基本上可以取任何实数值,输入与输出也呈线性变化。所以在模拟电路中,电压和电流可直接用来进行控制对象,例如家用电器设备中的音量开关控制、采用卤素灯泡灯具的亮度控制等等 ...

计算PWN等效电压

PWM的等效电压计算公式为:

(此处我认为因为是方波所以可以将其视作平均电压)
U =(T1*Umax)/(T1+T2)
T1:导通时间
T2:断流时间
T1+T2 脉冲周期
Umax:电压幅值

所以根据公式可知,由于T1/(T1+T2)正是空占比,所以改变空占比就等于改变了等效电压,所以使得灯泡的亮度发生了变化

为什么Analogwrite的值是0-255?

LED亮度通过调节LED驱动器的PWM占空比来对亮度控制,一个PWM周期可以划分成2的控制位的次方个时钟周期而对大部分LED而言,控制位通常是8位,所以8位PWM能够提供256个亮度级的电平,因此PWM周期由256个时钟周期组成.

脉冲周期/频率和人眼的关系

LED的典型时钟频率是32kHz,那么根据公式PWM周期为256/32kHz=8ms.那么这样对于人眼而言这个闪烁频率很安全的避免了人眼能够觉察的闪烁.

在ARDUINO中使用PWM控制LED灯模拟呼吸灯的实验

实验准备:

实验主设备: Arduino UNO R3(图片来自NRIOBOT)

浅析LED呼吸灯的实现和PWM的关系

其他:
LED灯(若干)
面包板(一块)
杜邦线(双头公若干)
电阻(若干)(可选择/非必需)

连接图示意(通过Fritzing软件制作的简易电路图)

浅析LED呼吸灯的实现和PWM的关系

实验代码:

/*先要介绍一下analogwrite的用法
将模拟值(PWM波)输出到管脚。可用于在不同的光线亮度调节发光二极管亮度或以不同的速度驱动马达。调用analogWrite()后,该引脚将产生一个指定占空比的稳定方波,直到下一次调用analogWrite()(或在同一引脚调用digitalRead()或digitalWrite())

这种方法也叫快速PWM方式*/

需要上传到ARDUINO中的代码:

//设定使用9号口
void setup (){
pinMode(9,OUTPUT);
}
void loop(){
//由于上文中提到的所以为256种亮度
for (int a=0; a<=255;a++) //控制PWM亮度的增加
{
analogWrite(9,a);
delay(8);
}
for (int a=255; a>=0;a--) //控制PWM亮度减小
{
analogWrite(9,a);
delay(8);
}
delay(300); //完成一个循环
}

Analogwrite和占空比的关系

analogwrite(x,y)

X是管脚,而y(value)就是亮度级(在LED中)

占空比的计算方法就是: 占空比=y/256

对于Analogwrite占空比的一个特殊之处的解释

对于快速PWM模式,如果我们代码用了analogWrite(9, 0)即Y(value)=0,实际上应该有1/256的占空比,然而实际输出的电平为0.这是因为在Arduino的强制设定,当检测到AnalogWrite的value为0,那么就等于关闭了PWM.所以带来的问题是,如果我们设置analogWrite(9, 1),那么占空比2/256,所以在0到1之间产生了一个跳跃,丢弃了占空比为1/256的情况.

总结

这次的python实验中,让我们尝试了怎么使用Arduino和LED灯做出呼吸灯的效果,因为对于机器是怎么输出高电平(5v)和低电平(0v)之间的电压好奇,所以探究了一下原理,总结来说就是机器通过pwm在管脚产生了一定占空比的方波,改变空占比就等同于改变了等效电压,所以使得灯泡的亮度发生了变化.

转自: xlxw

围观 13
182

89C51芯片没有自带PWM发生器,如果要用51来产生PWM波就必须要用软件编程的方法来模拟。方法大概可以分为软件延时和定时器产生两种方法。下面将逐一介绍。

1 软件延时法

利用软件延时函数,控制电平持续的时间,达到模拟pwm的效果。

程序如下:

#include<reg52.h>
sbit pwm=P1^0;
main()
{
while(1)
{
 
pwm=1;
delayus(60);//置高电平后延时60us,占空比60%
pwm=0;
delayus(40);
}
}
void delayus(uint x)
{
while(x--);
}

proteus软件仿真结果如下:

51单片机产生PWM方法

可见,用这种延时函数的方法就能简单地模拟出pwm输出。但是这种方法的缺点也相当明显。当程序除了要输出pwm波还要执行其他操作比如键盘扫描、显示等操作时,需要占用CPU一定的机器周期,这样就会影响pwm的准确度。现在很少会用到这种方法,接下来要介绍的是比较常用的方法。

2 定时器产生pwm

这种方法利用了定时器溢出中断,在中断服务程序改变电平的高低,在程序较复杂、多操作时仍能输出较准确的pwm波形。

2.1 注意事项

2.2.1中断服务程序的内容。

一般来说中断服务程序只完成改变标志位、转换高低电平的功能,如果中断服务程序中有太多的操作会影响pwm波的输出,尤其是除法、取余、浮点数运算会占用大量的机器周期,应在中断外完成运算。
2.2.2定时器装入初值的问题。

装入初值不能太接近于定时器的溢出值。如我们使用定时器方式1,最多能计65536个数,假设我们转入的初值为65534,那么定时器计两个数就会进入中断,这样会使程序紊乱而其他功能无法正常地执行,所以一般要留50-100个数的裕量。

2.2 定时器工作方式

在定时器工作方式的选择上,可以选择定时器的工作方式0、1、2都可以,本文采用的是工作方式1,即16位定时器,这样可以获得较宽的调频范围。

2.3 定时器初值的计算

设占空比为α,频率为f

产生高电平时装入定时器高8位的值应为

产生高电平时装入定时器低8位的值应为

显然,产生低电平时的公式只要把α换成(1-α)就行了。

然而在51单片机中,浮点数运算需要消耗cpu很长的时间,为了提高程序效率,通常用100倍的占空比来计算。同时,要注意数据类型,避免超出范围,影响计算结果。关于C51的乘除法问题,可以看以下这篇文章: http://blog.163.com/ssou_1985/blog/static/295320362010311102232210/

修改后的公式如下:
a为100倍占空比,fr为0.01倍频率
TH0 = (65535-a*100/fr)/256; //高位初值
TL0 = (65535-a*100/fr)%256;
同样,低电平的公式只需把a换成(100-a)即可。

2.4 例程

本例程采用定时器T0在工作方式1下产生一路PWM,用独立键盘控制频率、占空比的加减,频率可调范围100Hz-10kHz,占空比0-100%(均为理论值,实际值略低)
部分代码如下:

51单片机产生PWM方法

注:T0_H , T0_L , T1_H , T1_L 均用于暂时存储初值,进入中断服务程序后直接给寄存器TH0、TL0赋值,避免了在中断中计算。
51单片机产生PWM方法

注:flag为pwm输出标志,flag=1输出高电平,flag=0输出低电平

2.5 软件仿真结果

2.5.1 频率为100Hz

a.占空比约15%

51单片机产生PWM方法

b.占空比95%

51单片机产生PWM方法

2.5.2 频率为10KHz

a.占空比15%

51单片机产生PWM方法

b.占空比90%

51单片机产生PWM方法

转自: 玩转单片机

围观 16
160

脉宽调制(PWM:(Pulse Width Modulation)是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。只要带宽足够,任何模拟值都可以使用PWM进行编码。本文提出AVR单片机ATmega128的PWM的设计方法。

1.定时/计数器PWM设计要点

根据PWM的特点,在使用ATmega128的定时/计数器设计输出PWM时应注意以下几点:

1)首先应根据实际的情况,确定需要输出的PWM频率范围,这个频率与控制的对象有关。如输出PWM波用于控制灯的亮度,由于人眼不能分辨42Hz以上的频率,所以PWM的频率应高于42Hz,否则人眼会察觉到灯的闪烁。

2)然后根据需要PWM的频率范围确定ATmega128定时/计数器的PWM工作方式。AVR定时/计数器的PWM模式可以分成快速PWM和频率(或相位)调整PWM两大类。

3)快速PWM可以的到比较高频率的PWM输出,但占空比的调节精度稍微差一些。此时计数器仅工作在单程正向计数方式,计数器的上限值决定PWM的频率,而比较匹配寄存器的值决定了占空比的大小。PWM频率的计算公式为:

PWM频率 = 系统时钟频率/(分频系数*(1+计数器上限值))

4)快速PWM模式适合要求输出PWM频率较高,但频率固定,占空比调节精度要求不高的应用。

5)频率(相位)调整PWM模式的占空比调节精度高,但输出频率比较低,因为此时计数器仅工作在双向计数方式。同样计数器的上限值决定了PWM的频率,比较匹配寄存器的值决定了占空比的大小。PWM频率的计算公式为:

PWM频率 = 系统时钟频率/(分频系数*2*计数器上限值))

6)相位调整PWM模式适合要求输出PWM频率较低,但频率固定,占空比调节精度要求高的应用。当调整占空比时,PWM的相位也相应的跟着变化(Phase
Correct)。

7)频率和相位调整PWM模式适合要求输出PWM频率较低,输出频率需要变化,占空比调节精度要求高的应用。此时应注意:不仅调整占空比时,PWM的相位会相应的跟着变化;而一但改变计数器上限值,即改变PWM的输出频率时,会使PWM的占空比和相位都相应的跟着变化(Phase
and Frequency Correct)。

8)在PWM方式中,计数器的上限值有固定的0xFF(8位T/C);0xFF、0x1FF、0x3FF(16位T/C)。或由用户设定的0x0000-0xFFFF,设定值在16位T/C的ICP或OCRA寄存器中。而比较匹配寄存器的值与计数器上限值之比即为占空比。

2.PWM应用设计参考

下面给出一个设计示例,在示例中使用PWM方式来产生一个1KHz左右的正弦波,幅度为0-Vcc/2。

首先按照下面的公式建立一个正弦波样本表,样本表将一个正弦波周期分为128个点,每点按7位量化(127对应最高幅值Vcc/2):

f(x) = 64 + 63 * sin(2πx/180) x∈[0…127]

如果在一个正弦波周期中采用128个样点,那么对应1KHz的正弦波PWM的频率为128KHz。实际上,按照采样频率至少为信号频率的2倍的取样定理来计算,PWM的频率的理论值为2KHz即可。考虑尽量提高PWM的输出精度,实际设计使用PWM的频率为16KHz,即一个正弦波周期(1KHz)中输出16个正弦波样本值。这意味着在128点的正弦波样本表中,每隔8点取出一点作为PWM的输出。

程序中使用ATmega128的8位T/C0,工作模式为相位调整PWM模式输出,系统时钟为8MHz,分频系数为1,其可以产生最高PWM频率为:

8000000Hz / 510 =15686Hz。

每16次输出构成一个周期正弦波,正弦波的频率为980.4Hz。PWM由OC0(PB4)引脚输出。参考程序如下(ICCAVR)。

//ICC-AVR application builder : 2004-08

// Target : M128

// Crystal: 8.0000Mhz

#include

#include

#pragma data:code

// 128点正弦波样本表

const unsigned char auc_SinParam[128] = {

64,67,70,73,76,79,82,85,88,91,94,96,99,102,104,106,109,111,113,115,117,

118,120,121,123,124,125,126,126,127,127,127,127,127,127,127,126,126,125,

124,123,121,120,118,117,115,113,111,109,106,104,102,99,96,94,91,88,85,82,

79,76,73,70,67,64,60,57,54,51,48,45,42,39,36,33,31,28,25,23,21,18,16,14,12,

10,9,7,6,4,3,2,1,1,0,0,0,0,0,0,0,1,1,2,3,4,6,7,9,10,12,14,16,18,21,23,25,28,31,33,

36,39,42,45,48,51,54,57,60};

#pragma data:data

unsigned char x_SW = 8,X_LUT = 0;

#pragma interrupt_handler timer0_ovf_isr:17

void timer0_ovf_isr(void)

{

X_LUT += x_SW; // 新样点指针

if (X_LUT > 127) X_LUT -= 128; // 样点指针调整

OCR0 = auc_SinParam[X_LUT]; // 取样点指针到比较匹配寄存器

}

void main(void)

{

DDRB |= 0x10; // PB4(OC0)输出

TCCR0 = 0x71; // 相位调整PWM模式,分频系数=1,正向控制OC0

TIMSK = 0x01; // T/C0溢出中断允许

SEI(); // 使能全局中断

while(1)

{……};

}

每次计数器溢出中断的服务中取出一个正弦波的样点值到比较匹配寄存器中,用于调整下一个PWM的脉冲宽度,这样在PB4引脚上输出了按正弦波调制的PWM方波。当PB4的输出通过一个低通滤波器后,便得到一个980.4Hz的正弦波了。如要得到更精确的1KHz的正弦波,可使用定时/计数器T/C1,选择工作模式10,设置ICR1=250为计数器的上限值。

结束语:

本文以ATmega128为例介绍了AVR单片机的PWM设计方法。随着电力电子技术,微电子技术和自动控制技术的发展PWM技术获得了空前的发展,被广泛应用在测量、通信到功率控制与变换的许多领域中。

来源: eechina.com

围观 10
159

一、stm32的pwm输出引脚是使用的IO口的复用功能。

二、T2~T5这4个通用定时器均可输出4路PWM——CH1~CH4。

三、我们以tim3的CH1路pwm输出为例来进行图文讲解(其它类似),并在最后给出tim3的ch1和ch2两路pwm输出的c代码(已在STM32F103RBT6上测试成功,大家放心使用!)。

四、给出了PWM频率和占空比的计算公式。

步骤如下:

1、使能TIM3时钟

详解STM32的PWM输出及频率和脉宽(占空比)的计算

RCC->APB1ENR |= 1 2、配置对应引脚(PA6)的复用输出功能

详解STM32的PWM输出及频率和脉宽(占空比)的计算

GPIOA->CRL &= 0XF0FFFFFF;//PA6清0
GPIOA->CRL |= 0X0B000000;//复用功能输出(推挽50MHz输出)
GPIOA->ODR |= 1

3、设定计数器自动重装值及是否分频

TIM3->ARR = arr;//设定计数器自动重装值(决定PWM的频率)
TIM3->PSC = psc;//预分频器,0为不分频

4、设置PWM的模式(有1和2两种模式,区别在于输出电平极性相反),根据需求选一种即可

详解STM32的PWM输出及频率和脉宽(占空比)的计算

注:TIMX_CCMR1决定CH1~CH2路,TIMX_CCMR2决定CH3~CH4路。

详解STM32的PWM输出及频率和脉宽(占空比)的计算

//TIM3->CCMR1 |= 6 TIM3->CCMR1 |= 7 TIM3->CCMR1 |= 1

5、输出使能设置

详解STM32的PWM输出及频率和脉宽(占空比)的计算

TIM3->CCER |= 1

6、自动重装载预装载允许位(ARPE) 及定时器使能

详解STM32的PWM输出及频率和脉宽(占空比)的计算

TIM3->CR1 = 0X0080;//ARPE使能(此句不配置也行)
TIM3->CR1 |= 0X01;//使能定时器3

下面给出TIM3_CH1及TIM3_CH2的PWM输出代码:
void PWM_Init_TIM3_CH1(u16 arr, u16 psc)
{
//1、使能TIM3时钟
RCC->APB1ENR |= 1 //2、配置对应引脚(PA6)的复用输出功能
GPIOA->CRL &= 0XF0FFFFFF;//PA6清0
GPIOA->CRL |= 0X0B000000;//复用功能输出(推挽50MHz输出)
GPIOA->ODR |= 1 //3、设定计数器自动重装值及是否分频
TIM3->ARR = arr;//设定计数器自动重装值(决定PWM的频率)
TIM3->PSC = psc;//预分频器 0为不分频
//4、设置PWM的模式
TIM3->CCMR1 |= 7 TIM3->CCMR1 |= 1 //5、输出使能设置
TIM3->CCER |= 1 //6、自动重装载预装载允许位(ARPE) 及 定时器 使能
TIM3->CR1 = 0X0080;//ARPE使能
TIM3->CR1 |= 0X01;//使能定时器3
}
void PWM_Init_TIM3_CH2(u16 arr, u16 psc)
{
RCC->APB1ENR |= 1

GPIOA->CRL &= 0X0FFFFFFF;//PA7清0
GPIOA->CRL |= 0XB0000000;//复用功能输出(推挽50MHz输出)
GPIOA->ODR |= 1 TIM3->ARR = arr;//设定计数器自动重装值(决定PWM的频率)
TIM3->PSC = psc;//预分频器 不分频
TIM3->CCMR1 |= 7 TIM3->CCMR1 |= 1 TIM3->CCER |= 1 TIM3->CR1 = 0X0080;//ARPE使能
TIM3->CR1 |= 0X01;//使能定时器3
}
频率:
//Fpwm = 72M / ((arr+1)*(psc+1))(单位:Hz)
占空比:
//duty circle = TIM3->CCR1 / arr(单位:%)
注:本文方法的一个定时器4个通道的pwm输出的频率是相同的,但占空比可以不同!

转自: akunainiannian的专栏

围观 20
144

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

理论基础

• 冲量相等而形状不同的窄脉冲加在具有惯性的环节上时,其效果基本相同
• 冲量指窄脉冲的面积
• 效果基本相同,是指环节的输出响应波形基本相同
• 波形基本相同含义:低频段非常接近,仅在高频段略有差异

模拟电路

模拟信号的值可以连续变化,其时间和幅度的分辨率都没有限制。9V电池就是一种模拟器件,因为它的输出电压并不精确地等于9V,而是随时间发生变化,并可取任何实数值。与此类似,从电池吸收的电流也不限定在一组可能的取值范围之内。模拟信号与数字信号的区别在于后者的取值通常只能属于预先确定的可能取值集合之内,例如在{0V, 5V}这一集合中取值。

模拟电压和电流可直接用来进行控制,如对汽车收音机的音量进行控制。在简单的模拟收音机中,音量旋钮被连接到一个可变电阻。拧动旋钮时,电阻值变大或变小;流经这个电阻的电流也随之增加或减少,从而改变了驱动扬声器的电流值,使音量相应变大或变小。与收音机一样,模拟电路的输出与输入成线性比例。

尽管模拟控制看起来可能直观而简单,但它并不总是非常经济或可行的。其中一点就是,模拟电路容易随时间漂移,因而难以调节。能够解决这个问题的精密模拟电路可能非常庞大、笨重(如老式的家庭立体声设备)和昂贵。模拟电路还有可能严重发热,其功耗相对于工作元件两端电压与电流的乘积成正比。模拟电路还可能对噪声很敏感,任何扰动或噪声都肯定会改变电流值的大小。

数字控制

通过以数字方式控制模拟电路,可以大幅度降低系统的成本和功耗。此外,许多微控制器和DSP已经在芯片上包含了PWM控制器,这使数字控制的实现变得更加容易了。

简而言之,PWM是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波的占空比被调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。

PWM的原理以及应用

图1显示了三种不同的PWM信号。图1a是一个占空比为10%的PWM输出,即在信号周期中,10%的时间通,其余90%的时间断。图1b和图1c显示的分别是占空比为50%和90%的PWM输出。这三种PWM输出编码的分别是强度为满度值的10%、50%和90%的三种不同模拟信号值。例如,假设供电电源为9V,占空比为10%,则对应的是一个幅度为0.9V的模拟信号。
PWM的原理以及应用

图2是一个可以使用PWM进行驱动的简单电路。图中使用9V电池来给一个白炽灯泡供电。如果将连接电池和灯泡的开关闭合50ms,灯泡在这段时间中将得到9V供电。如果在下一个50ms中将开关断开,灯泡得到的供电将为0V。如果在1秒钟内将此过程重复10次,灯泡将会点亮并象连接到了一个4.5V电池(9V的50%)上一样。这种情况下,占空比为50%,调制频率为10Hz。

大多数负载(无论是电感性负载还是电容性负载)需要的调制频率高于10Hz。设想一下如果灯泡先接通5秒再断开5秒,然后再接通、再断开……。占空比仍然是50%,但灯泡在头5秒钟内将点亮,在下一个5秒钟内将熄灭。要让灯泡取得4.5V电压的供电效果,通断循环周期与负载对开关状态变化的响应时间相比必须足够短。要想取得调光灯(但保持点亮)的效果,必须提高调制频率。在其他PWM应用场合也有同样的要求。通常调制频率为1kHz到200kHz之间。

硬件控制器

许多微控制器内部都包含有PWM控制器。例如,Microchip公司的PIC16C67内含两个PWM控制器,每一个都可以选择接通时间和周期。占空比是接通时间与周期之比;调制频率为周期的倒数。执行PWM操作之前,这种微处理器要求在软件中完成以下工作:

• 设置提供调制方波的片上定时器/计数器的周期
• 在PWM控制寄存器中设置接通时间
• 设置PWM输出的方向,这个输出是一个通用I/O管脚
• 启动定时器
• 使能PWM控制器

虽然具体的PWM控制器在编程细节上会有所不同,但它们的基本思想通常是相同的。

通信与控制

PWM的一个优点是从处理器到被控系统信号都是数字形式的,无需进行数模转换。让信号保持为数字形式可将噪声影响降到最小。噪声只有在强到足以将逻辑1改变为逻辑0或将逻辑0改变为逻辑1时,也才能对数字信号产生影响。

对噪声抵抗能力的增强是PWM相对于模拟控制的另外一个优点,而且这也是在某些时候将PWM用于通信的主要原因。从模拟信号转向PWM可以极大地延长通信距离。在接收端,通过适当的RC或LC网络可以滤除调制高频方波并将信号还原为模拟形式。

PWM广泛应用在多种系统中。作为一个具体的例子,我们来考察一种用PWM控制的制动器。简单地说,制动器是紧夹住某种东西的一种装置。许多制动器使用模拟输入信号来控制夹紧压力(或制动功率)的大小。加在制动器上的电压或电流越大,制动器产生的压力就越大。

可以将PWM控制器的输出连接到电源与制动器之间的一个开关。要产生更大的制动功率,只需通过软件加大PWM输出的占空比就可以了。如果要产生一个特定大小的制动压力,需要通过测量来确定占空比和压力之间的数学关系(所得的公式或查找表经过变换可用于控制温度、表面磨损等等)。

例如,假设要将制动器上的压力设定为100psi,软件将作一次反向查找,以确定产生这个大小的压力的占空比应该是多少。然后再将PWM占空比设置为这个新值,制动器就可以相应地进行响应了。如果系统中有一个传感器,则可以通过闭环控制来调节占空比,直到精确产生所需的压力。

总之,PWM既经济、节约空间、抗噪性能强,是一种值得广大工程师在许多设计应用中使用的有效技术。

来源: 电子工程专辑

浏览 1 次
145

脉冲宽度调制(PWM),是英文“Pulse Width Modulation”的缩写,简称脉宽调制,是利用微处理器的数字输出来对模拟电路进行控制的一种非常有效的技术。PWM最基本的调节就是频率和占空比,通过调节频率和占空比对外部元件进行控制或者捕捉外部信号源。

在大功率电机、变频器、开关电源等方案中,末端都是由大功率管、IGBT等元件组成的H桥或3相桥。每个桥的上半桥和下半桥是是绝对不能同时导通的,但高速的PWM驱动信号在达到功率元件的控制极时,往往会由于各种各样的原因产生延迟的效果,造成某个半桥元件在应该关断时没有关断,造成功率元件烧毁。死区就是在上半桥关断后,延迟一段时间再打开下半桥或在下半桥关断后,延迟一段时间再打开上半桥,从而避免功率元件烧毁。

MM32L0系列MCU有多达9个定时器,高级定时器TIM1可以产生互补的PWM,高级定时器TIM1是1 个 16 位 4 通道高级控制定时器,有 4 通道 PWM 输出,以及死区生成和紧急停止功能,可以通过相关寄存器的设置使能或关闭PWM的输出。

高级控制定时器(TIM1)能够输出两路互补信号,并且能够管理输出的瞬时关断和接通。这段时间通常被称为死区,用户应该根据连接的输出器件和它们的特性(电平转换的延时、电源开关的延时等)来调整死区时间。

使用紧急停止功能,使能输出信号和无效电平都会被改变,关闭PWM输出,能够有效的预防突发事件造成外部电机等不可控的状态,刹车源既可以是刹车输入管脚又可以是一个时钟失败事件。时钟失败事件由复位时钟控制器中的时钟安全系统产生。在安全方面,你可以把刹车输入连到电源驱动的报警输出、热敏传感器或者其他安全器件上。

在编写电机的驱动程序时,需要利用TIM1的Channel1,2,3三个通道生成三路互补的PWM波形,TIM1需要配置的寄存器有:捕捉/比较模式寄存器 1(TIMx_CCMR1)、捕捉/比较使能寄存器(TIMx_CCER)、捕获/比较寄存器(TIMx_CCR1~3)和刹车和死区寄存器(TIMx_BDTR).
程序配置流程如下:

void TIM1_PWM_Init(u16 arr,u16 psc)
{ 
GPIO_InitTypeDef GPIO_InitStructure;
TIM_TimeBaseInitTypeDef  TIM_TimeBaseStructure;
TIM_OCInitTypeDef  TIM_OCInitStructure;
TIM_BDTRInitTypeDef TIM_BDTRInitStruct;
      
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB , ENABLE);
 
GPIO_InitStructure.GPIO_Pin =GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10; //TIM3_CH1  TIM3_CH1N
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
      
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15; //TIM3_CH1  TIM3_CH1N
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
      
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12; //TIM3_CH1  TIM3_CH1N
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
      
GPIO_PinAFConfig(GPIOA, GPIO_PinSource8,GPIO_AF_2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource9,GPIO_AF_2);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource10,GPIO_AF_2);
             
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13,GPIO_AF_2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource14,GPIO_AF_2);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource15,GPIO_AF_2);
             
GPIO_PinAFConfig(GPIOB,GPIO_PinSource12,GPIO_AF_2);
      
TIM_TimeBaseStructure.TIM_Period = arr;
TIM_TimeBaseStructure.TIM_Prescaler =psc;
TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1;
TIM_TimeBaseStructure.TIM_RepetitionCounter =0;
TIM_TimeBaseStructure.TIM_CounterMode= TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM1, &TIM_TimeBaseStructure);
 
TIM_BDTRInitStruct.TIM_OSSRState = TIM_OSSRState_Enable;
TIM_BDTRInitStruct.TIM_OSSIState = TIM_OSSIState_Enable;
TIM_BDTRInitStruct.TIM_LOCKLevel = TIM_LOCKLevel_OFF;
TIM_BDTRInitStruct.TIM_DeadTime = 0x99;
//TDTS = 125nS(8MHz)
//DTG[7: 5] = 0xx => DT = DTG[7: 0] * Tdtg, Tdtg = TDTS;
//DTG[7: 5] = 10x => DT =(64+DTG[5: 0]) * Tdtg, Tdtg = 2 * TDTS;
//DTG[7: 5] = 110 => DT =(32+DTG[4: 0]) * Tdtg, Tdtg = 8 * TDTS;
//DTG[7: 5] = 111=> DT =(32 + DTG[4: 0]) *  Tdtg, Tdtg = 16 * TDTS;
 
TIM_BDTRInitStruct.TIM_Break = TIM_Break_Enable;
TIM_BDTRInitStruct.TIM_BreakPolarity = TIM_BreakPolarity_High;
TIM_BDTRInitStruct.TIM_AutomaticOutput = TIM_AutomaticOutput_Enable;
TIM_BDTRConfig( TIM1, &TIM_BDTRInitStruct);     
      
TIM_OCStructInit(&TIM_OCInitStructure);
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 = 500;
TIM_OCInitStructure.TIM_OCPolarity = TIM_OCPolarity_High;
TIM_OCInitStructure.TIM_OCNPolarity=TIM_OCNPolarity_High;
TIM_OCInitStructure.TIM_OCIdleState=TIM_OCIdleState_Reset;
TIM_OCInitStructure.TIM_OCNIdleState=TIM_OCNIdleState_Reset;
             
TIM_OC1Init(TIM1, &TIM_OCInitStructure); 
TIM_OC2Init(TIM1, &TIM_OCInitStructure); 
TIM_OC3Init(TIM1, &TIM_OCInitStructure); 
 
TIM_OC1PreloadConfig(TIM1, TIM_OCPreload_Enable);  
TIM_OC2PreloadConfig(TIM1, TIM_OCPreload_Enable);  
TIM_OC3PreloadConfig(TIM1, TIM_OCPreload_Enable);  
 
TIM_ARRPreloadConfig(TIM1, ENABLE);
 
TIM_Cmd(TIM1, ENABLE);
      
}

第一步:开定时器TIM1的时钟和GPIOA\GPIOB的时钟。
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM1,ENABLE);
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOA | RCC_AHBPeriph_GPIOB , ENABLE);

第二步:配置GPIO的模式,根据UM_MM32L0系列产品手册的8.1.11外设的 GPIO 配置查表可以知配置CHx的输出比较通道x和互补输出通道x功能时,需将GPIO配置成推挽复用输出模式,配置定时器的刹车输入功能时GPIO需配置成浮空输入功能。

MM32 MCU互补PWM输出使能带死区、刹车功能

根据DS_MM32L0系列产品手册的表4和表5的端口功能复用列表可知,PA8\PA9\PA10的AF2是TIM1的CH1\CH2\CH3通道,PB13\PB14\PB15的AF2是TIM1的CH1N\CH2N\CH3N通道,所以在配置GPIO的复用功能选择时通过软件写入配置IO的复用功能为AF2。

在本试验中,通过配置PB12作为刹车信号源的输入脚。根据端口功能复用列表可知,PB12的AF2是TIM1的刹车输入功能。

MM32 MCU互补PWM输出使能带死区、刹车功能

MM32 MCU互补PWM输出使能带死区、刹车功能

第三步:配置定时器的基本功能,首先来了解定时器初始化参数结构体指针,结构体类型是TIM_TimeBaseInitTypeDef,该结构体主要包含5个成员变量:

typedef struct
{
        uint32_t TIM_Prescaler;
        uint32_t TIM_CounterMode;
uint32_t TIM_Period;
        uint32_t TIM_ClockDivision;
        uint8_t TIM_RepetitionCounter;
} TIM_TimeBaseInitTypeDef;

第一个参数TIM_Prescaler是用来设置分频系数的,MM32L0系列产品的高级定时器TIM1是挂在APB2上。在MM32所有例程中,在每次一启动时,在程序中就已经帮助客户配置好了APB的时钟,在system_MM32L0系列.c中如果您配置相对应的系统时钟,在时钟配置函数中,您可以看到已经对APB1\APB2\AHB的时钟做了配置,默认APB2的时钟是48MHz,所以定时器的时钟需用户根据自己的实际需求进行分频或者不分频操作。

MM32 MCU互补PWM输出使能带死区、刹车功能

第二个参数是TIM_CounterMode用来配置PWM模式,MM32L0系列产品的PWM模式有三种:向上计数模式、向下计数模式和中央对齐模式。
1、向上计数模式:例:当 TIMx_CNT 否则低。如果 TIMx_CCRx 中的比较值大于自动重装载值(TIMx_ARR),则 OCxREF 保持为‘1’。
2、向下计数模式:当 TIMx_CNT > TIMx_CCRx 时参考信号 OCxREF 为低,否则为高。如果 TIMx_CCRx中的比较值大于 TIMx_ARR 中的自动重装载值,则 OCxREF 保持为‘1’。
3、中央对齐模式:中央对齐模式又分为三种模式,根据不同的 CMS 位的设置,比较标志可以在计数器向上计数时被置‘1’、在计数器向下计数时被置‘1’、或在计数器向上和向下计数时被置‘1’。

中央对齐模式选择
MM32 MCU互补PWM输出使能带死区、刹车功能

第三个参数是TIM_Period用来设置自动重载计数周期值,自动装载寄存器是预先装载的,写或读自动重装载寄存器将访问预装载寄存器。根据在 TIMx_CR1 寄存器中的自动装载预装载使能位(ARPE)的设置,预装载寄存器的内容被立即或在每次的更新事件 UEV时传送到影子寄存器。当计数器达到溢出条件(向下计数时的下溢条件)并当TIMx_CR1 寄存器中的 UDIS位等于 0 时,产生更新事件。

第四个参数是TIM_ClockDivision用来设置时钟分频因子,该变量与后面死区持续时间配置有关,该变量是设置控制寄存器1(TIMx_CR1)的时钟分频因子CKD[1:0],这 2 位定义在定时器时钟(CK_INT) 频率、死区时间和由死区发生器与数字滤波器(ETR,TIx) 所用的采样时钟之间的分频比例。

第五个参数是TIM_RepetitionCounter用来设置重复计数值,该功能在上一篇文章有详细讲解。

第四步:配置定时器的刹车和死区,首先来了解定时器刹车和死区参数结构体指针,结构体类型是TIM_BDTRInitTypeDef,共7个成员变量:

    typedef struct
    {
        uint16_t TIM_OSSRState;
        uint16_t TIM_OSSIState;
        uint16_t TIM_LOCKLevel;
        uint16_t TIM_DeadTime;
        uint16_t TIM_Break;
        uint16_t TIM_BreakPolarity;
        uint16_t TIM_AutomaticOutput;
} TIM_BDTRInitTypeDef;

第一个参数是TIM_OSSRState用来配置运行模式下“关闭状态”选择。
第二个参数是TIM_OSSIState用来配置空闲模式下“关闭状态”选择。
第三个参数是TIM_LOCKLevel用来定时器的寄存器锁定保护,锁定级别分为3个级别,只能写入一次LOCK位,一旦写入TIMx_BDTR寄存器,则内容冻结至复位。
第四个参数是TIM_DeadTime设置死区时间,用户可根据UM_MM32L0xx手册的刹车和死区寄存器(TIM1x_BDTR)寄存器计算死区时间。
第五个参数是TIM_Break设置是否使能刹车功能。
第六个参数是TIM_BreakPolarity用来设置刹车输入电平。
第七个参数是TIM_AutomaticOutput设置BDTR寄存器的主输出使能(MOE)位。

第五步:配置定时器的PWM输出功能,

 typedef struct
    {
        uint16_t TIM_OCMode;
        uint16_t TIM_OutputState; 
        uint16_t TIM_OutputNState;          
        uint16_t TIM_Pulse;
        uint16_t TIM_OCPolarity;
        uint16_t TIM_OCNPolarity;
        uint16_t TIM_OCIdleState;
        uint16_t TIM_OCNIdleState;
    } TIM_OCInitTypeDef;

第一个参数是TIM_OCMode用来设置模式是输入捕获功能或者输出比较功能。
PWM 模式 1 - 在向上计数时,一旦 TIMx_CNT TIMx_CCR1 时通道 1 为无效电平(OC1REF= 0) ,否 则为有效电平(OC1REF = 1)
PWM 模式 2 - 在向上计数时,一旦 TIMx_CNT TIMx_CCR1 时通道 1 为有效电平,否则为无效电平。
第二个和第三个参数TIM_OutputState和TIM_OutputNState是配置互补通道输出使能。
第四个参数是TIM_Pulse用来设置待装入捕获比较寄存器的脉冲值,它的取值必须在 0x0000 和 0xFFFF之间。
第五和第六个参数TIM_OCPolarity和TIM_OCNPolarity是设置互补通道的极性是高还是低。
第七和第八个参数是TIM_OCIdleState和TIM_OCNIdleState用来设置刹车后的互补通道的电平状态。

第六步:初始化TIM1的OC1\OC2\OC3通道,使能定时TIM1。

逻辑分析仪抓取PWM波形
MM32 MCU互补PWM输出使能带死区、刹车功能
(逻辑分析仪精度不高,建议使用示波器抓波性)

小结:

1、PWM的频率和占空比计算:
//Fpwm = 48M / ((arr+1)*(psc+1))(单位:Hz)
//duty circle = TIM1->CCR1 / arr(单位:%)
本次配置参数:arr=999,psc=47,Pulse=500
Fpwm = 48M / ((arr+1)*(psc+1))=48M/ ((999+1)*(47+1))=1KHz
duty circle = (TIM1->CCR1 / arr )*100= (500/999)*100 = 50%

2、PWM互补通道电平设置:
通过上面截图可以看到互补通道的输出电平极性是相反的,如果用户需要配置互补通道输出相同的电平极性,需要配置的TIMx_CCER寄存器,通过库函数设置TIM_OCPolarity和TIM_OCNPolarity即可改变互补通道的电平输出极性。

MM32 MCU互补PWM输出使能带死区、刹车功能

3、刹车电平配置:
在配置刹车输入有效电平时,需先配置刹车和死区寄存器(TIMx_BDTR)的BKP位,配置为0时表示刹车输入低电平有效,配置为1时表示刹车输入高电平有效,在库函数中通过设置TIM_BreakPolarity变量即可实现有效电平设置,用户需根据外面信号来源配置对应的极性。

MM32 MCU互补PWM输出使能带死区、刹车功能

如上图所示,中间表示有刹车信号输入,关断PWM输出。在刹车信号关闭时,PWM又恢复输出,用户可以根据实际需求在刹车信号后是否恢复PWM输出,需要配置寄存器刹车和死区寄存器(TIMx_BDTR)的AOE位,在设置AOE位为0的情况下,触发刹车时,MOE关断,不再开启。

4、死区时间设置:
用户如果需要配置插入互补输出之间的死区持续时,需要配置刹车和死区寄存器(TIMx_BDTR)的死区发生器设置DTG[7:0],如下图所示,DT表示死区持续时间,Tdts为系统时钟周期,Tdtg表示乘以倍数后死区设置时间步进值。

MM32 MCU互补PWM输出使能带死区、刹车功能

Tdts = 1/48M = 20.83ns,TIM1_BDTR = 0xFF,高三位是0,所以选择第一个公式:
DT=(32+0x1F)*16* Tdts=(32+32)*16*20.83 = 21.3us。

MM32 MCU互补PWM输出使能带死区、刹车功能
(逻辑分析仪精度不高,建议使用示波器抓波性)

转自: 灵动微电子

围观 26
591

页面

订阅 RSS - PWM