AVR Studio上的脉宽调制(PWM)
题
我试图在ATmega8上为LED使用PWM,端口B的任何引脚。设置定时器一直很烦人,我也不知道该怎么处理我的OCR1A。这是我的代码,我很想得到一些反馈。
我只是想弄清楚如何使用PWM。我知道这个概念,OCR1A应该是我想要脉冲的整个计数器时间的一小部分。
#define F_CPU 1000000 // 1 MHz
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
int main(void){
TCCR1A |= (1 << CS10) | (1 << CS12) | (1 << CS11);
OCR1A = 0x0000;
TCCR1A |= ( 0 << WGM11 ) | ( 1 << WGM10 ) | (WGM12 << 1) | (WGM13 << 0);
TCCR1A |= ( 1 << COM1A0 ) | ( 0 << COM1A1 );
TIMSK |= (1 << TOIE1); // Enable timer interrupt
DDRB = 0xFF;
sei(); // Enable global interrupts
PORTB = 0b00000000;
while(1)
{
OCR1A = 0x00FF; //I'm trying to get the timer to alternate being on for 100% of the time,
_delay_ms(200);
OCR1A = 0x0066; // Then 50%
_delay_ms(200);
OCR1A = 0x0000; // Then 0%
_delay_ms(200);
}
}
ISR (TIMER1_COMA_vect) // timer0 overflow interrupt
{
PORTB =~ PORTB;
}
解决方案 2
您需要使用这两行初始化OCR1A:
TCCR1A = (1 << WGM10) | (1 << COM1A1);
TCCR1B = (1 << CS10) | (1 << WGM12);
.
然后使用这个:
OCR1A = in
.
并且知道该范围是0-255。计算你的百分比,你有它!
#define F_CPU 1000000 // 1 MHz
#include <avr/io.h>
#include <avr/delay.h>
#include <avr/interrupt.h>
int main(void){
TCCR1A = (1 << WGM10) | (1 << COM1A1);
TCCR1B = (1 << CS10) | (1 << WGM12);
DDRB = 0xFF;
sei(); // Enable global interrupts
PORTB = 0b00000000;
while(1)
{
OCR1A = 255;
_delay_ms(200);
OCR1A = 125;
_delay_ms(200);
OCR1A = 0;
_delay_ms(200);
}
}
. 其他提示
不,这是 不是 你应该如何做一个PWM的方式。例如,你如何设置一个PWM率,例如,42%与它?此外,代码大小很大,可以以更有效的方式完成。此外,您浪费了一个16位计时器来执行8位操作。你有2个8位定时器(定时器/计数器0和2),和一个16位定时器, Timer/Counter 1
.
将未使用的portpins设置为输出也是一个坏主意。所有没有连接到任何东西的portpins都应该作为输入。
ATmega8在定时器1和2上内置PWM发生器,无需通过软件进行模拟。您甚至不必手动设置端口(您只需将相应的portpin设置为输出)
你甚至不需要任何中断。
#define fillrate OCR2A
//...
// main()
PORTB=0x00;
DDRB=0x08; //We use PORTB.3 as output, for OC2A, see the atmega8 reference manual
// Mode: Phase correct PWM top=0xFF
// OC2A output: Non-Inverted PWM
TCCR2A=0x81;
// Set the speed here, it will depend on your clock rate.
TCCR2B=0x02;
// for example, this will alternate between 75% and 42% PWM
while(1)
{
fillrate = 191; // ca. 75% PWM
delay_ms(2000);
fillrate = 107; // ca. 42% PWM
delay_ms(2000);
}
请注意,您可以使用另一个LED与另一个PWM,通过使用相同的定时器和设置OCR2B而不是OCR2A。不要忘记设置TCCR2A以启用OCR2B作为PWM的输出,因为在本例中只允许OCR2A。
不隶属于 StackOverflow