Управление светодиодом с помощью ШИМ + 1 Гц прямоугольной волны в выходном проекте (ATMEGA328p) - PullRequest
0 голосов
/ 30 сентября 2019

Я изучаю микроконтроллеры во второй раз (я не очень разбираюсь в них, кроме базового программирования на ATMega128) и ищу помощь в школьном проекте. Мне нужно создать проект, в котором:

Я управляю светодиодом (или вентилятором) через ШИМ (через счетчики таймеров и т. Д.) Я создаю волну 1 Гц на выходе микроконтроллера

У меня проблемы с поиском, с чего начать. Кроме того, что мне нужно собрать все на макете (ATMega328p, led / fan и т. Д.), Я понятия не имею, как запустить код, даже если мне нужно написать его на C (так как я приличен в этом).

Я уже вообразил, каким будет код (в моей голове) более или менее. Я знаю, что у меня будет 3 или 4 переключателя для управления моим ШИМзначение (таким образом управляя светодиодом / вентилятором). Я также знаю, что мне нужно читать / возиться с таймерами.

#include <avr/interrupt.h>
#include <stdio.h>
#include <avr/io.h>
#define LED 1

volatile unsigned char count = 2; // Counter
volatile unsigned char led;       // Verifies if LED is turned ON or OFF

void inic(void) {

    PORTD = 0b00000011;                                     // Defined PD0 / PD3 as outputs. PD0: Blinking LED ; PD3: LED (pwm) [OC2B].
    DDRD  = 0b00000011;


    TCCR0A = (1<<WGM01);                                    // COM0Ax: Normal port operation ; COM0Bx: Normal port operation ; Bits 3&2: Reserved and read as zero ; CTC mode (T = [Prescaler/Clock] * (OCR0 + 1)
    TCCR0B = (1<<CS02)|(1<<CS00);                           // FOC0x: Read as zero ; Bits 5&4: Reserved and read as zero ; Prescaler = 1024 & Clock = 1Mhz
    TIMSK0 = (1<<OCIE0A);                                   // Timer/Counter0 Compare Match A interrupt enabled
    OCR0A  = 243;                                           // 0,245 = [1024/1MHz] * (OCR0 + 1) <=> OCR0 = 243 (0,249 ms)


    TCCR2A = (1<<COM2B1)|(1<<WGM21)|(1<<WGM20);             // COM2Ax: Normal port operation ; COM2Bx: Clear OC2B on Compare Match & Set OC2B at Bottom ; Bits 3&2: Reserved and read as zero ; Fast PWM
    TCCR2B = (1<<CS21)|(1<<CS20);                           // FOC2x: Read as zero ; Bits 5&4; Reserved and read as zero ; Prescaler = 32 & Clock = 1Mhz
    OCR2B  = 0;                                             


    ADMUX  = (1<<REFS0)|(1<<ADLAR)|(1<<MUX2)|(1<<MUX0);     // External capacitor on AREF pin (potentiometer) ; ADLAR adjusted to the left: Bit = 1 ; Bit 4 ; Reserved and read as zero ; PC5 (ADC5) defined as input
    ADCSRA = (1<<ADEN)|(1<<ADIE)|(1<<ADPS1)|(1<<ADPS2);     // ADEN enabled: Bit = 1 ; ADSC set when converting ; ADATE: Disabled auto triggering of the ADC ; ADIF: Set when conversion completes ; Prescaler = 8

    sei();                                                  // global int enable
}

ISR(ADC_vect) {                                         // ADC interruption

   OCR2B = ADCH;                                        // Transfers the value of the potentiometer to the led on PD3
   ADCSRA |= (1<<ADSC);                                 // Starts the conversion
}



ISR(TIMER0_COMPA_vect) {                                // Led blink interruption

   count--;                                             // Counts 250ms
   led = (PORTD & LED);                                 // Blinking LED

   if (count == 0 && led == 0) {                        // Count = 2 by default. 250ms * 2 = 500ms. Half a second on, Half a second off. Comes here if led is turned off
       PORTD |= LED;                                    // LED ON
       count = 2;                                       // Reset counter
   }

   if (count == 0 && led == 1) {                        // Comes here if led is turned on
       PORTD &= ~LED;                                   // LED OFF
       count = 2;                                       // Resets counter
   }
}


void main(void) {
    inic();                                             // Calls the inic function

    ADCSRA |= (1<<ADSC);                                // Starts the ADC conversion

    while(1){                                           // infinite cycle
    }

}

1 Ответ

0 голосов
/ 02 октября 2019

Вы можете проверить таблицу данных ATmega32 на первом шаге. Эта таблица данных содержит несколько примеров кода для периферийных устройств, таких как Timer и GPIO. ATmega328 является более новой версией ATmega32, и поэтому вы можете повторно использовать некоторые примеры кода из ATmega32 для ATmega328.

Вам нужно прочитать главу о GPIO и Timer, и обе главы довольно просты (imho). Разделите ваш проект на части и изучите и объедините каждый из этих фрагментов. Начните с GPIO, переключите светодиод и прочитайте кнопку. Перейдите к таймеру и сгенерируйте ШИМ для управления светодиодом. Теперь объедините кнопки с таймером, и вы успешно завершите свой проект. Существует множество учебных пособий для этого типа периферийных устройств с ATmega32 / ATmega328 (YouTube является хорошим источником для некоторых учебных пособий по AVR).

...