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? Впрочем, Ваше дело.
Без ресета игра продалжается, а не начинается заново. Я допишу немного функций и выложу, что получилось.
Ничего не понимаю, а чем тогда плох ресет сам по себе? Зачем огород городить? Впрочем, как я уже говорил, дело Ваше.
Ресет плох тем, что нужно третью кнопку городить, и выходит некрасиво и нессиметрично. И корпус больше делать нужно для некоторых вариантов.