发现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; //改变频率
}
}
请各位AVR高手们帮帮忙,谢谢 我发现你的思路有重大缺陷!!!!!
while(1)
{
i++;
if(i>9)
{ i=0;
ICR1L_=0xB2;}
Delay(100); //延时
ICR1L=ICR1L_+i; //改变频率
} eblc1388 发表于 2012-7-25 23:49 static/image/common/back.gif
我发现你的思路有重大缺陷!!!!!
while(1)
首先先感谢你的帮助!!!
执行这条指令:
ICR1L=ICR1L_+i;
时,ICR1L_应该不会发生变化吧 eblc1388 发表于 2012-7-25 23:49 static/image/common/back.gif
我发现你的思路有重大缺陷!!!!!
while(1)
刚按你的方法试过了,还是一样的结果
谢谢 本帖最后由 5201314fff 于 2012-7-26 20:21 编辑
{:dizzy:}{:sweat:}郁闷得很 我发现原来是我的思路有重大缺陷!!!!!{:shy:}
eblc1388 发表于 2012-7-26 00:21 static/image/common/back.gif
我发现原来是我的思路有重大缺陷!!!!!
我正急用这个功能,没想到竟会是这样的结果
用了那么久的AVR,之前都没发现这个
难道要换单片机了? 啊,放心,原因也不难明白。
在你改变 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; //改变频率
} 换个示波器吧,你会看到不一样的结果的。 本帖最后由 wzyllgx 于 2012-7-26 09:55 编辑
这种问题我就不说了,自己去找找问题所在,提升一下能力,还先申明一下,绝对不是芯片的BUG,是不是你程序的问题我不肯定的说。
1000分,要记念一下。 自己找找原因,AVR不会出现出这种问题吧? 本帖最后由 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;// 再开 呵呵 没看懂 哈哈,谢谢你们{:smile:}
标题却是夸张了点 eblc1388 发表于 2012-7-26 01:35 static/image/common/back.gif
啊,放心,原因也不难明白。
在你改变 ICR1 值时,你忘记了 Timer1 是继续工作的。当 i=9 时(即 ICR1=0x00 ...
明白了,谢谢你啊{:tongue:}
标题写的夸张了, 还以为又有人发现M16的bug了{:sweat:} 应该是你使用的问题,avr的pwm不会有这问题。 关注下PWM,最近也要使用了。 {:hug:}谢谢各位 你的问题Mega16的数据手册上专门有强调过的,仔细看手册。 我原来也碰到这样的问题,当时没来这个论坛,哎 13楼正解。。。
页:
[1]