搜索
bottom↓
回复: 80

一个很简单的T1工作模式9(相频修正PWM)例程!

[复制链接]

出0入0汤圆

发表于 2004-12-26 20:16:44 | 显示全部楼层 |阅读模式
这个程序是用ICC的向导生成的,很简单。

T0是作为普通8位定时器,频率100KHz,每次中断将PB0(pin1)状态反转,产生的是200KHz占空比50%的方波。

        T1是作为工作模式9:相频可调PWM波发生器,频率初始化16KHz,占空比50%。请注意:



TCNT1是T0的定时器计数值,就是每个定时器时钟加1,和普通定时器的计数值寄存器作用一样。

OCR1A作为比较的TOP值。

OCR1B作为匹配输出值。



当TCNT1的值增加到OCR1B相等时,OC1B(pin18)清零,就是对应低电平;

然后TCNT1继续增加到OCR1A(就是TOP)的值,然后TCNT1开始减少,这个中间,OC1B(Pin18)状态不变;当TCNT1减少到OCR1B相等时,OC1B(pin18)置1,就是对应高电平。

然后TCNT1继续减少到0x00(就是BOTTOM),然后TCNT1又开始增加,这个中间,OC1B(pin18)状态不变。



OCR1B的值与OCR1A的比值就是PWM的占空比!



所以这个值必须比OCR1A小。当OCR1B为0时,PWM波就一直为低电平(相当于占空比为0);当OCR1B为OCR1A时,PWM波就一直为高电平(相当于占空比为100);当OCR1B为OCR1A的一半时,PWM波就是占空比为50%。



        你可以修改OCR1B的值,然后重新下载程序运行,看看占空比的改变;也可以修改OCR1A的值,然后重新下载程序运行,看看频率的改变,不过要注意修改OCR1A时,同时注意OCR1B的值不要比OCR1A大。



        模式9算是PWM生成中最复杂的一种,只要你理解了这个,对别的几种PWM都好理解。

出0入0汤圆

发表于 2004-12-26 20:47:43 | 显示全部楼层
讲解详尽,辛苦了,对于我等菜鸟帮助不小!

出0入0汤圆

发表于 2005-1-20 19:26:59 | 显示全部楼层
TCCR0 = 0x00; //stop

TCNT0 = 0xB0; //set count

OCR0  = 0x50;  //set compare

TCCR0 = 0x01; //start timer

工作在normal模式下  这个OCR0设置有什么意义啊





TCNT1H = 0xFF; //setup

TCNT1L = 0x06;



OCR1AH = 0x00;

OCR1AL = 0xFA;



OCR1BH = 0x00;

OCR1BL = 0x7D;

这里TCNT的值大于OCR1A和OCR1B  为什么啊 不理解

难道是让TCNT的值增加到FFFF后从零开始吗?



我今天用这个程序试了

出来的频率都不对啊

大概是标定频率的十分之一啊





哪位来解释一下

出0入0汤圆

发表于 2005-1-21 09:08:01 | 显示全部楼层
哪位来回答一下啊
头像被屏蔽

出0入0汤圆

发表于 2005-1-21 10:42:30 | 显示全部楼层
耐心一点等蜗牛啊!



人如其名啊。蜗牛当然会慢一点的啦 ....

出0入0汤圆

发表于 2005-1-22 14:13:54 | 显示全部楼层
蜗牛来一下啊

出0入0汤圆

发表于 2005-1-22 15:10:42 | 显示全部楼层
好老师...





肯定是个笔误:"TCNT1是T0的定时器计数值."



这正好说明绝得是个人心得...



马上要用到T26的PWM...



以前用过PIC的,AVR应该原理差不多...



我的理解为:



OCR1A是PWM的工作周期,即TCNT1从0到OCR1A(TOP)的计数值.

OCR1B为PWM的占空数(低电平宽度),其值应该在TCNT1的变化范围内.



"当OCR1B为0时,PWM波就一直为低电平(相当于占空比为0);当OCR1B为OCR1A时,PWM波就一直为高电平(相当于占空比为100);当OCR1B为OCR1A的一半时,PWM波就是占空比为50%。 "



当OCR1B为0时,由于TCNT1==OCR1B时翻为低电平,故从开始翻到OCR1A前都是低电平.

当TCNT1==OCR1A时本想再翻为高电平,但TCNT1此时翻为0即同时又和OCR1B(0x00),

故PWM波就一直为低电平,没有"翻身求解放"的机会...



同理,当OCR1B为OCR1A时,OCR1A既是翻低点又是翻高点,故PWM波就一直为高电平...



所以,不变周期的PWM脉宽调制时,可以可变OCR1B的大小来改变PWM的脉宽...



OCR1B>OCR1A应该不算"犯规",硬件规则肯定将其归为OCR1B=OCR1A....(不知AVR内部如何处理)



蜗牛老师不知我理解是否还行???没跑题吧...

出0入0汤圆

 楼主| 发表于 2005-1-22 15:39:40 | 显示全部楼层
sorry....慢了点慢了点。。。。我正在申请采购“高速移动”专利,期望能达到现在的2倍速,那时,就是蜗牛的幸福了……



TCNT0 = 0xB0; //set count

OCR0  = 0x50;

即使工作在normal模式下,这个OCR0仍然在和TCNT0进行比较,一旦匹配后,就会产生中断或者改变OC0脚上的电平(产生PWM)。改变这个值,就会改变中断发生的时间,或者改变OC0脚上的方波的频率了。



T1定时器1的模式9,相频修正模式,可以用来产生波形非常完整的PWM波。TCNT1设置初值,增加到0xFFFF的时间,然后从0开始计数,这个理解是正确的。可以画一个波形图对应理解一下:画一个占空比50%的方波,高电平上平分为1、2两段,低电平上平分为3、4两段。



1就是TCCNT1从初值加,-->0xFFFF阶段,这个阶段OCR1B为高电平;

2就是TCCNT1从0x00加-->OCR1B阶段,这个阶段为高电平;匹配后,变为低电平

3就是TCCNT1从OCR1B加-->OCR1A阶段,这个阶段为低电平;

4就是TCCNT1从OCR1A减-->OCR1B阶段,这个阶段为低电平;匹配后,变为高电平



TCCNT1的初值,就是保证第一段高电平的时间,这样才能形成一个完整周期的方波。而且,这个初值应该根据OCR1B的值而设,就是TCCNT1 = 0xffff-OCR1B+1;这样才能保证时间的匹配。

出0入296汤圆

发表于 2005-1-22 18:42:33 | 显示全部楼层
我写的程序哦

使用的是3*2扫描式键盘

显示用的是595驱动的4个数码管,B口先送位码 D口再送段码



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

程序名称:电机驱动程序

运行平台:ATMaga8 4m晶振

程序版本:2.0

程序说明:通过按键 或A/D输入来调节pw波

         pc0-pc4 对应 r3-r1(pc3 作为ad输入)

                 pwm 波通过pc5输出

                 当a/d输入有效时,键盘自动屏蔽

                 



键盘说明

                   [rest]   [+]  [-]

                [none] [none] [none ]

                 

作者:Gorgon Meducer



最后修改:Gorgon Meducer

修改时间:2004年12月29日



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



#include <iom8v.h>

#include <macros.h>



#pragma  interrupt_handler Timer1_ovf:9

#pragma  interrupt_handler Adc_isr:15   //

const char DispCode[]={0xfc,0x60,0xda,0xf2,0x66,0xb6,0xbe,0xe0,0xfe,0xf6,

0xee,0x3e,0x9c,0x7a,0x9e,0x8e}; //数码管译码表

const char DispBit[] = {0b11101111,0b11011111,0b10111111,0b01111111};//数码管初始位值



unsigned char Mark_Line=0x80;



//定时器延时

unsigned int Timer_Count_End=0;

unsigned int Timer_Count=0;



//unsigned char PressKey_Per_n_Timer_Ovf=0;        //定义按键时间计数器

unsigned char Press_Keys=0;    //按键代码



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

void Port_init(void);

void Timer0_init(void);

void Timer1_init(void);

void Timer1_ovf(void);

void Hardware_init(void);

void Delay_ms(unsigned int delay_time);

void Key_Press_Scan(void);

void adc_init(void);

void Display_Message(unsigned char Where,unsigned char Number,unsigned char delays);



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



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

                                                    端口初始化

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

void Port_init(void)

{

//定义c为输入

DDRC =0b11111111;

PORTC=0b11111111;

DDRC =0b00100000;   //PC5用来输出pw波



//定义B口为输出,用于显示数据

DDRB=0xff;

PORTB=0xff;



//定义D口为输出,用于显示数据

DDRD=0xff;

PORTD=0x00;



}



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

                                                    定时器0初始化

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

//TIMER0 initialize - prescale:1

// desired value: 20KHz

// actual value: 20.000KHz (0.0%)

//定时器0用来产生PW波

void Timer0_init(void)

{

TCCR0 = 0x00; //stop

TCNT0 = 0x38; //set count

TCCR0 = 0x01; //start timer

}



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

                                                    定时器1初始化

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

//定时器1主要用来做精确延时

void Timer1_init(void)                     

{

//定时器1部分

     TCNT1H = 0xE0;

     TCNT1L = 0xC0;

         TCCR1B = 0x01;                       //1分频,定时1ms

}



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

                                                    A/D初始化

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

void adc_init(void)

{

ADCSRA =0X00; //关闭AD

ADMUX = 0b00100011; //选择外部参考电源 ADC3 左对齐

ACSR = (1<<ACD); //关闭模拟比较器

ADCSRA = 0b10011110;//中断允许 64分频

}

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

                                                    A/D中断处理

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

void Adc_isr(void)

{

Mark_Line=ADCH; //读取高位数据(左对齐)

ADMUX = 0b00100011; //选择外部参考电源 ADC3 左对齐

ADCSRA |=(1<<ADSC);  //启动AD转换

}

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

                                                    定时器1中断处理程序

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

void Timer1_ovf(void)                                      //1ms中断程序,检测主程序标志

{

       TCNT1H = 0xE0;

       TCNT1L = 0xC0;                                    //复位1ms记数器

           if (Timer_Count>0)

                     {

                   Timer_Count++;

                  }

               

          

           if (Press_Keys==2)

                     {

                   Mark_Line++;

                   if (Mark_Line>0xff)

                     {

                         Mark_Line=0x00;

                         }

                  }

           if (Press_Keys==3)

              {

                   Mark_Line--;

                   if (Mark_Line<0x01)

                    {

                         Mark_Line=0xff;

                        }

                  }

           if (Press_Keys==1)

              {

                   Mark_Line=0x80;   //复位

                  }

       

        if (TCNT0>Mark_Line)

           {

           //驱动电机

             PORTC |= 0b00100000;

           }

          else

           {

           //停止驱动

             PORTC &= 0b11011111;

           }

}



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

                                                    系统初始化

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

void Hardware_init(void)

{

CLI();



Port_init();

Timer1_init();

Timer0_init();

adc_init();

TIMSK = 0x04;



SEI();

}



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

                                                    延时程序

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

/*void Delay_ms(unsigned int delay_time)

{

Timer_Count_End=delay_time;

Timer_Count=1;                         //启动计数器

re_delay:

if (Timer_Count<=Timer_Count_End)

        {

         if (TCNT0>Mark_Line)

           {

           //驱动电机

             PORTC |= 0b00100000;

           }

          else

           {

           //停止驱动

             PORTC &= 0b11011111;

           }

         goto re_delay;

         

        }

   else

    {

         Timer_Count_End=0;

         Timer_Count=0;

        }

}*/

void Delay_ms(unsigned int m)  //1ms延时

{

int l,j;

for(l=0;l<m;l++)

   for(j=0;j<500;j++)

   {

   if (TCNT0>Mark_Line)

           {

           //驱动电机

             PORTC |= 0b00100000;

           }

          else

           {

           //停止驱动

             PORTC &= 0b11011111;

           }

   }

}



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

                                                    按键扫描程序

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

void Key_Press_Scan(void)  //判断键值

{ //unsigned char temp=0;

    //扫描第一列

        Press_Keys=0;

        PORTC = 0b00000111;

    DDRC =  0b00110000;

        //temp=PINC;          

    if ( (PINC&0b00000100) == 0)   

          {

           Delay_ms(10);

           if ((PINC&0b00000100) == 0)

                     {

                  Press_Keys=1;

                  }

          }

    else if ((PINC&0b00000010) ==0)

          {

           Delay_ms(10);

           if ((PINC&0b00000010) ==0)

                     {

                  Press_Keys=2;

              }

          }

    else if ((PINC&0b00000001) ==0)   

          {

           Delay_ms(10);

           if ((PINC&0b00000001) ==0)

                     {

                  Press_Keys=3;

                  }

          }  



   /*

        //扫描第二列

        PORTC = 0b00010111;     

             

    DDRC =  0b00111000;

        //temp=PINC;

    if ( (PINC&0b00000100) == 0)

           {

                   Delay_ms(10);

            if ((PINC&0b00000100) == 0)

                     {

                  Press_Keys=4;

                  }

           }

    else if ((PINC&0b00000010) ==0)

           {

                   Delay_ms(10);

            if ((PINC&0b00000010) ==0)

                     {

                  Press_Keys=5;

                  }

           }       

    else if ((PINC&0b00000001) ==0)

           {

                   Delay_ms(10);

            if ((PINC&0b00000001) ==0)

                     {

                  Press_Keys=6;

                  }

           }*/

}





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

                                                    显示函数

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

void Display_Message(unsigned char Where,unsigned char Number,unsigned char delays)

{

//在指定的位置显示指定的数字

PORTD = DispBit[Where];  

PORTB = DispCode[Number]; //调用数码管译码表

Delay_ms(delays);

}



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

                                                        主函数

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

void main(void)

{

Hardware_init();

ADCSRA |=(1<<ADSC);  //启动AD转换

while(1)

   {

           if (TCNT0>Mark_Line)

           {

           //驱动电机

             PORTC |= 0b00100000;

           }

          else

           {

           //停止驱动

             PORTC &= 0b11011111;

           }

     Key_Press_Scan();

        Display_Message(0,((Mark_Line<<4)>>4),5);

        Display_Message(1,(Mark_Line>>4),5);

   }

}




-----此内容被Gorgon Meducer于2005-01-22,18:48:05编辑过

出0入296汤圆

发表于 2005-1-22 18:45:29 | 显示全部楼层
至于为什么在程序的很多地方都单独加了

    if (TCNT0>Mark_Line)

      {

      //驱动电机

        PORTC |= 0b00100000;

      }

     else

      {

      //停止驱动

        PORTC &= 0b11011111;

      }

是因为我生成的波周期很小30ns左右,多加一点,波的抖动会很小。为什么不把这一段程序做成函数的原因其实是一样的,因为编译以后,子程序的寻址过程会损耗额外的时钟周期。

出0入0汤圆

发表于 2005-1-22 23:56:08 | 显示全部楼层
如果我是工作在normal  而且不需要匹配中断 是不是OCR0  = 0x50;就不要了?

那个tccnt1是懂了

还有一个问题哦

我用这个程序最后的输出频率只有设定值的十分之一左右不知道是怎么回事



还有

我用icc自动生成的话

得到的寄存器值和例程上的不一样啊



对于timer1

按照例程上的频率

给出的结果是ocr1A和ocr1B的值 是一样的

怎么回事啊

-----此内容被wowo于2005-01-22,23:59:24编辑过


-----此内容被wowo于2005-01-23,00:03:20编辑过

出0入0汤圆

发表于 2005-4-5 10:57:02 | 显示全部楼层
如果展空比是时刻变化的,变化规律是DI=0.5+0.5sin(n*2pi/25),那该怎么办,请指点!

谢谢,我用的算m16

出0入0汤圆

 楼主| 发表于 2005-4-5 12:15:15 | 显示全部楼层
如果是模式9,那么每次变化后,算出占空比,算出OCR1B的值并赋值,会自动在下一个周期改变占空比为新值。easy。。。重点是:每次给OCR1B赋值,会在 下一个 周期改变占空比。

出0入0汤圆

发表于 2005-4-5 20:13:26 | 显示全部楼层
不是吧,对我来说觉得好难!



能否帮我写这个程序呢?

出0入0汤圆

发表于 2005-4-17 23:15:50 | 显示全部楼层
受益很大,好东东,当然要顶一下.

出0入0汤圆

发表于 2005-4-18 11:52:30 | 显示全部楼层
的確不錯!!

出0入0汤圆

发表于 2005-4-18 23:59:10 | 显示全部楼层
datasheet中的PWM让我看得很郁闷,这个帖子好啊。

出0入0汤圆

发表于 2005-4-19 03:01:50 | 显示全部楼层
好像是不对啊,我用软件做了个仿真,得出的结论是这样的:

PWM的频率是固定的,就是说如果是8位的PWM,那么TOP就只能是0x00FF(255);

                        如果是9位的PWM,那么TOP就只能是0x01FF(511);  

                        如果是10位的PWM,那么TOP就只能是0x03FF(1023);



还有TCNT1与OCR1A匹配时OC1A产生相应的输出;

    TCNT1与OCR1B匹配时OC1B产生相应的输出;



PWM输出的占空比为OCR1X/TOP,如:对于8位的PWM那就是OCR1X/255.(其中X=A或B)

出0入0汤圆

发表于 2005-4-20 10:59:18 | 显示全部楼层
ldi          r16,0x19

                sts          tccr1b,r16

                ldi          r16,0xe2

                sts          tccr1a,r16



                ldi   r16,0

                ldi   r17,250

                sts   icr1h,r16

                sts   icr1l,r17

               

                ldi   r19,0

                ldi   r20,20

                sts   ocr1ah,r19

                sts   ocr1al,r20



上面是我的M48程序,请问为什么是工作在9位的相位修正模式,而不是模式14(快速的PWM模式)。输出的更新确实是在OCR1A与TCNT1相等时?

这是什么因为,我该如何改呢?

急啊……


-----此内容被fly0123于2005-04-20,11:07:06编辑过

出0入0汤圆

发表于 2005-5-7 11:14:17 | 显示全部楼层
楼主的理解好象有问题啊,dzahz理解是正确的.

出0入0汤圆

发表于 2006-2-17 10:57:25 | 显示全部楼层
楼主的理解没错

dzahz理解也没错



关键是用的模式不同!

出0入0汤圆

发表于 2006-4-16 15:45:38 | 显示全部楼层
受教了,谢谢

出0入0汤圆

发表于 2006-4-27 17:16:58 | 显示全部楼层
我也想问一下,M16中用T1当用内部时钟的时候,不管是当成普通的定时用还是,输入捕捉用,

TCNT1从0x00往上加开始的时间是不是在TCC1B=0x01之后马上就开始啊?

51中是TR1=1就开启了。

出0入0汤圆

发表于 2006-7-9 10:43:06 | 显示全部楼层
看来好长时间没有人在此发言了。想问问相位和频率修正模式下为什么就会产生高精度得

PWM波形呢?

出0入0汤圆

发表于 2006-8-20 17:38:14 | 显示全部楼层
例程呢?

还有TCCNT1 = 0xffff-OCR1B+1,但是楼主好像算错了哦

出0入42汤圆

发表于 2006-8-20 22:04:06 | 显示全部楼层
收益,PWM搞明白了

出0入0汤圆

发表于 2006-11-29 12:00:26 | 显示全部楼层
经典!!感谢楼主的精辟讲解!!!

出0入0汤圆

发表于 2007-3-22 06:41:40 | 显示全部楼层
别忘了占空比应该还得看COM寄存器的赋值吧?

PWM的频率不是固定的,实际上是可以调节的

Fast PWM:fpwm= F_CPU/(TOP*Prescaler)

Phase PWM : fpwm = F_CPU/(2*TOP*Prescaler)

占空比要看COM寄存器的设置,比如在8位fast pwm下设置COM1B1:0=2的占空比为

1-(OC1B/255).若COM1B1:0=3,则占空比为OC1B/255。

弱弱的问一句,占空比指的是低电平的百分比么?

出0入0汤圆

发表于 2007-3-22 09:54:12 | 显示全部楼层
楼上关于占空比与COM寄存器的解释似乎反了吧,我在试验时发现设置为COM1X1:COM1X0=3时,程序开始后LED灯是常亮的,随后随着OCR1X值的增加慢慢变暗,这恰好说明了占空比等于1-(OCR1X/TOP).硬件很简单,端口直接连电阻然后接LED的正极对地.初始化T1寄存器如下(AT90S8515):

  TCCR1A=0xf3;                     

  TCCR1B=0x02;                     

  TCNT1H=0x00;                     

  TCNT1L=0x00;

  OCR1AH=0x00;                     

  OCR1AL=0x00;                     

  OCR1BH=0x00;                     

  OCR1BL=0x00;



另外,百度上面是这样说的:占空比是指高电平在一个周期之内所占的时间比率

出0入0汤圆

发表于 2007-3-22 16:27:03 | 显示全部楼层
呵呵,因为学的是英文的,没有接触到占空比这个词,见笑了。

出0入0汤圆

发表于 2007-3-28 22:02:11 | 显示全部楼层
是有问题吧,PWM模式下, 根据你所使用的晶振频率,再根据设置的分频系数,所产生的PWM的占空比是可调的,但是频率并不能改变!!!

出0入0汤圆

发表于 2007-4-11 10:50:00 | 显示全部楼层
相频可调PWM模式,

占空比和PWM的频率都是可调的吧?

比较匹配值确定占空比,

TOP值可以确定PWM频率的高低,

TOP值高,PWM周期长,频率就低;

TOP值低,PWM周期短,频率就长。

出0入0汤圆

发表于 2007-5-23 20:17:22 | 显示全部楼层
我的PWM模式9怎么就没波形出来呢??



请蜗牛老师指点一下,谢谢!!!



请哪位高手指点一下啊,我用VMLAB仿真不出来啊!!!是不是我的程序有问题呢???

小弟很头疼,谢谢了!!!



#include<avr/io.h>



int main(void)

{

PORTD = _BV(PD5);

DDRD = _BV(PD5);

TCCR1A = _BV(COM1A1);

TCCR1B = _BV(WGM13)|_BV(CS10)|_BV(CS11);       //64分频 模式8

TCNT1 = 0xFF01;

ICR1 = 0x01FF;                       // TOP值

OCR1A = 0x0080;                      // 控制占空比

while(1);

}

出0入0汤圆

发表于 2007-5-25 21:51:32 | 显示全部楼层
哪位高手来救救我吧,我要疯掉了!!!

出0入0汤圆

发表于 2007-8-1 17:00:39 | 显示全部楼层
void Port_init(void)

{

//定义c为输入

DDRC =0b11111111;

PORTC=0b11111111;

DDRC =0b00100000; //PC5用来输出pw波





请问,这里定义c为输入,为什么不直接将DDRC =0b00100000,而要之前加一个DDRC =0b11111111;

出0入0汤圆

发表于 2007-10-20 23:43:59 | 显示全部楼层
谁能给我一个用MAGE8做的时钟的程序和图?非常感谢了!

出0入0汤圆

发表于 2007-12-5 04:03:48 | 显示全部楼层
新学AVR,TIMER1的第九模式总是出不来,各位大侠指点指点吧。初来贵宝地,多多关照。。。

//ICC-AVR application builder : 2007-12-4 20:46:21
// Target : M16
// Crystal: 1.0000Mhz

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

void port_init(void)
{
PORTA = 0x00;
DDRA  = 0x00;
PORTB = 0x00;
DDRB  = 0x00;
PORTC = 0x00; //m103 output only
DDRC  = 0x00;
PORTD = 0x10;
DDRD  = 0x10;
}

//TIMER1 initialize - prescale:8
// WGM: 9) PWM phz freq correct, TOP=OCRnA
// desired value: 1KHz
// actual value:  1.008KHz (0.8%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop
TCNT1H = 0xFF; //setup
TCNT1L = 0xC2;
OCR1AH = 0xB0;
OCR1AL = 0x3E;
OCR1BH = 0x00;
OCR1BL = 0x3E;

TCCR1A = 0x11;
TCCR1B = 0x12; //start Timer
}

//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();

MCUCR = 0x00;
GICR  = 0x00;
TIMSK = 0x00; //timer interrupt sources
SEI(); //re-enable interrupts
//all peripherals are now initialized
}

//
void main(void)
{
init_devices();
//insert your functional code here...
while(1);
}

出0入0汤圆

发表于 2007-12-6 01:59:38 | 显示全部楼层
谢谢

出0入0汤圆

发表于 2007-12-11 17:30:03 | 显示全部楼层
太感谢了,画龙点睛我一看就明白了许多,比资料更通俗易懂,顶一下!

出0入0汤圆

发表于 2008-1-2 19:24:07 | 显示全部楼层
很高兴认识大家,我是新手,请大家多多关照,楼主的帖子给我很多启示,谢谢,大家的程序都是非常好的资料,以后有好的程序我也会发的,希望大家多提意见.

出10入0汤圆

发表于 2008-1-3 22:05:08 | 显示全部楼层
有点理解了,明天试一下

出10入0汤圆

发表于 2008-1-4 13:52:08 | 显示全部楼层
我觉得肯定还漏了一个关键问题,我用 MODE 9 也是不出波形

而且我用 OC1A 作为输出时,脉宽无法改变

出0入0汤圆

发表于 2008-1-23 16:11:50 | 显示全部楼层
我的没有调试成功,有例程了吗?

出0入0汤圆

发表于 2008-1-23 23:04:41 | 显示全部楼层
int main(void)
{
unsigned char i,j,k; //定义变量
PORTD=0xFF;                       
DDRD=0xFF;                                //PA口设为输出高电平,灯灭
PORTB=0xFF;

TCCR1A=_BV(COM1A1)|_BV(COM1A0)|_BV(WGM10);                        //8位快速PWM,模式 9
TCCR1B=_BV(WGM12)|_BV(CS10);                                      //无预分频

DDRB|=_BV(PB1)|_BV(PB2)|_BV(PB0);  
TCNT1=0;
TCCR1A = 0x4ff;
TCCR1B = 0x71; //start Timer

while(1)
{
        i=1;
        for (j=0;j<8;j++)  //循环8次,即PA0~~PA7轮流闪亮  
        {
                PORTD=~i;                //反相输出,低电平有效
                for (k=0;k<10;k++) _delay_ms(30);        //延时 30*10=300毫秒,可自行调节
                i=i<<1;                        //左移一位
        }
}
}


我写的就是没有信号来。帮我看看啊。

出0入0汤圆

发表于 2008-1-23 23:29:12 | 显示全部楼层
PWM的精华帖!嘿嘿!

出0入0汤圆

发表于 2008-1-24 09:41:03 | 显示全部楼层
我贴的是不行的程序,帮我看看哪的问题?

出0入0汤圆

发表于 2008-1-24 11:03:42 | 显示全部楼层

出0入0汤圆

发表于 2008-2-15 17:01:15 | 显示全部楼层
怎么没找到代码在哪下?

出0入0汤圆

发表于 2008-8-2 10:23:56 | 显示全部楼层
谁有GCC avr的简单的定时益出中断程序啊,谢了!

出0入0汤圆

发表于 2008-8-2 11:26:51 | 显示全部楼层
好贴,留名

出0入0汤圆

发表于 2008-8-2 15:34:35 | 显示全部楼层
做个记号

出0入0汤圆

发表于 2008-8-5 01:36:41 | 显示全部楼层

出0入0汤圆

发表于 2008-8-5 08:38:38 | 显示全部楼层
留個腳印

出0入0汤圆

发表于 2008-8-5 09:27:57 | 显示全部楼层
学习咯!

出0入0汤圆

发表于 2008-8-5 10:07:09 | 显示全部楼层
学习ing~~

出0入0汤圆

发表于 2008-8-5 18:32:36 | 显示全部楼层
MARK

出0入0汤圆

发表于 2008-8-6 08:09:34 | 显示全部楼层
昨天我仔细看了一下M16的手册,PWM的模式9 个人理解确实如楼主所说
而且几种模式比较 模式9 确实是最好用的模式。
但是有一个疑问 问楼主:OCR1B作为匹配输出值,但是在手册里面看到都是说OCRnX用于比较输出,好像没有提到OCR1B。
只是在说设置TOP值的时候用OCR1A。 不知道是不是我看漏咯

出0入0汤圆

发表于 2009-4-26 16:47:55 | 显示全部楼层
很好!

出0入0汤圆

发表于 2009-5-5 14:36:28 | 显示全部楼层
我笨,还是不明白
呵,

出0入0汤圆

发表于 2009-9-13 20:21:11 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-9-18 09:06:07 | 显示全部楼层
这个贴子挺好的

出0入0汤圆

发表于 2009-9-18 22:41:39 | 显示全部楼层
这个AVR让我快受不了了,好难学

出0入0汤圆

发表于 2009-9-20 13:40:25 | 显示全部楼层
mark1

出0入0汤圆

发表于 2009-10-10 17:02:04 | 显示全部楼层
不是我赞美小日本  但是小日本的datasheet比老美的容易懂多了 AVR的我看的迷迷糊糊

出0入0汤圆

发表于 2009-10-21 10:15:37 | 显示全部楼层
大家用ICCAVR的TOOLS里的application builder设置

用里面的初始化得到TCCNT1 OCR1nX  ...

出0入0汤圆

发表于 2009-12-3 17:52:37 | 显示全部楼层
各位兄弟们,,我也搞了一天,,基本搞定了,,模式9的时候,,OC1A是不会输出波形的,,因为OCR1A用作了TOP值,,所以模式9的时候一定要用OC1B输出PWM波形,,就是说COM1B1和COM1B0要配置,,我的是mega88,,就是用16脚输出波形~~搞了一天,,郁闷,,鄙视一下avr的PDF!!

出0入0汤圆

发表于 2009-12-4 10:30:51 | 显示全部楼层
郑重声明 上面那个king23不是我,一个PWM搞一天,还说PDF写的差。
avr能有中文PDF就知足吧,虽然里面有个别错误,会误导,但是如果耐心仔细看的话是能分辨出来的。
再者只要是用了PWM输出,COMnXn位的配置都是要注意的。

出0入0汤圆

发表于 2010-1-21 20:27:00 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-1-26 22:19:49 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-20 20:36:23 | 显示全部楼层
很好!

看了半天的 PDF,可是PDF确没说明,如果早看到这篇文章就好了。

谢谢蜗牛!



明天试一下

出0入0汤圆

发表于 2010-7-27 21:02:20 | 显示全部楼层
好好学习

出0入0汤圆

发表于 2010-7-27 21:38:31 | 显示全部楼层
明天试试这个

出0入0汤圆

发表于 2010-7-30 14:27:59 | 显示全部楼层
pwm

出0入0汤圆

发表于 2010-12-12 00:39:23 | 显示全部楼层
鼎好,学习~~

出0入0汤圆

发表于 2012-1-31 18:53:27 | 显示全部楼层
一点就通!还是英文datasheet不行啊,看了一天没看懂,这个中文一下子就理解了,这是肯定的,包含着lz自己的劳动成果!

出0入0汤圆

发表于 2012-2-13 19:20:01 | 显示全部楼层
好的,手下了。Mark

出0入0汤圆

发表于 2012-3-4 17:32:41 | 显示全部楼层
模式9 我了个凑。。。。 我用的 16 只有 模式4 啊。。。呵呵。。。。。另外在此请教下 PWM 做DA 8位精度都是怎么滤波的

出0入0汤圆

发表于 2012-3-9 17:13:32 | 显示全部楼层
收下个,mark

出0入4汤圆

发表于 2014-8-25 00:10:58 | 显示全部楼层
king23 发表于 2009-12-3 17:52
各位兄弟们,,我也搞了一天,,基本搞定了,,模式9的时候,,OC1A是不会输出波形的,,因为OCR1A用作了TO ...

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

本版积分规则

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

GMT+8, 2024-4-29 13:16

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

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