专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

基于avr单片机I/O口输出SPWM程序

作者:佚名   来源:本站原创   点击数:  更新时间:2013年04月11日   【字体:

       基于ATmega16单片机输出SPWM程序,PWM频率为25KHZ,输出正弦波为50HZ,输出电压波形光滑,失真度小,只需要硬件和软件相结合。电路简单,只修改程序就可以调整功能,成本低,可靠性主高。
#include <avr/io.h>  
#include<avr/interrupt.h>  
#define BIT(x) (1<<x)  
//周期为20ms,产生50HZ的交流电,spwm频率为20k  
const unsigned char list[]={1,4,7,10,13,16,19,22,25,28,31,34,37,39,42,45,48,51,54,57,60,62,  
65,68,71,74,76,79,82,84,87,90,92,95,97,100,103,105,108,110,112,115,117,119,  
122,124,126,128,131,133,135,137,139,141,143,145,147,149,151,152,154,156,157,  
159,161,162,164,165,167,168,169,171,172,173,174,176,177,178,179,180,181,182,  
182,183,184,185,185,186,186,187,187,188,188,189,189,189,189,189,189,189,189,  
189,189,189,189,189,189,188,188,187,187,186,186,185,185,184,183,182,182,181,  
180,179,178,177,176,174,173,172,171,169,168,167,165,164,162,161,159,157,156,  
154,152,151,149,147,145,143,141,139,137,135,133,131,128,126,124,122,119,117,  
115,112,110,108,105,103,100,97,95,92,90,87,84,82,79,76,74,71,68,65,62,60,57,  
54,51,48,45,42,39,37,34,31,28,25,22,19,16,13,10,7,4,1};  
//周期为20ms,产生50HZ的交流电,spwm频率为20k  
int count,zf=0;  
void port_init(void)  
{  
PORTB = 0x00;  
DDRB  = 0xFF;//b口输出  
PORTC = 0x00;  
DDRC  = 0xFF;//c口输出  
PORTD = 0x00;  
DDRD  = 0xFF;//d口输出  
}  
//TIMER1 initialize - prescale:1  
// WGM13:0=10) PWM phz correct, TOP= ICR1  
// desired value: 10KHz  
// actual value: 10.000KHz (0.0%)  
void timer1_init(void)  
{  
TCCR1B = 0x00; //stop                                                                      
TCNT1H = 0xFF; /tup  
TCNT1L = 0x38;  
OCR1AH = 0x00;  
OCR1AL = 0xC8;  
OCR1BH = 0x00;  
OCR1BL = 0xC8;  
ICR1H  = 0x00;  
ICR1L  = 200;//    载波周期为50us              
TCCR1A = 0xA2; //10100010 top时更新OCR1A OCR1B,向上计数比较匹配清零,反之置位  
TCCR1B = 0x11; //start Timer 00010001  clk无分频,相位修正PWM  
TIMSK |= 0x20; //timer interrupt sources使能捕捉中断  
}  

//#pragma interrupt_handler timer1_capt_isr:7  
ISR(TIMER1_CAPT_vect)  
 

{   OCR1A=500;   OCR1B=500;  

if(zf)                                  

{  

  if(count<200)  
  {  
    if(count==1)       //此时2#管子才关断  
    {  
      //PORTB &= ~BIT(3);    //3#管子已经关断  
      PORTB |= BIT(4);     //开通4#管子  
    }  
  OCR1A=list[count++];     //开通1#管子  
  }  
  else if((count>=200)&&(count<400))  
  {  
    if(count==200)      
    {  
      PORTB &= ~BIT(4);    //关断4#管子  
    }  
    if(count==201)     //此时1#管子才关断  
    {  
       PORTB |= BIT(3);    //开通3#管子  
    }  
    OCR1B=list[count++-200];  //开通2#管子  
  }           else     {  
    count=0;      //2#管子已经关断  
    PORTB &= ~BIT(3);    //关断3#管子  
    //PORTB |= BIT(4);    //开通4#管子  
    OCR1A=list[count++];   //开通1#管子  
  }     }     else;   }  

//call this routine to initialize all peripherals  
void init_devices(void)  
{  
//stop errant interrupts until set up  
cli(); //disable all interrupts  
port_init();  
timer1_init();  

sei(); //re-enable interrupts  
//all peripherals are now initialized  
}  
// 主函数
int main(void)  
{  
init_devices();  
//insert your functional code here...  
 

zf = 1;   OCR1A=500;   OCR1B=500;   PORTB = 0;   while(1);  

}  

关闭窗口

相关文章