мигание светодиода с использованием прерывания переполнения таймера 1 в atmega328p

Я пытаюсь мигать светодиодом с помощью ISR в течение 3 секунд, здесь используется atmega328p. Я пытаюсь создать 1-секундную задержку в isr, используя TIMER1 (16 BIT), а затем зациклить ее на 3 секунды. Светодиод подключен к PD7, не знаю почему не моргает, может кто укажет на ошибку. Я использую simulIDE, вот схема, timer_circuit

#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)
unsigned int count = 0;
void timer()
{
  TCCR1A = 0x00; // Normal mode of operation
  TCNT1 = 0xC2F8; // decimal value is 49912
  TCCR1B |= ((1 << CS10) | (1 << CS12));
  TCCR1B &= ~(1 << CS11); //1024 prescaler

  sei(); // Global interrupt
}

int main(void)
{
    SET_BIT(DDRD,PD7);
    timer();
    while(1)
    {
        TIMSK1 |= TOIE1;
        if(count>=3)
        {
            SET_BIT(PORTD,PD7);
            count=0;
        }
    }
    ;
    return 0;
}
ISR(TIMER1_OVF_vect)
{
  count++;
}

person saravanan    schedule 14.03.2021    source источник
comment
Не забудьте очистить прерывание. Обычно это включает либо запись в регистр управления, либо является побочным эффектом чтения/записи определенного регистра данных.   -  person Weather Vane    schedule 14.03.2021


Ответы (1)


Этот код никогда не выключает светодиод ... как только бит установлен, ваш код никогда не очищает его ... попробуйте переключить бит вместо его установки

#define toggle_BIT(PORT,BIT) PORT ^= (1<<BIT) //this will flip the bit
...
if(count>=3)
  {
     toggle_BIT(PORTD,PD7);
     count=0;
     TCNT1 = 0xC2F8; // reset counter
  }

Обновить

  1. используйте модификатор доступа volatile перед переменной count, чтобы сообщить компилятору, что вы измените его из ISR, чтобы убедиться, что переменная count не будет удалена при оптимизации.
  2. когда вы устанавливаете TCCR1B, вы должны установить другие биты на ноль, чтобы работать в обычном режиме
  3. Пересчитайте значение TCNT1 для 8 МГц, которое является внутренней частотой по умолчанию.

полный код

#include <stdint.h>
#include <avr/io.h>
#include <avr/interrupt.h>

#define toggle_BIT(PORT,BIT) PORT ^= (1<<BIT) //this will flip the bit
#define SET_BIT(PORT,BIT) PORT |= (1<<BIT)
#define CLR_BIT(PORT,BIT) PORT &= ~(1<<BIT)

volatile unsigned int count = 0;

void timer()
{
    TCCR1A = 0x00; // Normal mode of operation
    TCNT1 = 64754; // over flow after 1 sec calculated at 8 MHZ
    TCCR1B = ((1 << CS10) | (1 << CS12)); //1024 prescaler
    TIMSK1 |= 1<<TOIE1; // Enable timer1 overflow interrupt
    sei(); // Global interrupt
}

int main(void)
{
    SET_BIT(DDRD,PD7);
    timer();
    while(1)
    {
        
        if(count>=3)
        {
            toggle_BIT(PORTD,PD7);
            count=0;
        }
    }
    
    return 0;
}
ISR(TIMER1_OVF_vect)
{
    count++;
    TCNT1 = 64754; // reset to over flow after 1 sec calculated at 8 MHZ
}
person Ibram Reda    schedule 14.03.2021
comment
Ошибка в том, что светодиод не включается сам по себе, я добавил схему в вопрос, можете ли вы сослаться на нее - person saravanan; 14.03.2021
comment
@saravanan Я обновил ответ ... скажите, существует ли проблема? - person Ibram Reda; 15.03.2021
comment
проблема решена, спасибо. - person saravanan; 15.03.2021