Помогите с программированием

Добрых времен всем. Други, помогите с проблемой - пытаюсь накропать класс для АТТИНИ 2313 кнопки на два нажатия в течение определенного времени (определяется подсчетом прерываний предварительно настроенного счетчика-таймера 0

ISR(TIMER0_COMPA_vect) {
  if (kn_1.counting) kn_1.count_Plus();
 }
  • метод count_Plus() стр. 23-32 ), метод опроса кнопки butt_Read()(стр. 34-56) постоянно вызывается из loop(); После второго нажатия кнопки вызывается внешняя функция target_Funct_, прекращается (вернее должен прекращаться) подсчет прерываний обнуляются(должны обнуляться) переменные counting, sec, sec_time, этого не происходит т.е. строки 51-53 тупо не выполняются (смотрю в протеусе и на зашитой микрухе),target_Funct_ выполняется, хотя в методе count_Plus() все срабатывает при достижении макс. значения счета. Подскажите пож. чего я не понимаю, где ошибка? Заранее благодарю.
class _Butt_ : public noga {
public:
  void (*funct_)();         //функция выключения счетчика
  void (*target_Funct_)();  //выполняемая функция кнопки
  //noga _Noga;
  bool dbg = 0;
  bool sec = 0;
  bool released = false;
  bool counting = 0;
  uint8_t dbg_time = 0;
  uint8_t sec_time = 0;

  void butt_Read();
  void count_Plus();
  // void tst_prnt(bool inp);
  _Butt_(uint8_t pin, void(*_funct), void(*t_Funct))
    : noga(pin),
      funct_(_funct), target_Funct_(t_Funct) {
    pin_Set(true, false);
  }
};

void _Butt_::count_Plus() {
 //target_Funct_();
  if (counting!=0) sec_time ++;
  if (sec_time >= 7 && dbg) dbg = false;
  if (sec_time >= 62 && sec) {
    sec_time = 0;
    counting = false;
    sec = false;
   }
}

void _Butt_::butt_Read() 
{
  if (!dbg && sec && !released) {
    if (pin_read()) released = true;
  }
  if (!pin_read()) {
    if (!dbg && !sec) {
      dbg = true;
      sec = true;
      counting = true;
      OCR0A = 254;
      TIMSK = 0b00000001;
       }
    else if (sec && !dbg && released) {
       TIMSK &=~1;
       funct_();
      target_Funct_();
      sec=0;
      released = false;
      counting = 0;
    }
  }
}

Нормального, целого компилируемого кода нет, поэтому и ответов нет. Разве предположения строить.

В 48 строке, вместо TIMSK &=~1; попробовать cli();, а в 45 sei()
И, памяти, после компиляции, сколько свободной остаётся?

1 лайк

Меня тоже удивило, вроде ТС тут не первый день. Я вот всегда запускаю глючный код и смотрю, мне так гораздо удобнее. А без запуска можно только самые простые вещи заметить.

1 лайк

Вот сам скейч(с), сделанный исключительно проверить класс

_Butt_ kn_1(14, timer_, target_1);
_Butt_ kn_2(15, timer_, target_2);
noga tst_pin(2);
noga tst_out(3);
noga ts_dbg(4);
noga _Sec(5);
noga prs(6);
noga _counting(9);
bool ir_flag = false;
bool flg_BT = false;
bool sleep_m = false;
bool counting = false;
bool dbg = false;
bool _sec = false;

uint8_t cntr = 0;

void timer_() {
if(!kn_1.counting && !kn_2.counting )  TIMSK = 0x0;  //выключаем маску прерывания таймера TIMER0_COMPA
           
  kn_1.sec = 0;
  kn_1.released = false;
  kn_1.counting = 0;
}



ISR(TIMER0_COMPA_vect) {
  if (kn_1.counting) kn_1.count_Plus();
  if (kn_2.counting) kn_2.count_Plus();
}

void target_1() {
  tst_out.pin_Write(!tst_out.pin_read());
}
void target_2() {
  tst_pin.pin_Write(!tst_pin.pin_read());
}


void setup() {
  kn_1.pull_Up();
  kn_2.pull_Up();
  tst_pin.pin_Set(false);
  _counting.pin_Set(false);
  ts_dbg.pin_Set(false);
  tst_out.pin_Set(false);
  _Sec.pin_Set(false);
 
  //установка счетчика____________
  TCCR0B = 0b00000101;
  TCCR0A = 0b00000010;
  OCR0A = 15;
 }

void loop() {
  static bool press;
  prs.pin_Write(press);
  _counting.pin_Write(counting);
  ts_dbg.pin_Write(dbg);
  _Sec.pin_Write(_sec);
  kn_1.butt_Read();
  kn_2.butt_Read();

}

сам класс

#pragma once
#include <Arduino.h>
#include "define_s2313.h"
void timer_();    //ппрототип функции
void target_1();  //ппрототипы целевых функций для кнопок
void target_2();
class noga {
private:
  uint8_t mask = 0;
public:
  uint8_t _noga_;
  uint8_t getMask(uint8_t);
  bool pin_read();
  bool pin_Write(bool dta);
  void pin_Set(bool r_w, bool p_up);
  void pull_Up();
  noga(uint8_t noga_)
    : _noga_(noga_) {
    mask = g_mask(noga_);
    // Serial.print("pin=");Serial.print(noga_);Serial.print(", mask=");Serial.println(mask);
  }
};


bool noga::pin_Write(bool dta) {
  (dta) ? _V_U_(g_PORT(_noga_)) |= (1 << mask) : _V_U_(g_PORT(_noga_)) &= ~(1 << mask);
}
bool noga::pin_read() {
  return _V_U_(g_PIN(_noga_)) & (1 << mask);
}
void noga::pin_Set(bool r_w, bool p_up = 0)  //r_w==true на чтение
{
  (!r_w) ? *(volatile uint16_t*)(g_DDR(_noga_)) |= (1 << mask) : *(volatile uint16_t*)(g_DDR(_noga_)) &= ~(1 << mask);
  if (p_up && r_w) *(volatile uint16_t*)(g_PORT(_noga_)) |= (1 << mask);
}

void noga::pull_Up() {
  if (!(_V_U_(g_DDR(_noga_)) & (1 << mask))) _V_U_(g_PORT(_noga_)) |= (1 << mask);
}
// класс кнопки----------------------->>>>>
class _Butt_ : public noga {
public:
  void (*funct_)();         //функция выключения счетчика
  void (*target_Funct_)();  //выполняемая функция кнопки
  //noga _Noga;
  bool dbg = 0;
  bool sec = 0;
  bool released = false;
  bool counting = 0;
  uint8_t dbg_time = 0;
  uint8_t sec_time = 0;
  void stp();
  void butt_Read();
  void count_Plus();
  // void tst_prnt(bool inp);
  _Butt_(uint8_t pin, void(*_funct), void(*t_Funct))
    : noga(pin),
      funct_(_funct), target_Funct_(t_Funct) {
    pin_Set(true, false);
  }
};

void _Butt_::stp() {
  sec = 0;
  released = false;
  counting = 0;
}

void _Butt_::count_Plus() {
 //target_Funct_();
  if (counting!=0) sec_time ++;
  if (sec_time >= 7 && dbg) dbg = false;
  if (sec_time >= 62 && sec) {
    sec_time = 0;
    counting = false;
    sec = false;
    //timer_();
   //TIMSK &=~1;
  //  funct_();
  }
}
// void _Butt_::count_Plus() {
//   if (counting) sec_time++;
//   if ((sec_time > 7) && dbg) {
//   dbg = false;
//   }
//   if (sec_time > 62) {
//     sec = false;
//     sec_time = 0;
//     //released = false;
//     funct_();  //функция выключения счетчика
//   }
// }
void _Butt_::butt_Read() 
{
//static bool press;

  if (!dbg && sec && !released) {
    if (pin_read()) released = true;
  }
  if (!pin_read()) {
    if (!dbg && !sec) {
      dbg = true;
      sec = true;
      counting = true;
     // funct_();
      OCR0A = 254;
      TIMSK = 0b00000001;
      
    }
    else if (sec && !dbg && released) {
      cli();
         //
            TIMSK &=~1;
      // _sec =!_sec ;
      stp();
      funct_();
      target_Funct_();
      sec=0;
      released = false;
      counting = 0;
      sei();
      return;
    }
  }
}

define_s2313.h:

#define g_DDR(x) (x==1||x==4||x==5)?&DDRA:(x>=12 && x<=19)?&DDRB:(x==2||x==3||x==6||x==7||x==8||x==9||x==11)?&DDRD:0

#define g_PORT(x) (x==1||x==4||x==5)?&PORTA:(x>=12 && x<=19)?&PORTB:(x==2||x==3||x==6||x==7||x==8||x==9||x==11)?&PORTD:0

#define g_PIN(x) (x==1||x==4||x==5)?&PINA:(x>=12 && x<=19)?&PINB:(x==2||x==3||x==6||x==7||x==8||x==9||x==11)?&PIND:0

#define g_mask(y) (y==2||y==5||y==12)?0:(y==4||y==3||y==13)?1:(y==1||y==14||y==6)?2:(y==7||y==15)?3:(y==8||y==16)?4:(y==9||y==17)?5:(y==11||y==18)?6:(y==19)?7:0
#define _V_U_(x) *(volatile uint8_t*)(x)

Извините, много мусора, как всегда :weary:

Угу, типа того, что в прерывании пытаются менять значение переменной, которая не объявлена как volatile.

1 лайк

Ну что, помог volatile? А то чегой-то у меня код не компилируется

Ни разу не помог, сижу втыкаю ничего не пойму в трех соснах такая фигня

Ну, нельзя же так. Я скопировал скетч, чтобы попытаться Вам помочь, и обнаружил, что он не компилируется! Как Вы его проверяли?

В строке №56 скетча класса неправильно описаны параметры. Надо писать вот так:

_Butt_(*uint8_t* pin, void(*_funct)(void), void(*t_Funct)(void))

Далее, в строках 25-27 того же файла у Вас функция объявлена как bool, но ничего не возвращает. Вы забыли return? Или функция должна быть void?

После этих исправлений код скомпилировался. Внесите их у себя, проверьте на месте ли проблема и попробуйте её как-то более внятно описать. Для начала нарисуйте схему что куда подключено, чтобы я мог это воспроизвести. А потом опишите что я должен сделать, чтобы увидеть проблему и в чём она (проблема) выражается.

У меня тоже не компилировался, но вот получилось от имени администратора )))) (Недавно тема была). Правда с предупреждениями. Аддон ATTinyCore…
Что-то новое, раньше вроде такого не было, может обновление…

Ну, я просто в микрочип-студии компилировал. После тех исправлений, что я описал предупреждения исчезли. Всё компилируется безо всяких бубнов.

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

Блин, вот почему сразу это всё не выкладывать? Ему вообще нужно решить проблему или так, потрындеть зашёл? Вот говорит, что исправил volatile - не помогло. А показать как исправил? Или он так уверен, что сделал это правильно?

Спасибо всем на сегодня все, завтра займусь

Butt(uint8_t pin, void(*_funct)(void), void(*t_Funct)(void))

за это отдельное спасибо

Нет не уверен, все до завтра, еще раз спасибо

всегда так…всему посёлку невеста нравится, а жениху нет )))

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

void _Butt_::butt_Read() 
{

    if (!dbg && !sec && !released ) {
    if (pin_read()){ on = false;dbg = false;}   
  }
  
  if (!dbg && sec && !released ) {
    if (pin_read()) released = true;   
  }
  
  if (!pin_read()) {
    if (!dbg && !sec && !on) {
      dbg = true;
      on = true;
      sec = true;
      counting = true;
     // funct_();
      OCR0A = 254;
      TIMSK = 0b00000001;      
    }
    else if (sec && !dbg && released && on) {    
       TIMSK &=~1;    
      stp();
      funct_();
      target_Funct_();
      printByte(counting);
      return;
    }
  }
}

И здесь убрать лишнее

void _Butt_::count_Plus() {
 //target_Funct_();
  if (counting!=0) sec_time ++;
  if (sec_time >= 7 && dbg) dbg = false;
  if (sec_time >= 62 && sec) {
    sec_time = 0; 
  }
}

Объявить

 bool on = false;

Спасибо всем кто откликнулся! Таки с логикой перемудрил, переписал сейчас все работает. Всем спасибо еще раз за помощь
мусорный скейч(с) с новой логикой кому интересно

Спойлер
#pragma once
#include <Arduino.h>
//#include "define_s.h"
//#include "define_s2560.h"
#include "define_s2313.h"
void timer_();    //ппрототип функции
void target_1();  //ппрототипы целевых функций для кнопок
void target_2();
class noga {
private:
  uint8_t mask = 0;
public:
  uint8_t _noga_;
  uint8_t getMask(uint8_t);
  bool pin_read();
  bool pin_Write(bool dta);
  void pin_Set(bool r_w, bool p_up);
  void pull_Up();
  noga(uint8_t noga_)
    : _noga_(noga_) {
    mask = g_mask(noga_);
  }
};


bool noga::pin_Write(bool dta) {
  (dta) ? _V_U_(g_PORT(_noga_)) |= (1 << mask) : _V_U_(g_PORT(_noga_)) &= ~(1 << mask);
}
bool noga::pin_read() {
  return _V_U_(g_PIN(_noga_)) & (1 << mask);
}
void noga::pin_Set(bool r_w, bool p_up = 0)  //r_w==true на чтение
{
  (!r_w) ? *(volatile uint16_t*)(g_DDR(_noga_)) |= (1 << mask) : *(volatile uint16_t*)(g_DDR(_noga_)) &= ~(1 << mask);
  if (p_up && r_w) *(volatile uint16_t*)(g_PORT(_noga_)) |= (1 << mask);
}

void noga::pull_Up() {
  if (!(_V_U_(g_DDR(_noga_)) & (1 << mask))) _V_U_(g_PORT(_noga_)) |= (1 << mask);
}
// класс кнопки----------------------->>>>>
class _Butt_ : public noga {
public:
  void (*funct_)();         //функция выключения счетчика
  void (*target_Funct_)();  //выполняемая функция кнопки
  //noga _Noga;
  volatile bool dbg = 0;
  volatile bool sec = 0;
  volatile bool released = false;
  volatile bool counting = false;
  uint8_t dbg_time = 0;
  bool pr1=0;
  bool pr2=0;
  bool key = 0;
  volatile byte sec_time = 0;
  bool tst_press=0;
  uint8_t prs_cnt=0;

  void stp();
  void butt_Read();
  void count_Plus();
  // void tst_prnt(bool inp);
  _Butt_(uint8_t pin, void (*_funct)(void), void (*t_Funct)(void))
    : noga(pin),
      funct_(_funct), target_Funct_(t_Funct) {
    pin_Set(true, false);
  }
};

void _Butt_::stp() {
  sec = 0;
  released = false;
  counting = 0;
}

void _Butt_::count_Plus() {
 if(counting || pr2) sec_time++;
  if (sec_time >= 2 && dbg) dbg = false;
  if (sec_time >= 31) {
    sec_time = 0;
    counting = false;
    sec = false;
    pr1=false;
    pr2=false;
    released=false;
  }
}

void _Butt_::butt_Read() {
if(!dbg && pr1){if(pin_read() && !released)released=true; }
if(!pin_read()){
if(!pr1){
  dbg=true;
  pr1=true;
  counting=true;
  return;
}
if(pr1 && !dbg)
{
  if(!pr2 && released){
    pr2=true;
     counting=false;
     target_Funct_();
    // sec_time=0;
  }
}
}

}

Уж очень сложная запись, куча флагов, легко запутаться. Как по мне, проще создать массив всех возможных состояний кнопок , и привязывать его к текущей позиции ИМХО

Но, как говорится , “на вкус и цвет…”))

“…он играет как умеет”, а умеет не очень хорошо, только сейчас поонимаю как не хватает именно системных знаний, поэтому позволю себе дать совет учитесь всегда, и желательно на чужих ошибках😀

1 лайк