5201314fff 发表于 2012-7-25 23:31:15

发现M16的TC1的重大缺陷!!!!!

本人用M16的TC1产生PWM信号,并且在产生信号的同时不断改变频率,但变频幅度很小,这时就出现一个很令人费解的现象,PWM信号会不时有断开的现象

PWM频率:28KHz
OC1A、OC1B双路输出:想得到的信号是:如图正常的波形


但是一旦改变频率,两路的信号会随即的中断6.5ms左右,如图断开的波形,不知其解,各位高手请指教


程序:

// Target : M16
// Crystal: 10.000Mhz
#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 = 0x00;
DDRD= 0b00110000;
}

//TIMER1 initialize - prescale:1
// WGM: 8) PWM phz freq correct, TOP=ICRn
// desired value: 28KHz
// actual value: 28.090KHz (0.3%)
void timer1_init(void)
{
TCCR1B = 0x00; //stop

TCNT1H = 0xFF; //setup
TCNT1L = 0x4E;

OCR1AH = 0x00;
OCR1AL = 0xB2-0x50;

OCR1BH = 0x00;
OCR1BL = 0x50;

ICR1H= 0x00;
ICR1L= 0xB2;

TCCR1A = 0xB0;
TCCR1B = 0x11; //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 Delay(unsigned int t)
{
   unsigned int i,j;
   
   for(i=0;i<t;i++)
      for(j=0;j<280;j++);

}

void main(void)
{
unsigned char i;
unsigned char ICR1L_;

i=0;
ICR1L_=0xB2;

SPH=0;
SPL=220;

port_init();
init_devices();
timer1_init();


while(1)
{
   i++;
    if(i>9)i=0;
   
    Delay(100); //延时
   
   ICR1L=ICR1L_+i; //改变频率


}


}



5201314fff 发表于 2012-7-25 23:48:48

请各位AVR高手们帮帮忙,谢谢

eblc1388 发表于 2012-7-25 23:49:17

我发现你的思路有重大缺陷!!!!!

while(1)
{
   i++;
    if(i>9)
   { i=0;
    ICR1L_=0xB2;}
   
    Delay(100); //延时
   
   ICR1L=ICR1L_+i; //改变频率


}

5201314fff 发表于 2012-7-25 23:54:53

eblc1388 发表于 2012-7-25 23:49 static/image/common/back.gif
我发现你的思路有重大缺陷!!!!!

while(1)


首先先感谢你的帮助!!!

执行这条指令:
ICR1L=ICR1L_+i;
时,ICR1L_应该不会发生变化吧

5201314fff 发表于 2012-7-25 23:57:50

eblc1388 发表于 2012-7-25 23:49 static/image/common/back.gif
我发现你的思路有重大缺陷!!!!!

while(1)


刚按你的方法试过了,还是一样的结果
谢谢

5201314fff 发表于 2012-7-26 00:02:29

本帖最后由 5201314fff 于 2012-7-26 20:21 编辑

{:dizzy:}{:sweat:}郁闷得很

eblc1388 发表于 2012-7-26 00:21:17

我发现原来是我的思路有重大缺陷!!!!!{:shy:}

5201314fff 发表于 2012-7-26 00:40:27

eblc1388 发表于 2012-7-26 00:21 static/image/common/back.gif
我发现原来是我的思路有重大缺陷!!!!!

我正急用这个功能,没想到竟会是这样的结果
用了那么久的AVR,之前都没发现这个
难道要换单片机了?

eblc1388 发表于 2012-7-26 01:35:21

啊,放心,原因也不难明白。

在你改变 ICR1 值时,你忘记了 Timer1 是继续工作的。当 i=9 时(即 ICR1=0x00BB) 而 TCNT1 > 0x00B2 但又未到达 ICR1 顶点,而你特然把 ICR1 改回 0x00B2,那 Timer1 便会一直向上工作至 65535, 0....,直至 0x00B2。

解决办法也很简单,在 TCNT1 > 0x00AA 後不容许改变 ICR1 的值。

while(1)
{
   i++;
    if(i>9) i=0;
   
    Delay(100); //延时
   
    while ( TCNT1L > 0xAA);// 如 TCNT1L 大於 0xAA 时在此等候

   ICR1L=ICR1L_+i; //改变频率


}

ahuang227 发表于 2012-7-26 09:25:50

换个示波器吧,你会看到不一样的结果的。

wzyllgx 发表于 2012-7-26 09:53:04

本帖最后由 wzyllgx 于 2012-7-26 09:55 编辑

这种问题我就不说了,自己去找找问题所在,提升一下能力,还先申明一下,绝对不是芯片的BUG,是不是你程序的问题我不肯定的说。


1000分,要记念一下。

gyzzg2030 发表于 2012-7-26 10:13:07

自己找找原因,AVR不会出现出这种问题吧?

t3486784401 发表于 2012-7-26 10:19:57

本帖最后由 t3486784401 于 2012-7-26 10:21 编辑

改变计数顶端时,程序必须确保新的计数顶端不低于当前的计数值,否则计数器就得转一圈。

10MHz主频、分频系数N=1情况下,转一圈(近似65536个计数)时间也就差不多6.5ms.

9楼很正确,或者先把定时器停下来,复位计数值,再改ICR1:

TCCR1B=0;   // 关定时器
TCNT1H=0;
TCNT1L=0;
ICR1L=ICR1L_+i; //改变频率
TCCR1B=0x11;// 再开

eryueniao 发表于 2012-7-26 10:35:31

呵呵   没看懂                                                                           

5201314fff 发表于 2012-7-26 11:57:10

哈哈,谢谢你们{:smile:}

标题却是夸张了点

5201314fff 发表于 2012-7-26 12:00:16

eblc1388 发表于 2012-7-26 01:35 static/image/common/back.gif
啊,放心,原因也不难明白。

在你改变 ICR1 值时,你忘记了 Timer1 是继续工作的。当 i=9 时(即 ICR1=0x00 ...

明白了,谢谢你啊{:tongue:}


标题写的夸张了,

Jigsaw 发表于 2012-7-26 12:06:19

还以为又有人发现M16的bug了{:sweat:}

coobot 发表于 2012-7-26 12:41:21

应该是你使用的问题,avr的pwm不会有这问题。

kerrwang1982 发表于 2012-7-26 13:14:04

关注下PWM,最近也要使用了。

5201314fff 发表于 2012-7-26 13:56:44

{:hug:}谢谢各位

enotss 发表于 2012-7-31 16:03:23

你的问题Mega16的数据手册上专门有强调过的,仔细看手册。

badrobot 发表于 2012-8-31 23:30:12

我原来也碰到这样的问题,当时没来这个论坛,哎

sco518 发表于 2012-9-1 08:04:48

13楼正解。。。
页: [1]
查看完整版本: 发现M16的TC1的重大缺陷!!!!!