搜索
bottom↓
回复: 4

请教马老师关于PWM输出问题

[复制链接]

出0入0汤圆

发表于 2010-4-26 13:28:09 | 显示全部楼层 |阅读模式
产生SPWM用于逆变器控制H桥,从而产生频率和电压幅值可变的正弦波输出

思路是:用MEGA16的定时器1产生SPWM输出,每个采样点时刻的占空比存入这个数组sin_temp[j]=0.5+0.5*M*sin(j*2*PI/N);如果采用pwm输出模式8的话,则ICR1的值为TOP值,那么OCR1A,OCR1B中的寄存器值就为 (uint)(TOP*sin_temp),我想在进入比较匹配中断的时候(或者溢出中断的时候)改变OCR1A,OCR1B的值,这样输出就能产生两路互补的SPWM波,其中ICR1的值改变载波频率,M为调制度(用于改变电压幅值),N为载波比(改变输出电压频率)
但是我调试了好久都是只输出一个固定占空比的PWM

这是我的调试程序:

#include<iom16v.h>
#include<macros.h>
#include<math.h>

#define uint unsigned int
#define uchar unsigned char

#define PI 3.1415926
#define N 60   //载波比
#define FS 50  //基波频率
#define M 0.5  //调制比
#define FCLK 8000000//晶振
#define DeadTime 16  //死区时间控制系数

float sin_temp[N];//占空比
uint TOP1;
uint temp[N];
uchar count=1;

void port_init(void)
{
        DDRD|=BIT(4)|BIT(5);//        OC1A,OC1B互补输出
}

void timer1_init(void)
{   
         TCCR1A=0XB0;//1011 0000  OC1A,OC1B互补输出
         //TCCR1A=0XB3;
         TCCR1B=0X10;//0001 0000,PWM模式8,关定时器
         //TIMSK|=BIT(TOIE1);  //开输入捕捉中断
         TIMSK|=BIT(OCIE1A)|BIT(OCIE1B);//比较匹配中断
         //TIMSK|=BIT(TICIE1);//输入捕获中断开
         ICR1=(uint)(FCLK/(2*N*FS));
         OCR1A=temp[0]-DeadTime;
         OCR1B=temp[0]+DeadTime;
}

/*#pragma interrupt_handler t1_capt: 6  // T/C1的输入捕捉中断
void t1_capt(void)
{

                  OCR1A=(uint)(TOP1*sin_temp[count++])-DeadTime;
                OCR1B=(uint)(TOP1*sin_temp[count++])+DeadTime;
                PORTB^=BIT(3);
       
          if(count>N) count=0;  
}

#pragma interrupt_handler timer1_ovf:9 //T/C1的溢出中断
void timer1_ovf(void)
{
     count++;
         if(count<=N)
         {
            //OCR1A=(uint)(TOP1*sin_temp)-DeadTime;
            //OCR1B=(uint)(TOP1*sin_temp)+DeadTime;
                OCR1A=temp[count]-DeadTime;
                OCR1B=temp[count]+DeadTime;
                PORTB^=BIT(3);
               
         }
         else
         count=0;
}*/


#pragma interrupt_handler timer1_compa:7//比较匹配A中断
void timer1_compa(void)
{
         if(count<=N)
         {
                OCR1A=temp[count++]-DeadTime;       
         }
         else
         count=0;
}

#pragma interrupt_handler timer1_compb:8//比较匹配B中断
void timer1_compb(void)
{
         if(count<=N)
         {
                OCR1B=temp[count++]+DeadTime;
         }
         else
         count=0;
}

void main(void)
{
         uchar j;
         CLI();
         TOP1=(uint)(FCLK/(2*N*FS));
         port_init();
         for(j=0;j<N;j++)
         {
                   sin_temp[j]=0.5+0.5*M*sin(j*2*PI/N);//各采样点的占空比
                 temp[j]=(uint)(TOP1*sin_temp[j]);
         }
         
         timer1_init();
         TIFR=0;
         TCNT1=0;
         SEI();//开总中断
         TCCR1B=0X11;//PWM模式8,开定时器
         DDRB|=BIT(3);
         PORTB&=~BIT(3);
         while(1);
}

出0入0汤圆

发表于 2010-4-26 20:12:07 | 显示全部楼层
回复【楼主位】stoneke 木子李
-----------------------------------------------------------------------

在周期中断中,改变比较值OCR1A OCR1B,选频率和相位调整PWM模式。若频率固定应算出比较值放在程序中查表,另外死区时间用软件产生不可靠,没有硬件保护,建议使用TI 2000系列DSP,若速度要求不高的话可选用凌阳单片机,有一款16位单片机专为变频的。

出0入0汤圆

 楼主| 发表于 2010-4-26 21:00:38 | 显示全部楼层
我的思路就是这样的,在线实时就算采样点的占空比存入全局数组中,在匹配中断的时候改变比较值OCR1A OCR1B,可是问题是在进入中断的时候只有数组中的固定一个值赋给OCR1A OCR1B,所以输出的只是占空比不变的PWM波,不是想要的SPWM,你能看一下问题出在哪里吗?

出0入0汤圆

发表于 2010-4-27 21:00:45 | 显示全部楼层
在周期中断(溢出中断)中,改变比较值OCR1A OCR1B,选频率和相位修正PWM模式,设置比较匹配时的引脚输出,例如比较匹配A上升沿匹配时输出高电平,下降沿匹配时输出低电平,B和A应该正好相反。
请问你还有匹配中断干吗呢?

出0入0汤圆

 楼主| 发表于 2010-4-28 12:10:53 | 显示全部楼层
现在好像没有中断干扰,但是出来波形不是很理想。
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-2 12:49

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表