attiny85 выход из сна по кнопке.
- Войдите на сайт для отправки комментариев
Пт, 08/09/2017 - 23:12
Помогите разобраться с кодом. Взял такой пример:
#include <avr/sleep.h> #include <avr/interrupt.h> const int switchPin = 3; const int statusLED = 2; void setup() { pinMode(switchPin, INPUT); digitalWrite(switchPin, HIGH); pinMode(statusLED, OUTPUT); // Flash quick sequence so we know setup has started for (int k = 0; k < 10; k = k + 1) { if (k % 2 == 0) { digitalWrite(statusLED, HIGH); } else { digitalWrite(statusLED, LOW); } delay(250); } // for } // setup void sleep() { GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts PCMSK |= _BV(PCINT3); // Use PB3 as interrupt pin ADCSRA &= ~_BV(ADEN); // ADC off set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT) sei(); // Enable interrupts sleep_cpu(); // sleep cli(); // Disable interrupts PCMSK &= ~_BV(PCINT3); // Turn off PB3 as interrupt pin sleep_disable(); // Clear SE bit ADCSRA |= _BV(ADEN); // ADC on sei(); // Enable interrupts } // sleep ISR(PCINT0_vect) { // This is called when the interrupt occurs, but I don't need to do anything in it } void loop() { sleep(); digitalWrite(statusLED, HIGH); delay(1000); digitalWrite(statusLED, LOW); }
И попробовал встроить в свой код:
#include <avr/io.h> #include <avr/sleep.h> const byte numLed[20][2] = { //какие пины дёргать чтоб загорался определённый светодиод {0,4}, //1 1 {1,4}, //5 2 {2,4}, //9 3 {3,4}, //13 4 {4,1}, //17 5 {0,3}, //2 6 {1,3}, //6 7 {2,3}, //10 8 {3,1}, //14 9 {4,3}, //18 10 {0,2}, //3 11 {1,2}, //7 12 {2,1}, //11 13 {3,2}, //15 14 {4,2}, //19 15 {0,1}, //4 16 {1,0}, //8 17 {2,0}, //12 18 {3,0}, //16 19 {4,0}, //20 20 }; long previousMillis = 0; long previousMillisSP = 0; byte mode = 0; byte i; //для циклов byte j; byte apl=8; //яблоко byte lgth = 1; //длина змейки byte _msnake = 0; //направление движения byte _snake[20] = {12,17,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; //голова и хвост змейки boolean _N0[4][5]={ {0,1,1,1,0}, {1,0,0,0,1}, {1,0,0,0,1}, {0,1,1,1,0}, }; boolean _N1[4][5]={ {0,0,0,0,0}, {1,0,0,1,0}, {1,1,1,1,1}, {1,0,0,0,0}, }; boolean _N2[4][5]={ {1,0,0,1,0}, {1,1,0,0,1}, {1,0,1,0,1}, {1,0,0,1,0}, }; boolean _N3[4][5]={ {0,1,0,0,1}, {1,0,0,0,1}, {1,0,1,0,1}, {0,1,0,1,1}, }; boolean _N4[4][5]={ {0,0,1,1,1}, {0,0,1,0,0}, {0,0,1,0,0}, {1,1,1,1,1}, }; boolean _N5[4][5]={ {1,0,1,1,1}, {1,0,1,0,1}, {1,0,1,0,1}, {0,1,0,0,1}, }; boolean _N6[4][5]={ {0,1,1,1,0}, {1,0,1,0,1}, {1,0,1,0,1}, {0,1,0,0,1}, }; boolean _N7[4][5]={ {0,0,0,0,1}, {0,0,0,0,1}, {1,1,1,0,1}, {0,0,0,1,1}, }; boolean _N8[4][5]={ {0,1,0,1,0}, {1,0,1,0,1}, {1,0,1,0,1}, {0,1,0,1,0}, }; boolean _N9[4][5]={ {0,0,0,1,0}, {1,0,1,0,1}, {1,0,1,0,1}, {0,1,1,1,0}, }; boolean _Bfl[6][7]={ {0,0,0,0,0,0,0}, {0,0,0,1,0,0,0}, {0,0,0,1,0,1,0}, {0,0,0,1,1,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, }; boolean _Bft[6][7]={ {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, {0,0,0,0,0,0,0}, }; byte g = 0; boolean h = 0; byte k = 0; void setup() { delay(1); if(digitalRead(3)==HIGH){ mode=0; } delay(1); if(digitalRead(4)==HIGH){ mode=1; } delay(1); pinMode(0, OUTPUT); pinMode(1, OUTPUT); pinMode(2, OUTPUT); pinMode(3, OUTPUT); pinMode(4, OUTPUT); } void(* resetFunc) (void) = 0; // Reset MC function void sleep(){ for(byte i=0; i<5; i++){ pinMode(i, OUTPUT); digitalWrite(i, LOW); } for(byte i=0; i<5; i++){ pinMode(i, INPUT); } GIMSK |= _BV(PCIE); // Enable Pin Change Interrupts PCMSK |= _BV(PCINT3); // Use PB3 as interrupt pin //PCMSK |= _BV(PCINT4); // Use PB4 as interrupt pin ADCSRA &= ~_BV(ADEN); // ADC off set_sleep_mode(SLEEP_MODE_PWR_DOWN); // replaces above statement sleep_enable(); // Sets the Sleep Enable bit in the MCUCR Register (SE BIT) sei(); // Enable interrupts sleep_cpu(); // sleep cli(); // Disable interrupts PCMSK &= ~_BV(PCINT3); // Turn off PB3 as interrupt pin // PCMSK &= ~_BV(PCINT4); // Turn off PB4 as interrupt pin sleep_disable(); // Clear SE bit ADCSRA |= _BV(ADEN); // ADC on //resetFunc(); sei(); // Enable interrupts /* ADCSRA &= ~(1 << ADEN); // перед сном отключим АЦП ACSR |= (1 << ACD); // компаратор set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_enable(); sleep_cpu(); // спать*/ } //ISR(PCINT3_vect) { // resetFunc(); // // This is called when the interrupt occurs, but I don't need to do anything in it //} void ledon (byte a, byte f){ //зажигает определённый светодиод for(byte i=0; i<5; i++)//очищаем входы pinMode(i, INPUT); pinMode(a, OUTPUT); pinMode(f, OUTPUT); digitalWrite(a, HIGH); digitalWrite(f, LOW); delayMicroseconds(45); for(byte i=0; i<5; i++)//очищаем входы pinMode(i, INPUT); //delayMicroseconds(5); } void onLedOne (byte i){ //зажигает только один выбранный светодиод по его номеру if(i<=20 && i>0){ i--; byte a = numLed[19-i][0]; byte f = numLed[19-i][1]; ledon (a, f); } } void aplRd(){ //генерируем яблоко там где нет хвоста и головы змейки do { i=0; apl=random(1,19); for(j=lgth+1; j>0; j--){ if(_snake[j-1]==apl) i++; } }while(i>0); } void loop() { // for(byte i=0; i<21; i++){ // для отладки // onLedOne (i); // delay(10); // } if(millis() - previousMillisSP > 1000){//проверяем спать или нет sleep(); //sleepMode(); } switch (mode){ case 0: rendom(); break; case 1: snake(); break; default: mode = 0; break; } } void snake(){ if(millis() - previousMillisSP > 30){ //смена неправления движения кнопками if(digitalRead(4)==HIGH){ previousMillisSP = millis(); if(_msnake>0){ _msnake--; }else{_msnake=3;} } if(digitalRead(3)==HIGH){ previousMillisSP = millis(); if(_msnake<3){ _msnake++; }else{_msnake=0;} } } if(millis() - previousMillis > 40) { previousMillis = millis(); if(_snake[0]==apl){ //если яблоко съели, хвост длиньше, и генерируем другое aplRd(); lgth++; } for(i=lgth; i>0; i--) //тащим за собой хвост _snake[i]=_snake[i-1]; switch (_msnake) { //перемещаем змейку case 0: //вверх if(_snake[0]<=5){ _snake[0]+=15; }else{_snake[0]-=5;} break; case 1: //вправо if(_snake[0]%5==0){ _snake[0]-=4; //lgth++; }else{_snake[0]+=1;} break; case 2: //вниз if(_snake[0]>15){ _snake[0]-=15; }else{_snake[0]+=5;} break; case 3: //влево if(_snake[0]%5==1){ _snake[0]+=4; }else{_snake[0]-=1;} break; } for(i=lgth; i>0; i--){ //съеден ли хвост if(_snake[0]==_snake[i]){ _snake[0]=12; _snake[1]=17; for(j=1; j<lgth;j++){ //показываем длину хвоста onLedOne(j); delayMicroseconds(5750); } lgth=1; _msnake=0; apl=random(1,20); //aplRd(); } } } for(i=lgth; i>0; i--){ //рисуем хвост onLedOne(_snake[i]); } onLedOne(_snake[0]); //рисуем голову if(millis()%20!=0){ onLedOne(apl); //рисуем яблоко } } void rendom() { if(digitalRead(3)==HIGH){ if(millis() - previousMillisSP > 50) { previousMillis = millis(); previousMillisSP = millis(); g++; k=0; } } if(digitalRead(4)==HIGH){ //if(millis() - previousMillisSP > 50) resetFunc(); } switch (g){ case 1: if(k==0){ k=(millis())%10+1; } clearBf(_Bft); switch (k){ case 10: copyArBfl(_Bfl,_N0); break; case 1: copyArBfl(_Bfl,_N1); break; case 2: copyArBfl(_Bfl,_N2); break; case 3: copyArBfl(_Bfl,_N3); break; case 4: copyArBfl(_Bfl,_N4); break; case 5: copyArBfl(_Bfl,_N5); break; case 6: copyArBfl(_Bfl,_N6); break; case 7: copyArBfl(_Bfl,_N7); break; case 8: copyArBfl(_Bfl,_N8); break; case 9: copyArBfl(_Bfl,_N9); break; default: onLedOne(random(0,21)); break; } paintM(_Bfl); h=1; break; case 0: if(millis() - previousMillis > 20) { previousMillis = millis(); kletAvt(); } paintM(_Bfl); if(h==1) onLedOne(random(0,21)); break; default: clearBf(_Bft); g=0; k=0; break; } } void clearBf(boolean _arr[6][7]){ for(byte i=0; i<6;i++){ for(byte j =0; j<7; j++) _arr[i][j]=0; } } void copyArB(boolean _arr0[6][7], boolean _arr1[6][7]){ for(byte i=0; i<6;i++){ for(byte j=0; j<7; j++) _arr0[i][j]=_arr1[i][j]; } } void copyArBfl(boolean _arr0[6][7], boolean _arr1[4][5]){ for(byte i=0; i<4;i++){ for(byte j=0; j<5; j++) _arr0[i+1][j+1]=_arr1[i][j]; } } int KAI(int i)//вспомогательня функция клеточного автомата { if(i<0){ i=5; }else if(i>5){ i=0; } return i; } int KAJ(int j)//вспомогательня функция клеточного автомата { if(j<0){ j=6; }else if(j>6){ j=0; } return j; } void kletAvt()//функция клеточного автомата { int _kk=0; for(int i=0; i<6; i++){ for(int j=0; j<7; j++){ _kk=0; for(int k=-1; k<2;k++) _kk += _Bfl[KAI(i-1)][KAJ(j+k)]+_Bfl[KAI(i)][KAJ(j+k)]+_Bfl[KAI(i+1)][KAJ(j+k)]; if(_Bfl[i][j]==1 && _kk>=3 &&_kk<=4 ){ _Bft[i][j]=1; }else if(_Bfl[i][j]==1 && _kk<3 && _kk>4){ _Bft[i][j]=0; }else if(_Bfl[i][j]==0 && _kk==3){ _Bft[i][j]=1; }else{ _Bft[i][j]=0; } }paintM(_Bfl); } copyArB(_Bfl,_Bft); } void paintM(boolean _arr[6][7]){ for(byte i=0; i<5; i++){ for(byte j=0; j<4; j++){ if(_arr[j+1][i+1]==1) onLedOne(j*5+i+1); } } }
Вроде с первого взгляда должно работать, но не работет. и Ещё вопрос, может не работать из-за того, что у меня кнопки притягиваются в высокое состояние HIGH, а не LOW? и как это исправить? Очень не хочется 3ю кнопку на ресет лепить и так места мало.
Вроде с первого взгляда должно работать, но не работет.
1. Никому оно ничего не должно. Зачем Вы ISR выбросили?
2. Что у Вас там в строках 234-237? Вы понимаете. что при таком коде она после первого засыпания начнёт засыпать сразу же, немедленно по пробуждении?
И, кстати, пример-то у Вас работает? А то может Вы ещё кнопку не тот пин цепляете.
http://youtu.be/W5SMJwiCTzU
Видео где видно как оно работает(вначале я пытаюсь включить нажав на кнопку где прерывание, затем просто на ресет).
ISR я выбросил потому как, что я туда не вставлял, в функцию, ничего не меняется. Пример проверял работает. На видео видно, что просыпается и не засыпает, а рисует, но когда доходит до контакта на котором прерывание повешано, оно вновь исполняется. Так вот вопрос как убрать прерывание с кнопки после тго как проснулся МК? Функция cli(); PCMSK &= ~_BV(PCINT3); не выполняется, я пробовал программный рест resetFunc();, но мк не отключает прерывание поле просыпания.
ISR я выбросил потому как, что я туда не вставлял, в функцию, ничего не меняется.
А Вас не смущает, что в примере туда ничего не вставляется, но люди его почему-то не выбрасывают? Вы думаете, они его там случано забыли? Таки нет, он нужен. Пустой, но нужен.
Так вот вопрос как убрать прерывание с кнопки после тго как проснулся МК?
Не обрабатывать прерывние, пока кнопка не будет отпущена.
Спасибо за помошь.
Получилось, когда поменял ISR(PCINT3_vect) на ISR(PCINT0_vect)(что то по невнимательности напутал) и вставил туда
А зачем Вам там reset? Впрочем, Ваше дело.
Без ресета игра продалжается, а не начинается заново. Я допишу немного функций и выложу, что получилось.
Ничего не понимаю, а чем тогда плох ресет сам по себе? Зачем огород городить? Впрочем, как я уже говорил, дело Ваше.
Ресет плох тем, что нужно третью кнопку городить, и выходит некрасиво и нессиметрично. И корпус больше делать нужно для некоторых вариантов.