王洁曦丑女无敌董迎迎:使用PWM调制信号产生多种波形

来源:百度文库 编辑:中财网 时间:2024/04/28 16:39:32

使用PWM调制信号产生多种波形 

                                                 作者:    

 在自身研发过程中,信号发生器是一个必不可少的仪器,但因为其价钱的缘故往往使个人研发者望而怯步。而往往我们需求的波形不多、要求精度也不是那么精密,因此对于满足一般性的要求波形发生器,我们可以用一片小型的单片机来完成。这样不但可以增加自身的技能还可以节省一批费用,何乐而不为呢。

       在大多设计中我们普遍采用求定点正弦函数值的做法:以产生正弦波为例,采用定点法来生成波形,即将一个周期的正弦波按360o等分为若干点,计算出各点的正弦函数值,并转化相应的D/A转换器输入数值,这样得到一个正弦函数表。通过程序将该表存于单片机的程序存储器中,利用单片机的定时器来产生定时,每当定时时间到时,查表得到该点对应的输出值,然后通过D/A转换得到该点的对应电压值。如此,周而复始地查表输出,就得到所要的正弦波。由于一个周期正弦波的点数固定,改变定时器的定时值,就改变相邻两点的间隔时间,从而改变正弦波的频率。 三角波和锯齿波的产生方法与正弦波类似。方波的产生较简单,只要交替地将最大值和最小值输出给D/A进行转换即可,它们的延续时间为周期的一半。 

       在此,我们通过另外一种更简便的方法来产生多种波形,使用单片机的PWM调制信号产生多种波形,但此种方法的缺陷就是产生波形的频率有限。

要:介绍了基于HT46R47单片机产生多种波形,采用放大器TL062,高速、稳定、具有良好的线性,用户通过按键选择输出需要的波形,波形精度能够满足一般的使用条件。

关键词:波形发生器、单片机HT46R47、放大器TL062、三角波、锯齿波、正弦波。

本文利用HT46R47单片机外接滤波电路,由HT46R47单片机产生不同占空比的PWM信号,经过滤波器将其窄带波形滤除掉从儿得到我们所需要的试验波形。由用户通过按键选择输出实验中经常使用到的几种基本波形:三角波、锯齿波、正弦波。

1 硬件设计

         HT46R47单片机时钟电路采用内部方式,外接晶体谐振器(频率为4 MHz),微调电容值为30 pF。系统复位采用掉电复位方式,通过按键由用户选择要输出的波形,按键选择占用PA.0~PA.7口,采用独立式键盘结构。利用HT46R47单片机内部自带的PWM发生器在 PD.0口上产生PWM信号,通过改变PWM信号的占空比来调节输出波形的频率。系统设计图如图1所示。

1.1            二级运算放大器TL062 

前面TL062AC是一个积分电路,其输出为:U01 = -1/RC∫U0dt;后面TL062AC为一个倒相器,

其输出为:U02 = -U01 = 1/RC∫U0dt;由图可知,U02 = -Ui,则 U0 = -RCdv/dt。

 

1.2 PWM调制原理

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

1-1 形状不同而冲量相同的各种窄脉冲

面积等效原理:

分别将如图1-1所示的电压窄脉冲加在一阶惯性环节(R-L电路)上,如图1-2a所示。其输出电流i(t)对不同窄脉冲时的响应波形如图1-2b所示。从波形可以看出,在i(t)的上升段,i(t)的形状也略有不同,但其下降段则几乎完全相同。脉冲越窄,各i(t)响应波形的差异也越小。如果周期性地施加上述脉冲,则响应i(t)也是周期性的。用傅里叶级数分解后将可看出,各i(t)在低频段的特性将非常接近,仅在高频段有所不同。

1-2 冲量相同的各种窄脉冲的响应波形

用一系列等幅不等宽的脉冲来代替一个正弦半波,正弦半波N等分,看成N个相连的脉冲序列,宽度相等,但幅值不等;用矩形脉冲代替,等幅,不等宽,中点重合,面积(冲量)相等,宽度按正弦规律变化。

SPWM波形——脉冲宽度按正弦规律变化而和正弦波等效的PWM波形。

1-3 PWM波代替正弦半波

要改变等效输出正弦波幅值,按同一比例改变各脉冲宽度即可。

 

2 软件设计

在硬件设计的基础上进行软件编程,由用户通过按键选择需要输出何种波形。按照波形发生器的功能,其应用程序必须有初始化、波形产生、键盘管理等几部分,我们在这里重点介绍正弦波的生成过程:

2.1 正弦波输出

我们在这里采用定时/计数器改变其PWM寄存器的值,从而改变PWM的占空比。首先设置定时/计数寄存器(TMR),定时/计数控制器(TMRC),中断控制寄存器(INTC)。然后通过HT46R47内部自带的脉冲宽度调制器,输出PWM信号。

PWM的占空比的计算方式:X(n)=PWM/256;

斜率点的计算方式:n=0~39;(取的点数)

                                      X(n)=(sin(0.05*Pi*n)+1)/2;

按照以上计算公式我们抽取了40个点一个周期,从而计算出我们所需要的PWM值,程序源代码如下 :

/**---------------文件信息-------------------------------------------------------------------------------

**文   件   名:      CreateWave.c

**创   建   人:     

**最后修改日期:    

**描        述:     

**-----------------历史版本信息------------------------------------------------------------------------

** 创建人:     

** 版  本:       v1.0

** 日 期:     

** 描 述:      原始版本

**--------------当前版本修订------------------------------------------------------------------------------

** 修改人:

** 版  本:

** 日 期:

** 描 述:

#include

//--------------------------RAM define--------------------------//

#define    IAR                     _iar

#define    MP                      _mp 

#define    ACC                   _acc

#define    PCL                     _pcl

#define    TBLP                  _tblp

#define    TBLH                 _tblh

#define    STATUS            _status

#define    INTC                  _intc

#define    TMR                   _tmr

#define    TMRC                _tmrc

#define    PA                       _pa

#define    PAC                    _pac

#define    PB                       _pb

#define    PBC                    _pbc

#define    PD                      _pd

#define    PDC                    _pdc

#define    PWM                 _pwm

#define    ADRL                 _adrl

#define    ADRH                _adrh

#define    ADER                 _ader

#define    ACSR                 _acsr

#define    TON                   _ton

#define    PD0                     _pd0

#define    PA7                     _pa7

//--------------------------I/O define--------------------------//

#define    KEY_1                _pa0

#define    KEY_2                _pa1

#define    KEY_3                _pa2

 

typedef  unsigned  char          uint8;                                    /*-----无符号8位整型变量------*/

typedef  signed  char               int8;                             /*-----有符号8位整型变量------*/

typedef  unsigned  long                   uint16;                                  /*-----无符号16位整型变量-----*/

typedef  signed  long              int16;                                     /*-----有符号16位整型变量-----*/

 

const uint8 wave[40]={128,148,168,186,203,219,232,242,250,254,255,254,250,242,232,219,203,186,

168,148,128,108,88,70,53,37,24,14,6,2,1,2,6,14,24,37,53,70,88,108}; 

const uint8 wave2[40]={128,131,134,137,140,144,147,150,153,156,160,163,166,169,172,176,179,

182,185,188,192,195,198,201,204,207,210,214,217,220,224,227,230,233,236,240,243,246,249,255};

const uint8 wave3[40]={128,140,153,166,179,192,204,217,230,243,255,243,230,217,204,192,179,166,

153,140,128,116,103,90,77,64,52,39,26,13,1,13,26,39,52,64,77,90,103,116};                      

uint8 Acc_buff,Status_buff,Key_flag,Point1,Point2,Point3;

unsigned long Tcounter1,Tcounter2,Tcounter3;

 

#pragma vector       Timer0       @0x08                                   //定时器0中断入口地址

 

/**********************************************************************************

** 函数名称: Delay()

** 功能描述: 延时函数

** 输 入:                x,x可决定延时时间的长短

** 输 出:                无       

** 全局变量: 无

** 调用模块: 无

** 作 者:              

** 日 期:               

/**********************************************************************************

void Delay(uint16 x)

 {

        uint16 i;

        if(x>=0xFFFF) x=0xFFFF;

        for(i=0; i

 }

 

/************************************************************************************ 函数名称:     SysInit()

** 功能描述: 系统初始化

** 输 入:               

** 输 出:                无       

** 全局变量: 无

** 调用模块: 无

** 作 者:               

** 日 期:               

/**********************************************************************************

void SysInit(void)

 {

                  INTC=0b00000101;        //允许定时器0中断      

        TMRC=0b10100010;             //定时器模式,无分频(Timer Rate为1:1)

        TMR=206;                         //256-206*1us==50us

        TON=1;

        PAC=0x0F;                    //PA设置为输入

        PBC=0x00;                //PB设置为输入

        PDC=0x00;                //PD设置为输出

                 Point1=Point2=Point3=Acc_buff=Status_buff=Key_flag=0;

                  Tcounter1=Tcounter2=Tcounter3=0;

                  PD0=1;

 

 }

/************************************************************************************ 函数名称:     Timer0()

** 功能描述: 定时器0函数

** 输 入:               

** 输 出:                无      

** 全局变量: 无

** 调用模块: 无

** 日 期:               

**********************************************************************************

void Timer0(void)

 {

                  Acc_buff=ACC;

                  Status_buff=STATUS;                                                              //保持现场

                  if(Key_flag==0x01) {Tcounter1++;Point2=Point3=0;}

                  if(Key_flag==0x02) {Tcounter2++;Point1=Point3=0;}

                  if(Key_flag==0x04) {Tcounter3++;Point1=Point2=0;}

                  TMR=206;

                  ACC=Acc_buff;

                  STATUS=Status_buff;

 }

 

/************************************************************************************ 函数名称:     main()

** 功能描述: 系统主程序

** 输 入:                无

** 输 出:                无     

** 全局变量: 无

** 调用模块: 无

** 作 者:               

** 日 期:               

/**********************************************************************************

void main(void)

 {

        SysInit();

        while(1)

                  {

                           if(Tcounter1>=50)                                 //f=10Hz的正弦波

                                    {

                                              Tcounter1=0;

                                              PWM=wave1[Point1];

                                              PD0=1;

                                              Point1++;

                                              if(Point1==40) Point1=0;

                                    }

                           if(Tcounter2>=50)                                           //f=10Hz的三角波形

                                    {

                                              Tcounter2=0;

                                              PWM=wave2[Point2];

                                              Point2++;

                                              if(Point2==40) Point2=0;

                                    }

                           if(Tcounter3>=50)                                           //f=10Hz的锯齿波形

                                    {

                                              Tcounter3=0;

                                              PWM=wave3[Point3];

                                              Point3++;

                                              if(Point3==40) Point3=0;

                                    }

                           //-----------------------------按键动作----------------------------------------//

                           if(KEY_1==0)

                                    {      

                                              Delay(500);

                                              if(KEY_1==0) {Key_flag=0x01;}

                                    }

                           else if(KEY_2==0)

                                    {

                                              Delay(500);

                                              if(KEY_2==0) Key_flag=0x02;

                                    }      

                           else if(KEY_3==0)

                                    {

                                              Delay(500);

                                              if(KEY_3==0) Key_flag=0x04;

                                    }

                          

                          

                  }

 }

2.2 锯齿波和三角波输出

锯齿波中的斜线用一个个小台阶来逼近,在一个周期内从最小值开始逐步递增,当达到最大值后又回到最小值,如此循环,当台阶间隔很小时,波形基本上近似于直线。适当选择循环的时间,可以得到不同周期的锯齿波。

而三角波形输出则和正弦波形输出类似。

         三角波斜率计算公式:n=0~39;

                                               X(n)=(n/10+1)/2;(n<=10)

                                               X(n)=((20-n)/10+1)/2; (10<><>

                                               X(n)=((n-40)/10+1)/2; (n>30)

         锯齿波的斜率计算公式:n=0~39;

                                               X(n)=n/40;

3         结语

本文基于HT46R47单片机的多种波形发生器产生的3种波形完全能够满足实验中的使用要求。通过软件实现可以输出更多的基本波形如:梯形波、三角波、反向锯齿波等,具有实际的使用价值。

<>