прерывание сбрасывает присвоенные в цикле значения элементов массива?!?!))

naviantropos
Offline
Зарегистрирован: 06.07.2017

На панельке led 8х8 отбражается змейка. Тело змейки-массив из 10 эл-ов (5 точек с координатами Х,У). В цикле координатам её "телец" присваиваются новые значения и змейка бежит. по нажатию клавиши обрабатывается прерывание. Прерывание присваивает глобальной переменной новое значение. Исходя из одного из этих значений выбирается нужный цикл (направление движение змейки). Но вот беда... по нажатию клавиши змейка начинает свой путь из точки 0.0 .. то есть присвоенные массиву новые координаты сбрасываются( 

#include "LedControl.h"
#include "binary.h"
#include <TM74HC595Display.h>
#include <TimerOne.h>
LedControl lc=LedControl(11,13,10,1);
int SCLK = 7;
int RCLK = 6;
int DIO = 5;
TM74HC595Display disp(SCLK, RCLK, DIO);
int Course=0;
void setup() {
  lc.shutdown(0,false);
  // выставляем яркость на среднее значение:
  lc.setIntensity(0,1);
  // очищаем дисплей:
  lc.clearDisplay(0); 
  attachInterrupt(0, course(), RISING);   //повышение напряжения на пин2
  }                                       //провоцирует выполнение course()
int delaytime = 100;
int snake[10];
void snakeY(int y){                      //присваивание координаты У
snake[9]=snake[7];snake[7]=snake[5];
snake[5]=snake[3];snake[3]=snake[1];
snake[1]=y;
}
void snakeX(int x){                      //присваивание координаты Х
snake[8]=snake[6];snake[6]=snake[4];
snake[4]=snake[2];snake[2]=snake[0]; 
snake[0]=x;
}
void ledsnake(){                         //отображение змеи
  int b=1;
for(int a=0; a<9; a+=2){
   lc.setLed(0,snake[a],snake[b],true); 
   b+=2;
  }
delay(delaytime);
b=1;
for(int a=0; a<9; a+=2){
   lc.setLed(0,snake[a],snake[b],false); 
   b+=2;
  }
}
volatile int course(){                   //направление движения по нажатию кнопки
volatile int val;
val=analogRead(0);
if(val>760&&val<795)            //лево
{disp.digit4(2); Course=2;}
if(val>625&&val<645)            //низ     
{disp.digit4(0); Course=0;}
if(val>525&&val<545)            //право
{disp.digit4(3); Course=3;}      
if(val>590&&val<610)            //верх
{disp.digit4(1); Course=1;}
}
void snakemove(){                     //движение змеи
  
if(Course==3){
  for(int y=snake[1];y<9;y++){
  snakeY(y);
  snakeX(snake[0]);
  ledsnake();
  if(Course!=3) continue;
  if(y==7)y=-1;
        }
}
if(Course==2){
  for(int y=snake[1];y>-2;y--){
  snakeY(y);
  snakeX(snake[0]);
  ledsnake();
   if(Course!=2) continue;
  if(y==0) y=8;
        }
}
if(Course==1){
  for(int x=snake[0];x>-2;x--){
  snakeX(x);
  snakeY(snake[1]);
  ledsnake();
   if(Course!=1) continue;
  if(x==0) x=8;
      }
}
if(Course==0){
  for(int x=snake[0];x<9;x++){
  snakeX(x);
  snakeY(snake[1]);
  ledsnake();
   if(Course!=0) continue;
  if(x==7) x=-1;
      }
}
}
void loop() {
  snakemove();
}

 

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

у вас вправо-влево - это y -координата, а вверх-вниз - это х ? оригинально...

Вообще, в таком "слепом" и непрозрачном коде легко налепить ошибок... не пробовали писать как-то попроще? В процедурах snakeX snakeY - что за бредовое переприсваивание координат? Циклы для кого придумали?

В процедуре snakemove - в каждом цикле отработки курса в операторе for вы насильственно меняете индексную переменную. Это нарушает логику, это прямой путь к трудно отловим глюкам.

Вывод - Типичный говнокод... сорри. неудивительно, что не работает

naviantropos
Offline
Зарегистрирован: 06.07.2017

Это, в общем, мой первый код) и он работает (когда переменной course присваивалось рандомное значение, а циклы завершались через определенные промежутки времени - змея двигалась как надо.) поэтому я думаю что дело именнно в прерываниях. Похоже прерыванием сбрасываются присвоенные значения. Объясните по поводу насильственного изменения индексной переменной

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Уберите volatile из строк 44 и 45, а поставьте в строку 10. Проблему это не решит, но курей-то зачем смешить?

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

naviantropos пишет:

Объясните по поводу насильственного изменения индексной переменной

я имел в виду вот этот код

for(int x=snake[0];x<9;x++){
  snakeX(x);
  snakeY(snake[1]);
  ledsnake();
   if(Course!=0) continue;
  if(x==7) x=-1;
      }

Непонятно все-таки, какое максимальное значение должен принимать x -  менее 9, то есть 8 -  как в заголовке цикла, или же 7, как в условии в 6-й строке? Если вы при достижении x==7 сбрасываете его до значения (-1)  - почему тогда в заголовке цикла for до x<9 ? 

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

по поводу volatile - в строке 44 вы обьявляете volatile возвращаетмое значение процедуры course() - не уверен, правильно ли это, но уверен, что это в вашем коде нафик не нужно, так как эта процедура вообще не возвращает значений. Процедуру course() надо описать как void.

Локальную перемененую val в этой же процедуре тоже незачем описывать как volatile

А вот что нужно описывать как волатильную переменную - вы не сделали.  Это переменная Course

naviantropos
Offline
Зарегистрирован: 06.07.2017

мда.. свой же подчерк не разобрал) volatile относится к переменной, а не к функции

naviantropos
Offline
Зарегистрирован: 06.07.2017

b707 пишет:

я имел в виду вот этот код

for(int x=snake[0];x<9;x++){
  snakeX(x);
  snakeY(snake[1]);
  ledsnake();
   if(Course!=0) continue;
  if(x==7) x=-1;
      }

Непонятно все-таки, какое максимальное значение должен принимать x -  менее 9, то есть 8 -  как в заголовке цикла, или же 7, как в условии в 6-й строке? Если вы при достижении x==7 сбрасываете его до значения (-1)  - почему тогда в заголовке цикла for до x<9 ? 

[/quote]

это по моему мнению - допустимая небрежность. просто использовал конструкцию цикла for, а по смыслу это while