Разрешение и запрет прерывание

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

  1. Yerabdi

    Yerabdi Гик

    Всем доброе утро , нужно ли запрещать и разрешать прерывание в теле функции.
    Если у меня все переменные обьявлены как volatile
     
  2. rkit

    rkit Гуру

    Прерывания нужно запрещать тогда. когда они вам не нужны. К переменным это отношения не имеет. Объявлять все переменные как volatile не следует.
     
  3. ostrov

    ostrov Гуру

  4. DetSimen

    DetSimen Гуру

    нах.., нет, зачем? запрещая прерывания в каждой функции, ты обрекаешь себя на то, что millis(), а тем более delay() всеми любимый будут работать неправильно. Как и вывод в сериал, и многое другое.
    Прерывания надо запрещать, когда функция выполняет критические расчеты в реальном времени. Почему-то мне кажеца, это не твой случай.
     
  5. Airbus

    Airbus Оракул

    Можно так глобально а можно и конкретное прерывание забанить локально.Только это не для Ардуино.
     
  6. Yerabdi

    Yerabdi Гик

    я использую ардуино нано, программу пишу на атмел студио.По внешнему прерыванию приходит импульс на ножку PD2, затем ставлю высокое положение на выходе PD6 на 4,5 миллисекунд. Зависимости от значение аналогового входа добавляю время от 1- 5 миллисекунд высокому состоянию PD6 . Вроде все нормально работает, когда идет расчет добавки времени у меня может произойти внешнее прерывание и он должен поставит выход открытым
     
  7. Igor68

    Igor68 Гуру

    Простите! Это у вас не ЧИМ случайно?
     
  8. Yerabdi

    Yerabdi Гик

    да ШИМ МОДУЛЯЦИЯ
     
  9. Igor68

    Igor68 Гуру

    Простите, но для ШИМ наверное удобнее использовать аппаратный ШИМ. А если я Вас правильно понял Вам надо одинаковую длительность импульса, но с разным интервалом... то есть ЧИМ.
    Спасибо.
     
  10. Igor68

    Igor68 Гуру

    Прошу прощения! Я не подумав сказал про PWM... как говориться я "зажрался" на ARMах:
    вот для AT91SAM7S64/128/256(Armel)
    snapshot45.png
    для ADuC7024(Analog Devices):
    snapshot44.png

    Вот и подумал, что аппаратный и для ATmega... а тут всё "косвенно"... хотя может мне и не попалась функциональная схема в DATASHEET.
    Ещё раз простите!
     
    Последнее редактирование: 24 сен 2017
  11. Onkel

    Onkel Гуру

    функции обработки прерывания должны работать по принципу "ударил -убежал". Выставить какой-нибудь флаг - и обратно в main , уже в режиме обычной работы этот флаг отрабатывать. И время в мс нужно поручить таймеру отсчитывать.
     
    parovoZZ нравится это.
  12. Aleksander1997

    Aleksander1997 Нерд

    Здравствуйте, это упрощенный пример, чтобы многие поняли суть вопроса
    Прерывание настроено на таймере 1 с интервалом 1 секунду. Мне нужно, чтобы по нажатию кнопки запускался таймер и начинался отсчет времени именно в момент нажатия а не по ходу программы как в данном случае. Догадываюсь что нужно запретить прерывание пока находимся в теле функции loop() и разрешить в момент нажатия таким образом чтобы не затронуть работу millis() и других завязанных на timer 0. Может есть способ по лучше.

    Код (C++):
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>

    // Set the LCD address to 0x27 for a 16 chars and 2 line display
    LiquidCrystal_I2C lcd(0x27, 16, 2);

    volatile unsigned char second = 0;
    volatile unsigned char minute = 0;
    boolean flag = 0;

    static void init_timer1(void);
    void LCD_update_time(void);

    void setup() {
        cli(); // запрет прерываний глобально
        // initialize Timer1
        TCCR1A = 0;     // set entire TCCR1A register to 0
        TCCR1B = 0;     // same for TCCR1B
       
        pinMode(11, INPUT_PULLUP);
        init_timer1();
        sei(); // enable global interrupts
       
        lcd.begin();
        lcd.backlight();
    }

    void loop() {
        static unsigned long previousMillis = 0;
        if (digitalRead(11) == LOW && (millis() - previousMillis > 100)) {
           previousMillis = millis();
           flag = 1;
        }
        if (flag) LCD_update_time();
    }

    static void init_timer1(void) //set timer1 interrupt at 1Hz
    {
      TCCR1A = 0;// set entire TCCR1A register to 0
      TCCR1B = 0;// same for TCCR1B
      TCNT1  = 0;//initialize counter value to 0
      // set compare match register for 1hz increments
      OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
      // Установить СТС режим и делитель частоты 1024
      TCCR1B |= (1 << WGM12)|(1 << CS12) | (1 << CS10);
      // Разрешаем прерывание по сравнению с OCR1A
      TIMSK1 |= (1 << OCIE1A);
    }
     
    void LCD_update_time()
    {
        lcd.setCursor(1, 0); //выводим значение минут
        lcd.print(minute/10); //количество минут
        lcd.print(minute%10); //количество минут  
        lcd.print(F(":"));         //выводим символ ":"между  минутами и секундами
        lcd.print(second/10); //количество секунд
        lcd.print(second%10); //количество минут
    }

    ISR(TIMER1_COMPA_vect)
    {
        second++;
        if (second == 60) {
            second = 0;
            minute++;
            if (minute == 60) {
                minute = 0;
            }
        }  
    }
     
  13. Aleksander1997

    Aleksander1997 Нерд

    Зря похоже обращался
    Код (C++):
    #include <Wire.h>
    #include <LiquidCrystal_I2C.h>
    #include <avr/io.h>
    #include <avr/interrupt.h>

    // Set the LCD address to 0x27 for a 16 chars and 2 line display
    LiquidCrystal_I2C lcd(0x27, 16, 2);

    volatile unsigned char second = 0;
    volatile unsigned char minute = 0;
    volatile boolean flag = 0;

    static void init_timer1(void);
    void LCD_update_time(void);

    void setup() {
        cli(); // запрет прерываний глобально
        // initialize Timer1
        TCCR1A = 0;     // set entire TCCR1A register to 0
        TCCR1B = 0;     // same for TCCR1B
       
        pinMode(11, INPUT_PULLUP);
        init_timer1();
        sei(); // enable global interrupts
       
        lcd.begin();
        lcd.backlight();
    }

    void loop() {
        static unsigned long previousMillis = 0;
        if (digitalRead(11) == LOW && (millis() - previousMillis > 100)) {
           previousMillis = millis();
           flag = 1;
        }
        if (flag) LCD_update_time();
    }

    static void init_timer1(void) //set timer1 interrupt at 1Hz
    {
      TCCR1A = 0;// set entire TCCR1A register to 0
      TCCR1B = 0;// same for TCCR1B
      TCNT1  = 0;//initialize counter value to 0
      // set compare match register for 1hz increments
      OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
      // Установить СТС режим и делитель частоты 1024
      TCCR1B |= (1 << WGM12)|(1 << CS12) | (1 << CS10);
      // Разрешаем прерывание по сравнению с OCR1A
      TIMSK1 |= (1 << OCIE1A);
    }
     
    void LCD_update_time()
    {
        lcd.setCursor(1, 0); //выводим значение минут
        lcd.print(minute/10); //количество минут
        lcd.print(minute%10); //количество минут  
        lcd.print(F(":"));         //выводим символ ":"между  минутами и секундами
        lcd.print(second/10); //количество секунд
        lcd.print(second%10); //количество минут
    }

    ISR(TIMER1_COMPA_vect)
    {
        if (flag) {
        second++;
        if (second == 60) {
            second = 0;
            minute++;
            if (minute == 60) {
                minute = 0;
            }
        }  
        }
    }
    }
     
  14. DetSimen

    DetSimen Гуру

    Тебе что сделать то надо? Раз в секунду кнопку опрашивать?
     
    parovoZZ нравится это.
  15. parovoZZ

    parovoZZ Гуру

    Комментарии на русском и на ангельском - это так сейчас модно в среде абдуринщиков?
     
  16. parovoZZ

    parovoZZ Гуру

    Почему здесь прерывания запрещаются
    А здесь нет
    Тем более, что TCNT1 16-ти битный регистр.
     
  17. Airbus

    Airbus Оракул

    Все просто код спи позаимствован откуда то а то что сам делал закоментил на русском.
     
  18. parovoZZ

    parovoZZ Гуру

    И зачем функция static? Компилятор её таковой сам сделает при однократном вызове. И почему идёт двойная инициализация регистра TCCR1?
     
  19. AlexU

    AlexU Гуру

    Ни в электронике, ни в программировании...
    С какого перепугу компилятор будет делать функцию static при однократном вызове. Простыми словами, модификатор static говорит компилятору не включать данную декларацию в таблицу глобальных ссылок и они "становятся" не видимыми для линкера. Это касается деклараций объявленных вне тела функции.
     
    SergeiL и Mitrandir нравится это.
  20. DetSimen

    DetSimen Гуру

    Нет. модификатор статик, примененный к функции указывает, что функцию видно только в этом файле и всё.
     
    SergeiL нравится это.