Запуск таймера1 по внешнему прерыванию int0

romc9
Offline
Зарегистрирован: 01.12.2019

Доброго дня ! Никак не запущу код. Помогите. Как только подаю сигнал на int0 кнопка Пуск-Стоп перестаёт работать, на дисплее моргание, светодиод на плате (горящий в режиме РАБОТА) горит постоянно. Задача сделать синхронизацию по внешнему прерыванию. 1. При смене уровня на входе int0 должен запускаться таймер1 на 1мс. Работает по совпадению. 2. Если при считающем таймере1 не появится сигнал смены уровня на входе int0, таймер досчитывает до 1 мс, обнуляется, останавливается. Затем цикл повторяется. 3. Если при считающем таймере1 появится сигнал смены уровня на входе int0, то таймер обнуляется, останавливается и выставляется флаг FlagSynhro = true. Считаем, что нашли момент синхронизации.

#include <LiquidCrystal.h>

const int ENABLEWORK = 4; //Вход разрешения работы Pin D4
const int Zar = 12; //Выход на ключ заряда
const int Razr = 5; //Выход на ключ разряда
const int Led = 13; //Выход на светодиод

int Cicl = 0; // указатель цикла работы обнулён
int currentENABLEWORK = HIGH;
boolean   FlagWork = false, FlagSynhro = false;
volatile boolean Flagint0 = false, StartTimer = false; 
volatile int nom = 1;  // пустой код по умолчанию

LiquidCrystal lcd(6, 7, 8, 9, 10, 11); //выводы подключены

void setup ()
{
  cli(); // отключить глобальные прерывания
  lcd.begin(16, 2); // 1602 дисплей
  lcd.print("MG2:");
  lcd.setCursor(12, 1);
  lcd.print("STOP");
  lcd.setCursor(0, 1);
  lcd.print("Sync:__"); // на дисплей синхронизация __
  

  pinMode (ENABLEWORK, INPUT_PULLUP);  //работает как вход с поддяжкой к плюсу
  pinMode (Zar, OUTPUT);        //работает как выход на ключ заряда
  pinMode (Razr, OUTPUT);        //работает как выход на ключ разряда
  pinMode (Led, OUTPUT);        //работает как светодиод индикации работы
  pinMode (2, INPUT);           //Pin2 вход прерывания int0
  attachInterrupt (0, ZC, CHANGE); //прерывание по zc CHANGE 

  sei(); // включить глобальные прерывания
  
  // инициализация Timer2 для отсчётов примерно 1 с
  //TCCR2A = 0; // установить регистры в 0
  //TCCR2B = 0;
  //TCCR2A |= (1 << WGM21); //сброс при совпадении (WGM22=0)
  //OCR2A = 254; // установка регистра совпадения
  //TIMSK2 |= (1 << TOIE2);  // разрешить прерывание при переполнении
  //TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); //установить делитель частоты на 1024=64мкс

  // инициализация Timer1 для отсчётов интервала 1ms
  GTCCR |= (1 << PSRSYNC); //Prescaler reset обнулить счётчик
  TCCR1A = 0; // установить регистры в 0
  TCCR1B = 0;
  OCR1B = 249; // установить время счёта таймера1 =1мс
    
}

void ZC()
{
  Flagint0 = true; // прерывание int0 произошло 
  if (FlagSynhro == false) // ищем синхронизацию переход к коду СИНХРОНИЗАЦИЯ
  {
    nom = 2;
  }
 
}

ISR (Timer1_COMPB_vect) // функция обработки прерывания по совпадению
{
  TCCR1B = 0;         // остановить таймер1
  TCNT1 = 0;          // обнулить значение счёта
  StartTimer = false;    // продолжить поиск флаг разрешить запуск таймера
      
  lcd.setCursor(8, 1);
  lcd.print("X");
  
}


void loop()
{

    currentENABLEWORK = digitalRead (ENABLEWORK); //считать вход разрешения работы
    
          
    if (currentENABLEWORK == 0 && digitalRead(Led) == 0) //Работа разрешена, светодиод - не горит
    {
      digitalWrite(Led, HIGH); //включить диод
      FlagWork = true;             //флаг разрешения работы вкл
      lcd.setCursor(12, 1);
      lcd.print("WORK");
      nom = 2;
      //sei(); // включить глобальные прерывания
    }
    
    if (currentENABLEWORK == 1 && digitalRead(Led) == 1) //Работа запрещена, светодиод - горит
    {
      //cli(); // отключить глобальные прерывания
      digitalWrite(Led, LOW); //иначе - выключить
      FlagWork = false;             //флаг разрешения работы откл
      lcd.setCursor(12, 1);
      lcd.print("STOP");
      lcd.setCursor(0, 1);
      lcd.print("Sync:__"); // на дисплей синхронизация __
      nom = 1;
    }
   
 
    

  if (currentENABLEWORK == LOW) // Работа разрешена
  {
   
    switch (nom)
    {
      case 1: //---------------------------------------------------------------- 1
        // ничего не делаем если стоим
        
      break;  
        
      case 2:  //---------------------------------------------------------------- 1

        //код Синхронизация запуска
               
        if (Flagint0 == true && StartTimer == false) // прерывание произошло но таймер ещё не запущен
        {
        //GTCCR |= (1 << PSRSYNC); //Prescaler reset обнулить счётчик
        //TCCR1B = 0;         // остановить таймер1
        TIMSK1 |= (1 << OCIE1B);  // разрешить прерывание при совпадении
        TCCR1B |= (1 << WGM12) | (1 << CS11)| (1 << CS10); //включить таймер делитель частоты на 64=4мкс
        Flagint0 = false; // обнулить флаг прерывания
        StartTimer = true; // таймер запущен  
        }

        
        if (StartTimer == true && Flagint0 == true) // таймер считает и прерывание произошло - цикл 4
        {

          TCCR1B = 0;         // остановить таймер1
          Flagint0 = false;       // сбросить флаг прерывания
          Cicl = 2;           // установить цикл работы начальный
          //nom = 3;         // разрешить код РАБОТА
          nom = 1;          // пока при отладке код не запускаем
          FlagSynhro = true;    // синхронизация ок
          lcd.setCursor(0, 1);
          lcd.print("Sync:Ok"); // на дисплей синхронизация ок
          
        }
           
      break;

      case 3:  //---------------------------------------------------------------- 1

        //код Работа
        {
        if (Flagint0 == true)
        {
        
            if (Cicl=1) // цикл РАБОТА
            {
              digitalWrite(Zar, LOW);
              digitalWrite(Razr, HIGH);
            }
            if (Cicl=2) // цикл ЗАРЯД
            {
              digitalWrite(Zar, HIGH);
              digitalWrite(Razr, LOW);
            }
            if (Cicl=3) // цикл МТ
            {
              digitalWrite(Zar, LOW);
              digitalWrite(Razr, LOW);
            }
            if (Cicl=4) // цикл ПАУЗА
            {
              digitalWrite(Zar, LOW);
              digitalWrite(Razr, LOW);
              Cicl = 0;
            }

            Cicl = Cicl + 1;
            Flagint0 = false;
        }
          
        }
      break;
  }


 
  }
  
}

 

b707
Offline
Зарегистрирован: 26.05.2017

romc9 пишет:

При смене уровня на входе int0 должен запускаться таймер1 на 1мс.

не вижу, чтобы вы запускали таймер в обработчике прерывания int0

Если вы пытаетесь это делать в Лупе, с кучей других операций да к тому же с выводом на дисплей - о какой обработке интервалов менее 1мс мы говорим? Это бред полный.

Я бы посоветовал для начала выкинуть работу с LCD. Как настроите прерывания - вернете обратно. Ну и, конечно, таймер должен запускаться непосредственно в прерывании. иначе это бессмысленно.

romc9
Offline
Зарегистрирован: 01.12.2019

b707 пишет:

romc9 пишет:

При смене уровня на входе int0 должен запускаться таймер1 на 1мс.

не вижу, чтобы вы запускали таймер в обработчике прерывания int0

Если вы пытаетесь это делать в Лупе, с кучей других операций да к тому же с выводом на дисплей - о какой обработке интервалов менее 1мс мы говорим? Это бред полный.

Я бы посоветовал для начала выкинуть работу с LCD. Как настроите прерывания - вернете обратно. Ну и, конечно, таймер должен запускаться непосредственно в прерывании. иначе это бессмысленно.

 

Хорошо. Попробую выкинуть всё лишнее.

romc9
Offline
Зарегистрирован: 01.12.2019

А вот ещё наверно глупый вопрос.

Сделав digitalWrite на цифровой вывод, например к уровню 1, он этот уровень на выводе не остаётся, как у светодиода на 13 ноге.

Я хочу на 12 ноге оставить уровень 1, но он только на микросекунды становится 1и снова возвращается в 0.

И как оставить в 1 ?

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

Вызывать библиотечные функции из прерывания - не очень хорошая идея. Надо точно знать как и что библиотека делает иначе можно легко повесить всю систему. 

 

ЗЫ Посмотрел Liquid Crystal - его можно из прерывания вызывать.  

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

romc9 пишет:

А вот ещё наверно глупый вопрос.

Сделав digitalWrite на цифровой вывод, например к уровню 1, он этот уровень на выводе не остаётся, как у светодиода на 13 ноге.

Я хочу на 12 ноге оставить уровень 1, но он только на микросекунды становится 1и снова возвращается в 0.

И как оставить в 1 ?

После digitalWrite состояние пина не меняется, пока не будет следующий digitalWrite.

У вас он строках 153-172 сбрасывается из-за ошибки в if-aх

romc9
Offline
Зарегистрирован: 01.12.2019

Какая ошибка в ifах?

До нового прерывания int0 и флага ifы не активны. В текущем цикле только один if отработает.

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Прочитайте, чем отличается операция присваивания от операции сравнения.

romc9
Offline
Зарегистрирован: 01.12.2019

Я переписал код вот так. Вообще не использую библиотечную команду digitalWrite.

Абсолютно всё также.

 if (Flagint0 == true)
        {
        
            if (Cicl=1) // цикл РАБОТА
            {
              PORTB &= (~(1<<4)); //Zar, LOW
              PORTD |= (1<<5);    //Razr, HIGH
            }
            if (Cicl=2) // цикл ЗАРЯД
            {
              PORTB |= (1<<4);    //Zar, HIGH
              PORTD &= (~(1<<5)); //Razr, LOW
            }
            if (Cicl=3) // цикл МТ
            {
              PORTB &= (~(1<<4)); //Zar, LOW
              PORTD &= (~(1<<5)); //Razr, LOW
            }
            if (Cicl=4) // цикл ПАУЗА
            {
              PORTB &= (~(1<<4)); //Zar, LOW
              PORTD &= (~(1<<5)); //Razr, LOW
              Cicl = 0;
            }

            Cicl = Cicl + 1;
            Flagint0 = false;
            
        }

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Абсолютна та же ошибка в условиях if()

romc9
Offline
Зарегистрирован: 01.12.2019

sadman41 пишет:

Прочитайте, чем отличается операция присваивания от операции сравнения.

 

Да, вы правы. Исправил

Почему-то не поставил двойное равно в ifах

Теперь заработало в этой части кода )

if (Flagint0 == true)
        {
        
            if (Cicl == 1) // цикл РАБОТА
            {
              PORTB &= (~(1<<4)); //Zar, LOW
              PORTD |= (1<<5);    //Razr, HIGH
            }
            if (Cicl == 2) // цикл ЗАРЯД
            {
              PORTB |= (1<<4);    //Zar, HIGH
              PORTD &= (~(1<<5)); //Razr, LOW
            }
            if (Cicl == 3) // цикл МТ
            {
              PORTB &= (~(1<<4)); //Zar, LOW
              PORTD &= (~(1<<5)); //Razr, LOW
            }
            if (Cicl == 4) // цикл ПАУЗА
            {
              PORTB &= (~(1<<4)); //Zar, LOW
              PORTD &= (~(1<<5)); //Razr, LOW
              Cicl = 0;
            }

            Cicl = Cicl + 1;
            Flagint0 = false;
            
        }

 

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

sadman41 пишет:

Абсолютна та же ошибка в условиях if()

Из-за которой все if выполняются подряд не взирая на Cicl

romc9
Offline
Зарегистрирован: 01.12.2019

Теперь останется разобрать синхронизацию...

romc9
Offline
Зарегистрирован: 01.12.2019

И всё же, почему нельзя запустить таймер по флагу, а не в самом обработчик прерывания int0.

Пишут, что код в обработчике должен быть совсем небольшим.

А вся программа небольшая в лупе почти ничего не делается.

asam
asam аватар
Offline
Зарегистрирован: 12.12.2018

romc9 пишет:

И всё же, почему нельзя запустить таймер по флагу, а не в самом обработчик прерывания int0.

Ну почему нельзя, можно. Просто тереяется гарантия что он запустится сразу. Мало ли чего там в лупе в этот момент происходит.

Цитата:
Пишут, что код в обработчике должен быть совсем небольшим.

Скорее он должен очень быстро выполняться, размер особого значения не имеет.

 

 

romc9
Offline
Зарегистрирован: 01.12.2019

Да

Хорошо. Завтра продолжу настройку кода синхронизации. Благодарю за помощь !

romc9
Offline
Зарегистрирован: 01.12.2019

Убрал вывод на дисплей.

Результат тот же. При обработке кода синхронизации (кейс 2) слетает код. Дисплей мигает. Кнопка СТОП не работает.

#include <LiquidCrystal.h>

const int ENABLEWORK = 4; //Вход разрешения работы Pin D4
const int Zar = 12; //Выход на ключ заряда
const int Razr = 5; //Выход на ключ разряда
const int Led = 13; //Выход на светодиод

//int Cicl = 0; // указатель цикла работы обнулён
int Cicl = 1; // указатель цикла работы 1
int currentENABLEWORK = HIGH;
boolean   FlagWork = false, FlagSynhro = false;
volatile boolean Flagint0 = false, StartTimer = false; 
volatile int nom = 1;  // пустой код по умолчанию

LiquidCrystal lcd(6, 7, 8, 9, 10, 11); //выводы подключены

void setup ()
{
  cli(); // отключить глобальные прерывания
  lcd.begin(16, 2); // 1602 дисплей
  lcd.print("MG2:");
  lcd.setCursor(12, 1);
  lcd.print("STOP");
  lcd.setCursor(0, 1);
  lcd.print("Sync:__"); // на дисплей синхронизация __
  

  pinMode (ENABLEWORK, INPUT_PULLUP);  //работает как вход с поддяжкой к плюсу
  pinMode (Zar, OUTPUT);        //работает как выход на ключ заряда
  pinMode (Razr, OUTPUT);        //работает как выход на ключ разряда
  pinMode (Led, OUTPUT);        //работает как светодиод индикации работы
  pinMode (2, INPUT);           //Pin2 вход прерывания int0
  attachInterrupt (0, ZC, CHANGE); //прерывание по zc CHANGE 

  sei(); // включить глобальные прерывания
  
  // инициализация Timer2 для отсчётов примерно 1 с
  //TCCR2A = 0; // установить регистры в 0
  //TCCR2B = 0;
  //TCCR2A |= (1 << WGM21); //сброс при совпадении (WGM22=0)
  //OCR2A = 254; // установка регистра совпадения
  //TIMSK2 |= (1 << TOIE2);  // разрешить прерывание при переполнении
  //TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); //установить делитель частоты на 1024=64мкс

  // инициализация Timer1 для отсчётов интервала 1ms
  GTCCR |= (1 << PSRSYNC); //Prescaler reset обнулить счётчик
  TCCR1A = 0; // установить регистры в 0
  TCCR1B = 0;
  //TIMSK1 |= (1 << OCIE1B);  // разрешить прерывание при совпадении
  OCR1B = 249; // установить время счёта таймера1 =1мс
    
}

void ZC()
{
  Flagint0 = true; // прерывание int0 произошло 
  if (FlagSynhro == false) // ищем синхронизацию переход к коду СИНХРОНИЗАЦИЯ
  {
    nom = 2;
  }
 
}

ISR (Timer1_COMPB_vect) // функция обработки прерывания по совпадению
{
  TCCR1B = 0;         // остановить таймер1
  TCNT1 = 0;          // обнулить значение счёта
  StartTimer = false;    // продолжить поиск флаг разрешить запуск таймера
    
}


void loop()
{

    currentENABLEWORK = digitalRead (ENABLEWORK); //считать вход разрешения работы
    
          
    if (currentENABLEWORK == 0 && digitalRead(Led) == 0) //Работа разрешена, светодиод - не горит
    {
      digitalWrite(Led, HIGH); //включить диод
      FlagWork = true;             //флаг разрешения работы вкл
      lcd.setCursor(12, 1);
      lcd.print("WORK");
      nom = 2;
      //sei(); // включить глобальные прерывания
    }
    
    if (currentENABLEWORK == 1 && digitalRead(Led) == 1) //Работа запрещена, светодиод - горит
    {
      //cli(); // отключить глобальные прерывания
      
      FlagWork = false;             //флаг разрешения работы откл
      Flagint0 = false;       // сбросить флаг прерывания
      FlagSynhro = false;    // ещё нет синхронизации
      PORTB &= (~(1<<4)); //Zar, LOW //остановить управление клчючами
      PORTD &= (~(1<<5)); //Razr, LOW
      digitalWrite(Led, LOW); //иначе - выключить
      lcd.setCursor(12, 1);
      lcd.print("STOP");
      lcd.setCursor(0, 1);
      lcd.print("Sync:__"); // на дисплей синхронизация __
      nom = 1;
    }
   
 
    

  if (currentENABLEWORK == LOW) // Работа разрешена
  {
   
    switch (nom)
    {
      case 1: //---------------------------------------------------------------- 1
        // ничего не делаем если стоим
        
      break;  
        
      case 2:  //---------------------------------------------------------------- 1

        //код Синхронизация запуска
               
        if (Flagint0 == true && StartTimer == false) // прерывание произошло но таймер ещё не запущен
        {
        //GTCCR |= (1 << PSRSYNC); //Prescaler reset обнулить счётчик
        //TCCR1B = 0;         // остановить таймер1
        TIMSK1 |= (1 << OCIE1B);  // разрешить прерывание при совпадении
        TCCR1B |= (1 << WGM12) | (1 << CS11)| (1 << CS10); //включить таймер делитель частоты на 64=4мкс
        StartTimer = true; // таймер запущен
        Flagint0 = false; // обнулить флаг прерывания  
        }

        
        if (StartTimer == true && Flagint0 == true) // таймер считает и прерывание произошло - цикл 4
        {

          TCCR1B = 0;         // остановить таймер1
          Flagint0 = false;       // сбросить флаг прерывания
          Cicl = 2;           // установить цикл работы начальный
          nom = 1;         // разрешить код РАБОТА
          FlagSynhro = true;    // синхронизация ок
          //lcd.setCursor(5, 1);
          //lcd.print("Ok");      // на дисплей синхронизация ок
          
        }
           
      break;

      case 3:  //---------------------------------------------------------------- 1

        //код Работа
        {
        if (Flagint0 == true)
        {
        
            if (Cicl == 1) // цикл РАБОТА
            {
              PORTB &= (~(1<<4)); //Zar, LOW
              PORTD |= (1<<5);    //Razr, HIGH
            }
            if (Cicl == 2) // цикл ЗАРЯД
            {
              PORTB |= (1<<4);    //Zar, HIGH
              PORTD &= (~(1<<5)); //Razr, LOW
            }
            if (Cicl == 3) // цикл МТ
            {
              PORTB &= (~(1<<4)); //Zar, LOW
              PORTD &= (~(1<<5)); //Razr, LOW
            }
            if (Cicl == 4) // цикл ПАУЗА
            {
              PORTB &= (~(1<<4)); //Zar, LOW
              PORTD &= (~(1<<5)); //Razr, LOW
              Cicl = 0;
            }

            Cicl = Cicl + 1;
            Flagint0 = false;
            
        }
          
        }
      break;
  }


 
  }
  
}

 

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

romc9, По описанию похоже на счёт времени импульса. Если он меньше 1мс, то выполнить некие команды, если больше -то ничего не делать. Если так, то необязательно останавливать и запускать таймер и использовать внешнее прерывание.  Можно на постоянно работающем таймере делать захват счётчика через вход ICP. В прерывании по захвату поднять флаг таймаута (если таковой произойдёт)  через прерывание сравнения COMPA/B.  Немного сложнее в программировании, но итоговое кол-во строк будет меньше. Советую почитать статейку на изи http://we.easyelectronics.ru/AVR/taymery-i-zaderzhki-sbornik-receptov.html тут много полезных советов по таймерам.

romc9
Offline
Зарегистрирован: 01.12.2019

Нашёл косяк

Написал ISR (Timer1_COMPB_vect) вместо TIMER1

Ну кто бы мог подумать...

romc9
Offline
Зарегистрирован: 01.12.2019

dimax пишет:

romc9, По описанию похоже на счёт времени импульса. Если он меньше 1мс, то выполнить некие команды, если больше -то ничего не делать. Если так, то необязательно останавливать и запускать таймер и использовать внешнее прерывание.  Можно на постоянно работающем таймере делать захват счётчика через вход ICP. В прерывании по захвату поднять флаг таймаута (если таковой произойдёт)  через прерывание сравнения COMPA/B.  Немного сложнее в программировании, но итоговое кол-во строк будет меньше. Советую почитать статейку на изи http://we.easyelectronics.ru/AVR/taymery-i-zaderzhki-sbornik-receptov.html тут много полезных советов по таймерам.

 

Важно именно по int0 запускать - это узел синхронизации.

А за статейку - спасибо. Учту на будущее

romc9
Offline
Зарегистрирован: 01.12.2019

Решил разгрузить проц  и опрос кнопки разрешения работы делать каждые 3 секунды. Для чего использую Таймер2. По совпадению, таймер выставляет флаг - в лупе проверяется состояние кнопки.

Но вот не работает выдержка интервала таймером. Кнопка срабатывает сразу, а не через 3 секунды.

В чём может быть причина ?

#include <LiquidCrystal.h>

const int ENABLEWORK = 4; //Вход разрешения работы Pin D4
const int Zar = 12; //Выход на ключ заряда
const int Razr = 5; //Выход на ключ разряда
const int Led = 13; //Выход на светодиод

//int Cicl = 0; // указатель цикла работы обнулён
int Cicl = 1; // указатель цикла работы 1
volatile int currentENABLEWORK = HIGH;
boolean   FlagWork = false, FlagSynhro = false;
volatile boolean Flagint0 = false, StartTimer = false, FlagEN = false; 
volatile int nom = 1;  // пустой код по умолчанию

LiquidCrystal lcd(6, 7, 8, 9, 10, 11); //выводы подключены

void setup ()
{
  cli(); // отключить глобальные прерывания
  
  lcd.begin(16, 2); // 1602 дисплей
  lcd.print("MG2:");
  lcd.setCursor(12, 1);
  lcd.print("STOP");
  lcd.setCursor(0, 1);
  lcd.print("Sync:__"); // на дисплей синхронизация __
  
  pinMode (ENABLEWORK, INPUT_PULLUP);  //работает как вход с поддяжкой к плюсу
  pinMode (Zar, OUTPUT);        //работает как выход на ключ заряда
  pinMode (Razr, OUTPUT);        //работает как выход на ключ разряда
  pinMode (Led, OUTPUT);        //работает как светодиод индикации работы
  pinMode (2, INPUT);           //Pin2 вход прерывания int0
  attachInterrupt (0, ZC, CHANGE); //прерывание по zc CHANGE 
 
  // инициализация Timer2 для отсчётов интервала
  TCCR2A = 0; // установить регистры в 0
  TCCR2B = 0; // установить регистры в 0
  TCNT2 = 0; //обнулить значение счёта
  TIMSK2 |= (1 << OCIE2A);  // разрешить прерывание при совпадении
  OCR2A = 46874; // установка регистра совпадения для 3c
  TCCR2A |= (1 << WGM21); //режим СТС
  TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); //запустить CTC делитель частоты на 1024=64мкс
  
  // инициализация Timer1 для отсчётов интервала 1ms
  //GTCCR |= (1 << PSRSYNC); //Prescaler reset обнулить счётчик
  TCCR1A = 0; // установить регистры в 0
  TCCR1B = 0;
  TCNT1 = 0;   // обнулить значение счёта
  TIMSK1 |= (1 << OCIE1B);  // разрешить прерывание при совпадении
  OCR1B = 249; // установить время счёта таймера1 =1мс
  
  
  // Установить аналоговый A2 как цифровой выход
  //DDRC |= (1<<2);    // PC2-A2 выход на светодиод
  
  sei(); // включить глобальные прерывания
}

void ZC()
{
  Flagint0 = true; // прерывание int0 произошло 
  if (FlagSynhro == false) // ищем синхронизацию переход к коду СИНХРОНИЗАЦИЯ
  {
    nom = 2;
  }
 
}

ISR (TIMER1_COMPB_vect) // функция обработки прерывания по совпадению
{
  TCCR1B = 0;         // остановить таймер1
  TCNT1 = 0;          // обнулить значение счёта
  StartTimer = false;    // продолжить поиск флаг разрешить запуск таймера
    
}

ISR (TIMER2_COMPA_vect) // функция опрос состояния каждые 1 сек
{  
    TCCR2B = 0;     // остановить таймер2
    FlagEN = true;     //выставить флаг разрешения опроса кнопки
}

  
void loop()
{

    //currentENABLEWORK = digitalRead (ENABLEWORK); //считать вход разрешения работы
    

    if (FlagEN == true) //Опросить кнопку разрешения работы
    {
      
      currentENABLEWORK = digitalRead (ENABLEWORK); //считать вход разрешения работы
      TCNT2 = 0; //обнулить счётный регистр
      FlagEN = false;
      TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20); //запустить CTC делитель частоты на 1024=64мкс
      //TCCR2B |= (1 << WGM22) | (1 << CS22) | (1 << CS21) | (1 << CS20); //запустить CTC делитель частоты на 1024=64мкс (1 << WGM22) |
            
    }
          
    if (currentENABLEWORK == 0 && digitalRead(Led) == 0) //Работа разрешена, светодиод - не горит
    {
      digitalWrite(Led, HIGH); //включить диод
      FlagWork = true;             //флаг разрешения работы вкл
      lcd.setCursor(12, 1);
      lcd.print("WORK");
      nom = 2;
      //sei(); // включить глобальные прерывания
    }
    
    if (currentENABLEWORK == 1 && digitalRead(Led) == 1) //Работа запрещена, светодиод - горит
    {
      //cli(); // отключить глобальные прерывания
      digitalWrite(Led, LOW); //иначе - выключить
      TCCR1B = 0;         // остановить таймер1
      TCNT1 = 0;          // обнулить значение счёта
      StartTimer = false;    // продолжить поиск флаг разрешить запуск таймера
      FlagWork = false;      //флаг разрешения работы откл
      Flagint0 = false;      // сбросить флаг прерывания
      FlagSynhro = false;    // ещё нет синхронизации
      
      PORTB &= (~(1<<4));    //Zar, LOW //остановить управление ключами
      PORTD &= (~(1<<5));    //Razr, LOW
      //PORTC &= (~(1<<2)); // отключить светодиод синхронизация ок
      
      lcd.setCursor(12, 1);
      lcd.print("STOP");
      lcd.setCursor(0, 1);
      lcd.print("Sync:__"); // на дисплей синхронизация __
      nom = 1;
    }
   
 
    

  if (currentENABLEWORK == LOW) // Работа разрешена
  {
   
    switch (nom)
    {
      case 1: //---------------------------------------------------------------- 1
        // ничего не делаем если стоим
        
      break;  
        
      case 2:  //---------------------------------------------------------------- 1

        //код Синхронизация запуска
               
        if (Flagint0 == true && StartTimer == false) // прерывание произошло но таймер ещё не запущен
        {
        //GTCCR |= (1 << PSRSYNC); //Prescaler reset обнулить счётчик
        //TCCR1B = 0;         // остановить таймер1
        //OCR1B = 249; // установить время счёта таймера1 =1мс
        TCCR1B |= (1 << WGM12) | (1 << CS11)| (1 << CS10); //включить таймер делитель частоты на 64=4мкс
        StartTimer = true; // таймер запущен
        Flagint0 = false; // обнулить флаг прерывания  
        }

        
        if (StartTimer == true && Flagint0 == true) // таймер считает и прерывание произошло - цикл 4
        {

          TCCR1B = 0;         // остановить таймер1
          TCNT1 = 0;          // обнулить значение счёта
          Flagint0 = false;       // сбросить флаг прерывания
          FlagSynhro = true;    // синхронизация ок
          Cicl = 2;           // установить цикл работы начальный
          nom = 3;         // разрешить код РАБОТА
          //PORTC |= (1<<2);    // включить светодиод синхронизация ок
          //lcd.setCursor(5, 1);
          //lcd.print("Ok");      // на дисплей синхронизация ок
          
        }
           
      break;

      case 3:  //---------------------------------------------------------------- 1

        //код Работа
        {
        if (Flagint0 == true)
        {
        
            if (Cicl == 1) // цикл РАБОТА
            {
              PORTB &= (~(1<<4)); //Zar, LOW
              PORTD |= (1<<5);    //Razr, HIGH
            }
            if (Cicl == 2) // цикл ЗАРЯД
            {
              PORTB |= (1<<4);    //Zar, HIGH
              PORTD &= (~(1<<5)); //Razr, LOW
            }
            if (Cicl == 3) // цикл МТ
            {
              PORTB &= (~(1<<4)); //Zar, LOW
              PORTD &= (~(1<<5)); //Razr, LOW
            }
            if (Cicl == 4) // цикл ПАУЗА
            {
              PORTB &= (~(1<<4)); //Zar, LOW
              PORTD &= (~(1<<5)); //Razr, LOW
              Cicl = 0;
            }

            Cicl = Cicl + 1;
            Flagint0 = false;
            
        }
          
        }
      break;
  }


 
  }
  
}
romc9
Offline
Зарегистрирован: 01.12.2019

максимальное число для Таймера2 = 255.

Поэтому задержка много меньше...

romc9
Offline
Зарегистрирован: 01.12.2019

Благодарю всех, принимавших участие в обсуждении и дававших советы.

Код успешно запущен.