прерывания по таймеру в atmega 328p

Тема в разделе "Микроконтроллеры AVR", создана пользователем Мурад, 23 мар 2017.

  1. kipalex

    kipalex Нуб

    А чем моя запись отличается от Вашей? Тем более если использовать _delay_ms то работает. ~ На судьбу таймера не играет.
     
  2. Mitrandir

    Mitrandir Гуру

    Приоритетом операций отличается
     
  3. DetSimen

    DetSimen Guest

    Та не. Ничем. Я не настаиваю.
     
  4. parovoZZ

    parovoZZ Гуру

    В ней есть симулятор. Вот и прогони там свой код. Если по диагонали, то вроде рабочий.
     
  5. kipalex

    kipalex Нуб

    Так я в Протеусе и в железе гоняю. Ровно 6 секунд.
     
  6. parovoZZ

    parovoZZ Гуру

    там дебагер есть? Посмотри регистры, переменные. Я всегда так делаю. И если уж и там затык, то только после этого лезу на форум =)
     
  7. parovoZZ

    parovoZZ Гуру

    Кстати, частота у мк какая?
     
  8. parovoZZ

    parovoZZ Гуру

    Чтобы использовать вот это, прерывание по этому необходимо разрешить.

    Таймер в каком режиме работает? CTC? Если так, то сюда никогда не зайдем:
    Переменная seconds как определена?
     
    Последнее редактирование: 30 авг 2018
  9. kipalex

    kipalex Нуб

    Полный листинг, частота 8MHz
    Код (C++):
    # define F_CPU 8000000UL

    #include <avr/io.h>
    #include <avr/interrupt.h>
    #include <util/delay.h>
    #include <stdio.h>
    #include <string.h>
    #include <math.h>

    #define KEY1 (1<<PORTD2)
    #define KEY2 (1<<PORTD3)
    #define ANYKEY (KEY1 | KEY2)
    #define NOKEY 0

    #define ALARM_OUT_EN (PORTB|=(1<<PORTB2))
    #define ALARM_OUT_STOP (PORTB&=(~1<<PORTB2))

    volatile uint16_t seconds;

    int main(void)
    {

    // Input/Output Ports initialization
    // Port B initialization
    // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=Out Bit2=Out Bit1=Out Bit0=Out
    DDRB=(0<<DDB7) | (0<<DDB6) | (0<<DDB5) | (0<<DDB4) | (1<<DDB3) | (1<<DDB2) | (1<<DDB1) | (1<<DDB0);
    // State: Bit7=T Bit6=T Bit5=T Bit4=T Bit3=0 Bit2=0 Bit1=0 Bit0=0
    PORTB=(0<<PORTB7) | (0<<PORTB6) | (0<<PORTB5) | (0<<PORTB4) | (0<<PORTB3) | (0<<PORTB2) | (0<<PORTB1) | (0<<PORTB0);

    // Port C initialization
    // Function: Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
    DDRC=(0<<DDC6) | (0<<DDC5) | (0<<DDC4) | (0<<DDC3) | (0<<DDC2) | (0<<DDC1) | (0<<DDC0);
    // State: Bit6=T Bit5=T Bit4=T Bit3=T Bit2=T Bit1=T Bit0=T
    PORTC=(0<<PORTC6) | (0<<PORTC5) | (0<<PORTC4) | (0<<PORTC3) | (0<<PORTC2) | (0<<PORTC1) | (0<<PORTC0);

    // Port D initialization
    // Function: Bit7=In Bit6=In Bit5=In Bit4=In Bit3=In Bit2=In Bit1=In Bit0=In
    DDRD=(0<<DDD7) | (0<<DDD6) | (0<<DDD5) | (0<<DDD4) | (0<<DDD3) | (0<<DDD2) | (0<<DDD1) | (0<<DDD0);
    // State: Bit7=P Bit6=P Bit5=P Bit4=P Bit3=P Bit2=P Bit1=T Bit0=T
    PORTD=(1<<PORTD7) | (1<<PORTD6) | (1<<PORTD5) | (1<<PORTD4) | (1<<PORTD3) | (1<<PORTD2) | (0<<PORTD1) | (0<<PORTD0);

    // Set prescale to 256 and start the timer
    TCCR1B |= (1 << WGM12) | (1 << CS12) | (0<<CS11) | (0<<CS10);
    TCCR1A = 0;
    // set compare for 1 second interrupts
    OCR1A = 0x7A11;
    // setup for compare interrupts
    TIMSK1 |= (1<<OCIE1A);
    // start the interrupts
    sei();
     
        unsigned char get_key(void)
        {
            unsigned char key = ~PIND & ANYKEY;
         
            _delay_ms(10);
            if(key == (~PIND & ANYKEY))
            return key;
            else
            return NOKEY;
        }
     
        /* Replace with your application code */
        while (1)
        {
             
            switch(get_key())
            {
                // Processing reaction of the button 1
                case KEY1:
                ALARM_OUT_EN;
                seconds = 20;
                break;
            }
         
            // Processing timer expired
            if (seconds == 0)
            {
                seconds = -1;
                ALARM_OUT_STOP;
            }

        }
    }
    ISR(TIMER1_OVF_vect)
    {
        if (seconds > 0)
        seconds--;
    }
     
     
  10. parovoZZ

    parovoZZ Гуру

    а так можно делать:
     
  11. DetSimen

    DetSimen Guest

    тут всё можно.
     
    Mitrandir и parovoZZ нравится это.
  12. parovoZZ

    parovoZZ Гуру

    ах ах ах
    Ты прав, ты прав)))
    Вот здесь
    key - локальная переменная. А что вернет функция, если сразу по выходу из функции эта локальная переменная будет уничтожена?
    ТС, запускай атмеловский симулятор и дебажь свой код. Много открытий сделаешь))
     
  13. Mitrandir

    Mitrandir Гуру

    В смысле что вернёт? Значение переменной, там же не по ссылке возврат
     
  14. ZAZ-965

    ZAZ-965 Гуру

    Вложенные функции разве поддерживаются? Или это ошибка копирования и вставки на форум?
     
  15. parovoZZ

    parovoZZ Гуру

    ну да, ты прав =)
     
  16. kipalex

    kipalex Нуб

    При нажатии кнопки seconds устанавливается в 20, включается порт.

    Далее в фоне эти секунды тикают вниз
    Код (C++):
    seconds = -1;
    , при достижении нуля декремент прекратится (seconds > 0 не выполняется больше), поэтому в основном цикле это будет отловлено, таймер окончательно остановлен (-1), порт выключится.

    Любое нажатие кнопки снова "сбросит" таймер в 60.
     
  17. parovoZZ

    parovoZZ Гуру

    мне интересно, как в беззнаковую переменную компилятор запишет минус один?
     
  18. b707

    b707 Гуру

    ну как - так и напишет, как может :)
    ТС же пишет, что у него таймер никогда не выключается. Вот и причина.

    ТС - зачем вам эта жуткая бредятина с инициализацией портов? Вы понимаете, что PORTC =0; DDRB = 0; - это то же самое, что у вас там наверчено, только в 20 раз короче?
     
  19. kipalex

    kipalex Нуб

    Хорошо. соглашусь пусть код не идеален. вместо того чтоб тапками кидаться могли просветить подробнее? Вот Вам к примеру простейший код.

    Код (C++):
    volatile int16_t seconds = 0;
    ISR(TIMER1_COMPA_vect)
    {
    seconds++;
    if (seconds == 60)
    {
        seconds = 0;
    }
    PORTB ^=(1<<PORTB2);
    }

     
    Почему игнорируется seconds? Частота 8MHZ настройки таймера
    Код (C++):
    cli(); // disable interrupts
    // reset
    //TCCR1A = 0; // set TCCR1A register to 0
    //TCCR1B = 0; // set TCCR1B register to 0
    TCNT1  = 0; // reset counter value
    // set compare for 1 second interrupts
    OCR1A = 31249;
    // Set prescale to 256 and start the timer
    TCCR1B |= (1 << WGM12) | (1 << CS12);
    // enable timer compare interrupt
    TIMSK1 |= (1<<OCIE1A);
    // start the interrupts
    sei();
    Получается состояние порта меняется каждые 8 секунд.
     
  20. parovoZZ

    parovoZZ Гуру

    Debug что показывает?