新浪博客

脉冲宽度调制(PWM)

2011-08-23 11:53阅读:
脉冲宽度调制(PWM)是一种对模拟信号电平进行数字编码的方法。通过高分辨率计数器的使用,方波占空比调制用来对一个具体模拟信号的电平进行编码。PWM信号仍然是数字的,因为在给定的任何时刻,满幅值的直流供电要么完全有(ON),要么完全无(OFF)。电压或电流源是以一种通(ON)或断(OFF)的重复脉冲序列被加到模拟负载上去的。通的时候即是直流供电被加到负载上的时候,断的时候即是供电被断开的时候。只要带宽足够,任何模拟值都可以使用PWM进行编码。
  多数负载(无论是电感性负载还是电容性负载)需要的调制频率高于10Hz,通常调制频率为1kHz到200kHz之间。
  许多微控制器内部都包含有PWM控制器。例如,Microchip公司的PIC16C67内含两个PWM控制器,每一个都可以选择接通时间和周期。占空比是接通时间与周期之比;调制频率为周期的倒数。执行PWM操作之前,这种微处理器要求在软件中完
成以下工作:
  1、设置提供调制方波的片上定时器/计数器的周期
  2、 在PWM控制寄存器中设置接通时间
  3、设置PWM输出的方向,这个输出是一个通用I/O管脚
  4、启动定时器
  5、使能PWM控制器
  目前几乎所有市售的单片机都有PWM模块功能,若没有(如早期的8051),也可以利用定时器及GPIO口来实现。更为一般的PWM模块控制流程为(笔者使用过TI的2000系列,AVR的Mega系列,TI的LM系列):
  1、使能相关的模块(PWM模块以及对应管教的GPIO模块)。
  2、配置PWM模块的功能,具体有:
  ①:设置PWM定时器周期,该参数决定PWM波形的频率。
  ②:设置PWM定时器比较值,该参数决定PWM波形的占空比。
  ③:设置死区(deadband),为避免桥臂的直通需要设置死区,一般较高档的单片机都有该功能。
  ④:设置故障处理情况,一般为故障是封锁输出,防止过流损坏功率管,故障一般有比较器或ADC或GPIO检测。
  ⑤:设定同步功能,该功能在多桥臂,即多PWM模块协调工作时尤为重要。
  3、设置相应的中断,编写ISR,一般用于电压电流采样,计算下一个周期的占空比,更改占空比,这部分也会有PI控制的功能。
  4、使能PWM波形发生。
脉冲宽度调制优点
  PWM的一个优点是从处理器到被控系统信号都是数字形式的,无需进行数模转换。让信号保持为数字形式可将噪声影响降到最小。噪声只有在强到足以将逻辑1改变为逻辑0或将逻辑0改变为逻辑1时,也才能对数字信号产生影响。
  对噪声抵抗能力的增强是PWM相对于模拟控制的另外一个优点,而且这也是在某些时候将PWM用于通信的主要原因。从模拟信号转向PWM可以极大地延长通信距离。在接收端,通过适当的RCLC网络可以滤除调制高频方波并将信号还原为模拟形式。
  总之,PWM既经济、节约空间、抗噪性能强,是一种值得广大工程师在许多设计应用中使用的有效技术。

实例说明
本例介绍一种新型PWM输出的方式,它是用单片机89C52作为主控部分,用8254可编程定时器/计数器来实现步进式PWM的输出;具有分辨率高、反应速度快及占用CPU时间少的优点。
本例的功能模块可以分为以下几个部分:
(1)单片机89C52:主控部分,控制外部计数芯片实现脉冲计数;
(2)外部计数器电路:计数芯片与单片机的接口电路,以及外围电路;
(3)单片机程序:控制技术芯片正常工作。
设计思路分析 在进行单片机实现步进式PWM信号输出设计之前,了解PWM控制技术的知识是至关重要的。
PWM基本原理及其实现方法
PWM是通过控制固定电压的直流电源开关频率,从而改变负载两端的电压,进而达到控制要求的一种电压调整方法。PWM可以应用在许多方面,如电机调速、温度控制、压力控制等。
(1) PWM基本原理
脉冲宽度调制波通常由一列占空比不同的矩形脉冲构成,其占空比与信号的瞬时采样值成比例。如图6-42(a)和(b)所示分别表示脉冲宽度调制系统的原理框图和波形图。
脉冲宽度调制(PWM)
图6-42 脉冲宽度调制系统的原理框图和波形图
该系统有一个比较器和一个周期为Ts的锯齿波发生器组成。语音信号如果大于锯齿波信号,比较器输出正常数A,否则输出0。因此,从图1中可以看出,比较器输出一列下降沿调制的脉冲宽度调制波。
通过图6-42(b)的分析可以看出,生成的矩形脉冲的宽度取决于脉冲下降沿时刻t k时的语音信号幅度值。因而,采样值之间的时间间隔是非均匀的。在系统的输入端插入一个采样保持电路可以得到均匀的采样信号,但是对于实际中tk-kTs<<Ts的情况,均匀采样和非均匀采样差异非常小。脉冲宽度调制波可以直接通过低通滤波器进行解调。
(2)实现方法
实现数字脉冲宽度调制器的基本思想如图6-43所示。
脉冲宽度调制(PWM)
图6-43 数字脉冲宽度调制器的构成
图6-43中,在时钟脉冲的作用下,循环计数器的5位输出逐次增大。5位数字调制信号用一个寄存器来控制,不断于循环计数器的输出进行比较,当调制信号大于循环计数器的输出时,比较器输出高电平,否则输出低电平。循环计数器循环一个周期后,向寄存器发出一个使能信号EN,寄存器送入下一组数据。在每一个计数器计数周期,由于输入的调制信号的大小不同,比较器输出端输出的高电平个数不一样,因而产生出占空比不同的脉冲宽度
调制波。
奇偶序列的产生方法是将计数器的最后一位作为比较数据的最低位,在一个计数周期内,前半个周期计数器输出最低位为0,其他高位逐次增大,则产生的数据即为偶数序列;后半个周期输出最低位为1,其余高位依次减小,产生的数据为依次减小的偶序列。
具体电路如图6-44所示。
脉冲宽度调制(PWM)
图6-44 数字PWM实现电路

一般情况下,调节脉冲宽度信号的脉宽有两种方法,一种方法是采用模拟电路中的调制方法,另一种是脉冲计数法。对于一般电机控制,由于滤波频率较低、滤波精度要求高和滤波电路的参数不易调整地原因,采用第一种方法在控制电压变化时滤波的实现存在较大的困难。因此,本例主要介绍单片机控制实现的脉冲计数法。
硬件电路设计
本例将实现3路PWM信号输出,定时/计数芯片8254具有3个独立的计数器,只需要选择一片就可以满足要求。硬件电路设计部分主要由单片机控制部分电路,定时/计数芯片8254电路以及单片机与定时/计数芯片8254的接口电路组成。
单片机控制部分电路原理图如图6-47所示。
脉冲宽度调制(PWM)
图6-47 单片机控制部分电路原理图
图中所示,单片机部分采用Atmel公司的AT89C52(U1),工作时钟为12MHz,P0.0~P0.7口与计数芯片8254的数据口D0~D7相连,8254的片选信号线连接在单片机的P2.0口,P2.1、P2.2与8354的地址线A1、A0相连,8254的读、写控制脚分别连接在单片机的P3.7(读)、P3.6(写)口。
定时/计数芯片8254电路原理图如图6-48所示。
脉冲宽度调制(PWM)
图6-48 定时/计数芯片8254电路原理图
定时/计数芯片8354(U2)由3个计数器输出3路独立的PWM信号,分别为PWM_1、PWM_2和PWM_3,3个计数器的输入时钟均为1MHz,他们的门控制输入均接高电平,确保信号连续输出。

软件设计流程
单片机实现3路PWM信号输出的流程图如图6-49所示。
脉冲宽度调制(PWM)
图6-49 单片机实现3路PWM信号输出的流程图
程序说明
基于8254产生PWM信号的程序主要包括三方面内容:一是定义8253寄存器的地址,二是控制字的写入,三是数据的写入。
具体代码如下:
#include <reg52.h> //引用标准库的头文件
#include <absacc.h>
#include <stdio.h>
#define COMWORD XBYTE[0x0600] //控制字寄存器地址
#define COUNT0 XBYTE[0x0000] //计数器0寄存器地址
#define COUNT1 XBYTE[0x0200] //计数器1寄存器地址
#define COUNT2 XBYTE[0x0400] //计数器2寄存器地址
void main()
{
EA = 1;//开CPU中断
ET0 = 1; //开定时器0中断
TMOD = 0x01; //定时器0工作方式1
TH0 = -(20000/256); //20ms定时器的计数初值
TL0 = -(20000%6);
//选择计数器0,初值为0
COMWORD = 0x30;
COUNT0 = 0; //低位字节
COUNT0 = 0; //高位字节
//选择计数器1,初值为0
COMWORD = 0x70;
COUNT0 = 0; //低位字节
COUNT0 = 0; //高位字节
//选择计数器2,初值为0
COMWORD = 0xB0;
COUNT0 = 0; //低位字节
COUNT0 = 0; //高位字节
TR0 = 1; //启动定时器T0
while(1){}
}
//定时器0中断服务子程序
void timer0_int() interrupt 1 using 1
{
TR0 = 0; //关闭T0
TH0 = -(20000/256); //重置20ms定时器的计数初值
TL0 = -(20000%6);
//发送第1路PWM信号
COMWORD = 0x30; //计数1000次,实现1ms高电平
COUNT0 = 0xE8;
COUNT0 = 0x03;
//发送第2路PWM信号
COMWORD = 0x70; //计数2000次,实现2ms高电平
COUNT0 = 0xD0;
COUNT0 = 0x07;
//发送第3路PWM信号
COMWORD = 0xB0; //计数3000次,实现3ms高电平
COUNT0 = 0xB8;
COUNT0 = 0x0B;
TR0 = 1; //启动T0
}

我的更多文章

下载客户端阅读体验更佳

APP专享