Широтно-импульсная модуляция (ШИМ) на AVR Studio
Я пытаюсь использовать PWM для светодиода на ATmega8, любой вывод порта B. настройка таймеров была раздражающей, и я не знаю, что делать с моим OCR1A. вот мой код, и я хотел бы получить обратную связь.
Я просто пытаюсь понять, как использовать ШИМ. Я знаю эту концепцию, и 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 ответов:
Нет, это Не способ, как вы должны делать ШИМ. Например, как вы устанавливаете скорость ШИМ, например, 42% с его помощью? Кроме того, размер кода велик, это можно сделать гораздо более эффективным способом. Кроме того, вы тратите 16-битный таймер на выполнение 8-битных операций. У вас есть 2 8-битных таймера (таймер/счетчик 0 и 2) и один 16-битный таймер,
Timer/Counter 1.Также не рекомендуется устанавливать неиспользуемые портпины для вывода. Все портпины, которые ни к чему не подключены, должны быть оставлены в качестве входов.
В ATmega8 имеет встроенный генератор ШИМ на таймерах 1 и 2, нет необходимости в его моделировании с помощью программного обеспечения. Вам даже не нужно устанавливать порты вручную (вам нужно только установить соответствующий портpin для вывода)
Вам даже не нужно прерываться.
#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); }Обратите внимание, что вы можете использовать другой светодиод с другим ШИМ, используя тот же таймер и установив OCR2B вместо OCR2A. не забудьте установить TCR2A, чтобы включить OCR2B в качестве выходного сигнала для вашего ШИМ, так как в этом примере используется только OCR2A. разрешено.
Вам нужно инициализировать 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); } }
Comments