выход из прерывания на начало программы

russo
Offline
Зарегистрирован: 20.11.2014

Здравствуйте, необходимо по нажатию кнопки (из обработчика прерывания на INT0) вывалиться на начало программы. При прописывании команды goto для перехода из обработчика прерываня на метку в основной программе loop() компилятор ругается. 

Как правильно выйти из обработчика прерывания на начало программы loop()    ?

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

russo, досрочный выход из функций -return;

russo
Offline
Зарегистрирован: 20.11.2014

Разве из прерывания можно делать return;    

Возврат все равно будет на место прерывания.

Я не могу опрашивать флаг установленого прерывания в основной программе, т.к. много функций delay(); 

 

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

russo, покажите скетч.  Вы что-то перемудрили  по-моему.

russo
Offline
Зарегистрирован: 20.11.2014

Не могу понять, что за ошибки

Это светофор со световыми эфектами с регулятором скорости мигания и переключением программ мигания

int RED_1 = 3;         // 
int YEL_1 = 4;         // 
int GRN_1 = 5;         // 
int RED_2 = 6;         // 
int YEL_2 = 7;         // 
int GRN_2 = 8;         //
int RED_3 = 9;         // 
int YEL_3 = 10;        // 
int GRN_3 = 11;        //
int RED_4 = 12;        // 
int YEL_4 = 13;        // 
int GRN_4 = 14;        //

int button = 2;        //кнопка висит на 2
int regulator = 18;    //регулятор скорости висит на А4

int button_press_flag = 0;  //флаг нажатия кнопки
int button_depress_flag = 1;//флаг отпускания кнопки после нажатия кнопки
int programma = 0;          //номер программы мигания светодиодов
int led;                    //переменная для зажигания нужного светодиода в программе  


//программа обработчика прерывания кнопки-------------------------------------------------
void button_program()    
{
  int temp;                   //переменная для подсчета времени нажатия кнопки
  
  if(!digitalRead(button)) //если кнопку нажали или дребезг
  {
    if(!button_press_flag)
    {
      for (temp=0; temp<30; temp++)  //проверка на успокоение кнопки
      {
         delay(1);	 //задержка в 1 милсек
	 if (digitalRead(button)) return; //если дребезг - вываливаемся
      }
      button_press_flag = 1;      //подымаем флаг нажатия кнопки
      programma = programma + 1;  //меняем программу мигания
      if(programma>4) programma=0;//программ всего 5
      
      for(led=3; led<15; led++)   //гасим все светодиоды
      {
        digitalWrite(led, LOW);
      }

    }
  }
  else  //если кнопку отжали или дребезг
  ( 
    if(button_press_flag)
    {
      for (temp=0; temp<30; temp++)  //проверка на успокоение кнопки
      {
         delay(1);	 //задержка в 1 милсек
	 if (!digitalRead(button)) return; //если дребезг - вываливаемся
      }
      button_press_flag = 0;      //подымаем флаг отжатия кнопки
      
    }
   )
    
}
//------------------------------------------------------------------------------------------------


void setup() //инициализируем порты контроллера
{
  pinMode(button, INPUT);     // 2  вход с кнопки прерыванием
  pinMode(regulator, INPUT);  // A4  вход с регул
  attachInterrupt(0, button_program,  CHANGE); //включаем прерывание по изменению  уровня на 2 порте (при нажатии-отпускании кнопки)
 
  pinMode(RED_1, OUTPUT);      // 
  pinMode(YEL_1, OUTPUT);      //
  pinMode(GRN_1, OUTPUT);      //
  pinMode(RED_2, OUTPUT);      //
  pinMode(YEL_2, OUTPUT);      //
  pinMode(GRN_2, OUTPUT);      //
  pinMode(RED_3, OUTPUT);      //
  pinMode(YEL_3, OUTPUT);      //
  pinMode(GRN_3, OUTPUT);      //
  pinMode(RED_4, OUTPUT);      //
  pinMode(YEL_4, OUTPUT);      //
  pinMode(GRN_4, OUTPUT);      //
  
}

void loop()  //это выполняется постоянно
{
  
  int val;                         //считаное значение с АЦП 

  val = analogRead(regulator);     // считываем значение
  
  if(programma==0)  //программа светофора
{

  digitalWrite(RED_1, HIGH);       // 
  digitalWrite(GRN_2, HIGH);
  digitalWrite(RED_3, HIGH);
  digitalWrite(GRN_4, HIGH);
  delay(val*10);                  // 
  val = analogRead(regulator);    // считываем значение
  
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_2, LOW);       // 
  digitalWrite(GRN_4, LOW);
  delay(val/2); 
  val = analogRead(regulator);    // считываем значение
  
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_2, HIGH);      // 
  digitalWrite(GRN_4, HIGH);
  delay(val/2);
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_2, LOW);   // 
  digitalWrite(GRN_4, LOW);
  delay(val/2);
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_2, HIGH);   // 
  digitalWrite(GRN_4, HIGH);
  delay(val/2);
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_2, LOW);   // 
  digitalWrite(GRN_4, LOW);
  delay(val/2);
  val = analogRead(regulator);     // считываем значение
  digitalWrite(GRN_2, HIGH);   // 
  digitalWrite(GRN_4, HIGH);
  delay(val/2);
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_2, LOW);   // 
  digitalWrite(GRN_4, LOW);
  digitalWrite(RED_1, LOW);
  digitalWrite(RED_3, LOW);
  
  digitalWrite(YEL_1, HIGH);   // 
  digitalWrite(YEL_2, HIGH);
  digitalWrite(YEL_3, HIGH);
  digitalWrite(YEL_4, HIGH);
  delay(val*2); 
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(YEL_1, LOW);   // 
  digitalWrite(YEL_2, LOW);
  digitalWrite(YEL_3, LOW);
  digitalWrite(YEL_4, LOW);
  
  digitalWrite(GRN_1, HIGH);   // 
  digitalWrite(RED_2, HIGH);
  digitalWrite(GRN_3, HIGH);
  digitalWrite(RED_4, HIGH);
  delay(val*10); 
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_1, LOW);   // 
  digitalWrite(GRN_3, LOW);
  
  delay(val/2);
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_1, HIGH);   // 
  digitalWrite(GRN_3, HIGH);
  delay(val/2);
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_1, LOW);   // 
  digitalWrite(GRN_3, LOW);
  delay(val/2);
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_1, HIGH);   // 
  digitalWrite(GRN_3, HIGH);
  delay(val/2);
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_1, LOW);   // 
  digitalWrite(GRN_3, LOW);
  delay(val/2);
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_1, HIGH);   // 
  digitalWrite(GRN_3, HIGH);
  delay(val/2);
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(GRN_1, LOW);   // 
  digitalWrite(GRN_3, LOW);
  digitalWrite(RED_2, LOW);
  digitalWrite(RED_4, LOW);
  
  digitalWrite(YEL_1, HIGH);   // 
  digitalWrite(YEL_2, HIGH);
  digitalWrite(YEL_3, HIGH);
  digitalWrite(YEL_4, HIGH);
  delay(val*2); 
  val = analogRead(regulator);     // считываем значение
  //button_press_flag = 0;   //сброс флага нажатия кнопки
  digitalWrite(YEL_1, LOW);   // 
  digitalWrite(YEL_2, LOW);
  digitalWrite(YEL_3, LOW);
  digitalWrite(YEL_4, LOW);
}
  
  if(programma==1)  //программа - бегущий огонек
  {  
    
    for(led=3; led<15; led++)
    {
      digitalWrite(led, HIGH);
      delay(val);
      digitalWrite(led, LOW);
      val = analogRead(regulator);     // считываем значение
      //button_press_flag = 0;   //сброс флага нажатия кнопки
    }
  
  }
  
  else if(programma==2)  //программа - последовательного включения  и гашения 
  {  
    
    for(led=3; led<15; led++)
    {
      digitalWrite(led, LOW);
      delay(val);
      digitalWrite(led, HIGH);
      val = analogRead(regulator);     // считываем значение
      //button_press_flag = 0;   //сброс флага нажатия кнопки
    }
    for(led=3; led<15; led++)
    {
      digitalWrite(led, HIGH);
      delay(val);
      digitalWrite(led, LOW);
      val = analogRead(regulator);     // считываем значение
      //button_press_flag = 0;   //сброс флага нажатия кнопки
    }
  
  }
  
  else if(programma==3)  //программа - случайное вспыхивание светодиода в разброс
  {  
    led = random(3, 15);
 
    digitalWrite(led, HIGH);
    delay(val);
    digitalWrite(led, LOW);
    
    //button_press_flag = 0;   //сброс флага нажатия кнопки
  
  }
  
  else //if(programma==4)  //программа - тупо горим, типа подсвечник
  {  
    
    for(led=3; led<15; led++)
    {
      digitalWrite(led, HIGH);
    }
    //button_press_flag = 0;   //сброс флага нажатия кнопки
  
  }
  
}


traffic_light.ino: In function 'void button_program()':
traffic_light.ino:50:5: error: expected primary-expression before 'if'
traffic_light.ino:50:5: error: expected ')' before 'if'
traffic_light.ino:267:1: error: expected ';' at end of input
traffic_light.ino:267:1: error: expected '}' at end of input
Ошибка компиляции.

 

 

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

В 49 строке после else не должно  быть круглой скобки.  И в 60й строке убрать её пару

russo
Offline
Зарегистрирован: 20.11.2014

Спасибо, вот лоханулся.

И все таки вопросс по выходу из прерывание на начало программы, вот обработчик прерывания

//программа обработчика прерывания кнопки-------------------------------------------------
void button_program()    
{
  int temp;                   //переменная для подсчета времени нажатия кнопки
  
  if(!digitalRead(button)) //если кнопку нажали или дребезг
  {
    if(!button_press_flag)
    {
      for (temp=0; temp<30; temp++)  //проверка на успокоение кнопки
      {
         delay(1);	 //задержка в 1 милсек
	 if (digitalRead(button)) return; //если дребезг - вываливаемся
      }
      button_press_flag = 1;      //подымаем флаг нажатия кнопки
      programma = programma + 1;  //меняем программу мигания
      if(programma>4) programma=0;//программ всего 5
      
      for(led=3; led<15; led++)   //гасим все светодиоды
      {
        digitalWrite(led, LOW);
      }

    }
  }
  else  //если кнопку отжали или дребезг
  { 
    if(button_press_flag)
    {
      for (temp=0; temp<30; temp++)  //проверка на успокоение кнопки
      {
         delay(1);	 //задержка в 1 милсек
	 if (!digitalRead(button)) return; //если дребезг - вываливаемся
      }
      button_press_flag = 0;      //подымаем флаг отжатия кнопки
      
    }
  }
    
}
//------------------------------------------------------------------------------------------------

При returne из прерывания нужно перепрыгивать на начало программы loop(), у меня вроде бы не так.

Отладку бы в протеусе сделать...

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

russo, у вас много недостатков в скетче. Недостатки вызывают проблемы. Из-за использования delay() вам досталась  проблема,  что выходя из прерывания нужно  закончить очень затяжной цикл loop() прежде чем изменения вступят в силу.  Если бы вы не использовали delay() то и проблемы не было, программа бы изменилась едва вы коснулись кнопки. То, что вы сейчас хотите -это попытка бороться со следствием, а не лучше ли заняться причиной? Вместо delay написать функцию задержки, хотя бы на том-же миллисе. Проблема сразу же отпадёт.

russo
Offline
Зарегистрирован: 20.11.2014

В ассемблере нет таких проблем, поставил goto по метке и радуйся...

В этом "компиляторе" (ардуино не хочу называть компилятором) goto в другую функцию не прокатывает. В общем я огорчен. 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

Если без delay() - никак то можно перед каждым delay() ставить проверку, было ли прерывание и если да тогда "goto".

Это ускорит переход по прерыванию.  А вообще dimax, прав delay() нужно убрать.

kisoft
kisoft аватар
Offline
Зарегистрирован: 13.11.2012

О да, С плохой язык, он не позволяет из обработчика прерываний перейти в любую точку программы. Забавно даже. Используйте другой язык.
А если без сарказма, то любая задача решается без особых проблем, если все делать правильно. Но есть другой вариант, свалить все на язык, вместо того, что бы просто решить задачу.
А если задача не решается, значит решение не правильное.
О чем dimax и написал.

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

russo: Если Вам еще интересен Ваш проэкт, то я его сделал без delay() и проверил на протеусе, можете посмотреть.

Првда без прерывания, На мой взгля оно там не нужно, хотя для общего развития можно поставить.

Критика приветствуется!

bool fl_drebezg = 0;//Флаг - Дребезга
int t1 = 50; //Время для дребезга
bool D_Pause = 0;// Переменная для pause
bool kn_start = 0;
bool fl_start;
int next = 0;
unsigned long currentTime; //Переменная для дребезга
unsigned long currentTime2; //Переменная для pause


int RED_1 = 3;         // 
int YEL_1 = 4;         // 
int GRN_1 = 5;         // 
int RED_2 = 6;         // 
int YEL_2 = 7;         // 
int GRN_2 = 8;         //
int RED_3 = 9;         // 
int YEL_3 = 10;        // 
int GRN_3 = 11;        //
int RED_4 = 12;        // 
int YEL_4 = 13;        // 
int GRN_4 = 14;        //

int programma = 4;          //номер программы мигания светодиодов
int led;       //переменная для зажигания нужного светодиода 
int button = 2;        //кнопка висит на 2
int regulator = 18;    //регулятор скорости висит на А4

void setup() //инициализируем порты контроллера
{
  pinMode(button, INPUT_PULLUP);     // 2  вход с кнопки прерыванием
  pinMode(regulator, INPUT);  // A4  вход с регул
  
  pinMode(RED_1, OUTPUT);      // 
  pinMode(YEL_1, OUTPUT);      //
  pinMode(GRN_1, OUTPUT);      //
  pinMode(RED_2, OUTPUT);      //
  pinMode(YEL_2, OUTPUT);      //
  pinMode(GRN_2, OUTPUT);      //
  pinMode(RED_3, OUTPUT);      //
  pinMode(YEL_3, OUTPUT);      //
  pinMode(GRN_3, OUTPUT);      //
  pinMode(RED_4, OUTPUT);      //
  pinMode(YEL_4, OUTPUT);      //
  pinMode(GRN_4, OUTPUT);      //
  currentTime = millis();
  currentTime2 = millis();
}


///Функция паузы
int pause(int y)
{
	bool x = 0;
	if (millis() - currentTime2 >= y) x = 1, currentTime2 = millis();
	return x;
}

//Функция дребезга
int drebezg(int y)
{
	bool x = 0;
	if (fl_drebezg == 0)currentTime = millis(), fl_drebezg = 1;
	if (millis() - currentTime >= y) x = 1, fl_drebezg = 0;
	return x;
}

void loop()
{
  int val; //считаное значение с АЦП 
  // Здесь "val = 1000" для проверки без регулятора
  val = 1000;//analogRead(regulator);     // считываем значение

  if (digitalRead(button) == 0)
  {
  	if (fl_start == 0) fl_drebezg = 0, fl_start = 1;
    if (kn_start == 0) kn_start = drebezg (t1); // Отправляем в Функцию дребезга
}

if (digitalRead(button) == 1)
{
	if (fl_start == 1) fl_drebezg = 0, fl_start = 0;
    if (kn_start == 1) kn_start = !drebezg (t1); // Отправляем в Функцию дребезга
}

if (kn_start == 1)
{
	D_Pause = pause(300);
    if (D_Pause == 1){
	for(led=3; led<15; led++)   //гасим все светодиоды
     {
      	digitalWrite(led, LOW);
     }
    next = 0;
	led=3;
  ++programma;//меняем программу мигания
  if(programma>4) programma=0;//программ всего 5
}

  }

if(programma==0)  //программа светофора
{
switch (next) 
{
 case 0:
      //выполняется, когда next равно 0
     digitalWrite(RED_1, HIGH);
     digitalWrite(GRN_2, HIGH);
     digitalWrite(RED_3, HIGH);
     digitalWrite(GRN_4, HIGH);
     next=1;
   break;
case 1:
 	D_Pause = pause(val*10);
	if (D_Pause == 1)
	 {
  	  digitalWrite(GRN_2, LOW);       // 
  	  digitalWrite(GRN_4, LOW);
  	  next=2;
	 }
  break;
case 2:
	D_Pause = pause(val/2);
	if (D_Pause == 1)
	{
  	  digitalWrite(GRN_2, HIGH);      // 
  	  digitalWrite(GRN_4, HIGH);
  	  next=3;
	} 
  break;
case 3:
	D_Pause = pause(val/2);
  	if (D_Pause == 1)
  	{
  	  digitalWrite(GRN_2, LOW);       // 
  	  digitalWrite(GRN_4, LOW);
  	  next=4;
	}
  break;
case 4:
	D_Pause = pause(val/2);
	if (D_Pause == 1)
	{
  	  digitalWrite(GRN_2, HIGH);      // 
  	  digitalWrite(GRN_4, HIGH);
  	  next=5;
	}  
  break;
case 5:
  	D_Pause = pause(val/2);
  	if (D_Pause == 1)
  	{
  	  digitalWrite(GRN_2, LOW);       // 
  	  digitalWrite(GRN_4, LOW);
   	  next=6;
	}
  break;
case 6:
	D_Pause = pause(val/2);
	if (D_Pause == 1)
	{
  	  digitalWrite(GRN_2, HIGH);      // 
  	  digitalWrite(GRN_4, HIGH);
   	  next=7;
	}  
  break;
case 7:
	D_Pause = pause(val/2);
	if (D_Pause == 1)
	{
  	  digitalWrite(GRN_2, LOW);   // 
  	  digitalWrite(GRN_4, LOW);
  	  digitalWrite(RED_1, LOW);
  	  digitalWrite(RED_3, LOW);
  
  	  digitalWrite(YEL_1, HIGH);   // 
  	  digitalWrite(YEL_2, HIGH);
  	  digitalWrite(YEL_3, HIGH);
  	  digitalWrite(YEL_4, HIGH);
   	  next=8;
	}
  break;
case 8:
	D_Pause = pause(val/2);
	if (D_Pause == 1)
	{
  	  digitalWrite(YEL_1, LOW);   // 
  	  digitalWrite(YEL_2, LOW);
  	  digitalWrite(YEL_3, LOW);
  	  digitalWrite(YEL_4, LOW);
  
  	  digitalWrite(GRN_1, HIGH);   // 
  	  digitalWrite(RED_2, HIGH);
  	  digitalWrite(GRN_3, HIGH);
  	  digitalWrite(RED_4, HIGH);
  	  next=9;
	}
  break;
case 9:
	D_Pause = pause(val*10);
	if (D_Pause == 1)
	{
  	  digitalWrite(GRN_1, LOW);   // 
  	  digitalWrite(GRN_3, LOW);
  	  next=10;
	}
  break;
case 10:
	D_Pause = pause(val/2);
	if (D_Pause == 1)
	{
  	  digitalWrite(GRN_1, HIGH);   // 
  	  digitalWrite(GRN_3, HIGH);
   	  next=11;
	}
  break;
case 11:
	D_Pause = pause(val/2);
	if (D_Pause == 1)
	{
  	  digitalWrite(GRN_1, LOW);   // 
  	  digitalWrite(GRN_3, LOW);
  	  next=12;
	}
  break;
case 12:
	D_Pause = pause(val/2);
	if (D_Pause == 1)
	{
  	  digitalWrite(GRN_1, HIGH);   // 
  	  digitalWrite(GRN_3, HIGH);
   	  next=13;
	}
  break;
case 13: 
 	D_Pause = pause(val/2);
	if (D_Pause == 1)
	{
  	  digitalWrite(GRN_1, LOW);   // 
  	  digitalWrite(GRN_3, LOW);
   	  next=14;
	}
  break;
case 14: 
	D_Pause = pause(val/2);
	if (D_Pause == 1)
	{
  	  digitalWrite(GRN_1, HIGH);   // 
  	  digitalWrite(GRN_3, HIGH);
 	  next=15;
	}
  break;
case 15: 
 	D_Pause = pause(val/2);
	if (D_Pause == 1)
	{
  	  digitalWrite(GRN_1, LOW);   // 
  	  digitalWrite(GRN_3, LOW);
  	  digitalWrite(RED_2, LOW);
  	  digitalWrite(RED_4, LOW);
  
  	  digitalWrite(YEL_1, HIGH);   // 
  	  digitalWrite(YEL_2, HIGH);
  	  digitalWrite(YEL_3, HIGH);
  	  digitalWrite(YEL_4, HIGH);
  	  next=16;
	}
  break;
case 16: 
	D_Pause = pause(val/2);
	if (D_Pause == 1)
	{
  	  digitalWrite(YEL_1, LOW);   // 
  	  digitalWrite(YEL_2, LOW);
  	  digitalWrite(YEL_3, LOW);
  	  digitalWrite(YEL_4, LOW);      
  	  next=0;
	}
	break;
	
  }
 }

if(programma==1)  //программа - бегущий огонек
  {  
switch (next) 
{
 case 0:
      //выполняется, когда next равно 0
     digitalWrite(led, HIGH);
   D_Pause = pause(val);
   if (D_Pause == 1)
    {
      digitalWrite(led, LOW);
      ++led;
    }
      if (led == 15)led = 3;  
     next=0;
    break;
	}
  }

  if(programma==2)  //последовательноe включения  и гашения 
  {  
switch (next) 
{
 case 0:
      digitalWrite(led, HIGH);
      D_Pause = pause(val);
   if (D_Pause == 1)
    {
      next=1;
    }
   break;
 case 1:
 	digitalWrite(led, LOW);
 	D_Pause = pause(val);
   if (D_Pause == 1)
    {
      next = 0;
      ++led;
     if (led == 15)led = 3; 
    }
    break;
	}
  }

if(programma==3)  //программа - случайное вспыхивание
{
   digitalWrite(led, HIGH);
   D_Pause = pause(val);
   if (D_Pause == 1)
    {
      digitalWrite(led, LOW);
      led = random(3, 15);
	}
}

if(programma==4)  //программа - тупо горим, типа подсвечник
  {  
    for(led=3; led<15; led++)
    {
      digitalWrite(led, HIGH);
    }
  }
}

 

brokly
brokly аватар
Offline
Зарегистрирован: 08.02.2014

russo пишет:

В ассемблере нет таких проблем, поставил goto по метке и радуйся...

В этом "компиляторе" (ардуино не хочу называть компилятором) goto в другую функцию не прокатывает. В общем я огорчен. 

Как у вас все просто, вы еще скажите, что "goto" за вас и указатель стека поправит :)

Datak
Offline
Зарегистрирован: 09.10.2014

russo, конечно, в ассемблере можно всё, но под свою ответственность. :)

C/C++ пытаются хоть как-то защитить нас от глупых ошибок, и упростить программирование.

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

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

vosara, ваш код существенно лучше, (по крайней мере основная проблема решена). Однако до совершенства далеко :) Обычно, когда стоит задача рулить сразу большим количеством портов удобнее создать специальную функцию, которой будут скармливать некую переменную, в которой лежат побитово все данные, необходимые для записи в порты. Применительно к данному случаю -у нас 12 светодиодов, значит заводим двухбайтовую переменную, в которой  состояние 12-ти младших бит будет соответствовать 12 нужным выходам. Я для тренировки решил набросать такую. Светодиоды включены как у автора, на ногах 3..14 относительно земли. Функция ledout() зажжёт светодиоды в точном соответствии с битами переменной, которую передадут в функцию. Разбирать какие там программы переключений у автора уже не интересно, ограничусь для примера одной -бегущий огонёк.

//Скетч бегущий огонёк. 12 светодиодов подключены к выводам 3..14 и общему.
void setup() {
DDRD|=B11111000;
DDRB|=B00111111;
DDRC|=B00000001;
}

void loop() { 
prog1();

}



void ledout(unsigned int x){
x<<=3;//сдвинуть влево на три бита что бы "сесть" на PD3-PD7
PORTD=x&0xf8;//f8-маска что бы не трогать другие биты у порта D
x>>=8;//сдвинуть на 8 бит, что бы избавится от уже переданных в порт бит
PORTB=x&0x3f; //передать на биты PB0-PB5
x>>=6;//сдвинуть на 6 бит, что бы избавится от уже переданных в порт бит
PORTC=x&1;//записать последний бит
}

void prog1() {
 static unsigned long prevmillis=millis();
   if (millis()-prevmillis>=300) {
         static unsigned int n=0;
         n? n>>=1: n=0x800; // "n" не равно нулю? Если да -то сдвигаем на бит вправо. Если нет, то старший бит=1 
         prevmillis=millis();
         ledout(n);
       }
     }

 

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

dimax, Спасибо за кементарий, я понимаю что с побитовыми операциями намного удобней, быстрей и экономней  но для меня это пока проблема. Благодаря Вашему, хорошо прокоментированому коду, буду продвигаться в этом направлении.

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

vosara, c функцией ledout() очень легко добавлять новые эффекты. Их можно генерить чисто математически (как в скетче), а можно и просто рисовать битами, например

n=B000000000000;     
n=B000001100000;     
n=B000010010000;     
n=B000100001000;     
n=B001000000100;     
n=B010000000010;     
n=B100000000001;  

потом эти команды прокрутить назад, будет красивый эффект ) Можно сделать светодиодную палочку, и ей в воздухе слова рисовать, или к велосипеду на колесо приделать что-то подобное, и узоры рисовать).

vosara
vosara аватар
Offline
Зарегистрирован: 08.02.2014

dimax, Да как работает Ваш код я понял, вроде ничего сложного, благодаря коментариям. Вот теперь ищу больше информации. По поводу рисования, я делал свои символы на дисплей но на порт никогда не выводил да и 12 бит вывести на 3 порта (D,B,C) не знал.

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

Добавка к тому-же коду, функция "индикатор уровня звука". Звук подавать на аналоговый вход. analogReference сделать INTERNAL, что-б чувствительность поднять.  Вот записал маленький видеоролик работы, скачать.

void indik() {
int ain=analogRead(A4)/85;//поделить всю шкалу на 12 частей
unsigned int data_out=0;
for (int y=0; y <ain; y++){ data_out|=(1<<y); }
ledout(data_out);  
}

Ещё один бегущий огонёк, бегает  от 1-го до 12-го и обратно от 12-го до 1-го :)

void prog2() { // огонёк бегает от 1-го к 12-му и обратно.
 static unsigned long prevmillis=millis();
   if (millis()-prevmillis>=300) {
         static unsigned int n=0x800;
         static boolean dir=1;
         if (dir) n==1? dir=0 : n>>=1 ; 
         else  n==0x800? dir=1 : n<<=1;   
         prevmillis=millis();
         ledout(n);
       }
     }