用ATmega8的T/C1和T/C2可以产生三路PWM 信号.
快速PWM 的产生就是先设定一个TOP值再设定一个比较值,然后,计数器开始计数,比如保持输出1,计数到设定的比较值时,电平变为0,并维持,然后继续计数到TOP 电平再变为1,如此重复循环.
1.T/C1可以产生2路(OC1A即PB1 OC1B即PB2).T/C2产生一路(OC2即PB3).
2.需要设定T/C1的寄存器有四个 TCCR1A TCCR1B(这两个寄存器一起决定了两路PWM信号的产生方式,频率和TOP值)OCR1A(此值/TOP就是占空比) OCR1B(设定第二路PWM的占空比)
2.需要设定T/C2的寄存器有2个 TCCR2(同理,这个寄存器决定了第三路PWM信号的产生方式,频率和TOP值 )
OCR2(这个寄存器决定占空比)
上面所述只能产生几个固定频率的PWM信号(占空比可以随便调),并且前两路的频率是一样的.如果想产生自己想要频率的PWM,需要用OCR1A
设定OCR1B的TOP值,由OCR1B产生PWM,此时OCR1A只能产生占空比50%的PWM.
下面是我用ATmega8产生三路频率31.25K,占空比分别为1/3 1/2 2/3 PWM 的程序. 8M
#include void main(void) { PORTB=0x00; DDRB=0x0E; // T/C1 初始化 TCCR1A=0xA1; TCCR1B=0x09; //匹配时清零,TOP:255,频率:8M/256=31.25K OCR1A=85; //占空比:1/3 OCR1B=128; //占空比:1/2 // T/C2 初始化 TCCR2=0x69; //匹配时清零,TOP:255,频率:31.25K OCR2=170; //占空比:2/3 while (1); } 用示波器观察过,占空你很精确,频率实测是30.22K,与理论值有点误差,可能频率高了,精确度就达不到了. 希望以上对初学者有所帮助. 2008-05-14,09:28:07 资料 邮件 回复 引用回复 ↑↑ ↓↓ 编辑 删除 我把注释再做详细一些,发上来。 同时做了一个占空比调节循环,可以观察到占空比从0~100%的变化过程(在Proteus中仿真) #include void delay(void) { unsigned int i,j; for(i=0; i<100; i++) for(j=0; j<10; j++); } int main(void) { unsigned char i; PORTB=0x00; DDRB=0x0E; // T/C1 初始化 TCCR1A=0xA1; //COM1A1~0 = 10 -> 升序计数时比较匹配将清零OC1A/OC1B,降序计数时的比较匹配将置位OC1A/OC1B //COM1B1~0 = 10 //WGM11~10 = 01 -> 8位快速PWM TCCR1B=0x09; //WGM13~12 = 01 //CS12~10 = 001 ->时钟选择:无预分频 //匹配时清零,TOP:255,频率:8M/256=31.25K OCR1A=85; //85/255 = 1/3 ,占空比:1/3 O CR1B=128; //128/255 = 1/2 占空比:1/2 // T/C2 初始化 TCCR2=0x69; //WG21 = 1, WG20 = 1 -> 快速PWM, TOP=255 //C0M21 = 1, COM20 = 1 -> 比较匹配发生时OC2置位,计数到TOP时OC2清零 //匹配时清零,TOP:255,频率:31.25K OCR2=170; //170/255 = 2/3 , 占空比:2/3 //占空比循环变化 while (1) { for(i=0; i< 255; i ++) { OCR1A = i; OCR1B = i; OCR2 = i; delay(); } } }下载本文