Прерывание внутри библиотеки

32bit
Offline
Зарегистрирован: 16.02.2016
Вопрос. Я создаю библиотеку "Biblioteka.h".
В Biblioteka.cpp подключаю
#include <CyberLib.h>

создаю:

void Biblioteka::Timer_Action1()
{
}
В конструкторе
Biblioteka()
{
 StartTimer1(Timer1_action, 1000);
}

При компиляции ошибка, т.к. как я понимаю в StartTimer1 передается не "Timer1_action" а "Biblioteka::Timer1_action".

Вот сама ошибка:
"error: cannot convert 'Biblioteka::Timer1_action' from type 'void (Biblioteka::)()' to type 'void (*)()' "
Вопрос собственно вот в чем: как внутри библиотеки использовать прерывания?
 
С библиотекой TimerOne тоже самое.
MacSim
Offline
Зарегистрирован: 28.11.2012

а в *.h что пишите?

помоему вы половину не написали того что нужно для библиотеки, или просто не выложили. давайте уж все файлы сюда.

MacSim
Offline
Зарегистрирован: 28.11.2012

не объявили, передавать передаете аргументы, а принимать не принимаете.

создайте сначала подфункцию. в подфункцию передавали аргументы, возвращили?

разместите вашу подфункцию после главной функции, в арду еде после лупа, посмотрите что скажет компиль.

MacSim
Offline
Зарегистрирован: 28.11.2012

... и собственно смотрю регистрация свежая... может рано еще библиотеки писать?

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

32bit
Offline
Зарегистрирован: 16.02.2016

Может и рано.. Но так быстрее и удобнее.

Вот собственно фалйлы.

 

StepIndi.h

//          Библиотека для X25 168 стрелочного индикатора
//          Подключение по 4 проводам



#if defined(ARDUINO) && ARDUINO >= 100
  #include "Arduino.h"
#else
  #include "WProgram.h"
#endif



class StepIndi
{
  public:
    StepIndi();     // Конструктор класса
	volatile int positionIndi;						// Текущее положение стрелки
	volatile int setPosition;
	volatile int maxStep;                             // Максимальное количество шагов для индикатора
	volatile int setPause;
    void stepLeft();                         // Один шаг влево
    void stepRight();                        // Один шаг вправо
    void Reset();
	void Timer1_action();
  private:
	int _stepMicro;
	volatile int _pauseMicro;
	void steps(int a);
	void s(char a);
};

extern StepIndi Indi;

 

StepIndi.cpp

//                      X25 168            955 шагов

#include <StepIndi.h>
#include <CyberLib.h>

StepIndi Indi;

StepIndi::StepIndi()


{ 
  positionIndi = 0;       // Положение стрелки(текущее положение  неизвестно)
  setPosition = 0;
  maxStep = 955;           // Максимальное количество шаг для индикатора
  _stepMicro = 1;
  setPause = 1;
  _pauseMicro = 1;
  D8_Out;
  D9_Out;
  D10_Out;
  D11_Out;
  D8_Low;
  D9_Low;
  D10_Low;
  D11_Low;
  StartTimer1(Timer1_action, 1000);
} 

void StepIndi::stepLeft()                  // Шаг влево
{
 s('L');
 if (positionIndi > 0) {positionIndi--;}
}

void StepIndi::stepRight()                 // Шаг вправо
{
  s('R');
  if (positionIndi < maxStep) {positionIndi++;}
}

void StepIndi::steps (int a)
{
  switch (a)
  {
   case 1:
    D8_High;
    D9_Low;           //1
    D10_Low;
    D11_High;
    break;
   case 2:
    D8_Low;           //2
    D9_Low;
    D10_Low;
    D11_High;
    break;
   case 3:
    D8_Low;
    D9_High;          //3
    D10_High;
    D11_High;
    break;
   case 4:
    D8_Low;
    D9_High;
    D10_High;
    D11_Low;          //4
    break;
   case 5:
    D8_High;          //5
    D9_High;
    D10_High;
    D11_Low;
    break;
   case 6:
    D8_High;
    D9_Low;           //6
    D10_Low;
    D11_Low;
    break;
   default:
    D8_Low;
    D9_Low;           //0
    D10_Low;
    D11_Low;
  }
}

void StepIndi::s (char a)
{
  if ( a == 'L')
  {
    _stepMicro--;
    if (_stepMicro < 1)
    {
      _stepMicro = 6;
      steps(_stepMicro);  
    }
    else  {steps(_stepMicro);}
  }
  if (a == 'R')
  {
    _stepMicro++;
    if (_stepMicro > 6)
    {
      _stepMicro = 1;
      steps(_stepMicro);
    }
    else {steps(_stepMicro);}
  }
} 

void StepIndi::Timer1_action()
{
  if (setPause == _pauseMicro)
  {
   if (positionIndi > setPosition) {stepLeft();}
   if (positionIndi < setPosition) {stepRight();}
   _pauseMicro = setPause;
  }
  else {_pauseMicro--;}
}

void StepIndi::Reset()
{
  setPosition = 0;
  positionIndi = maxStep;
} 

 

32bit
Offline
Зарегистрирован: 16.02.2016

Если использование прерывания вывести в стетч, то все работает. А если в библиотеку, то нет.

32bit
Offline
Зарегистрирован: 16.02.2016
void StartTimer1(void (*isr)(), uint32_t set_us);

Это из CyberLib.h

void (*func)();
volatile uint16_t dub_tcnt1;
 
void StartTimer1(void (*isr)(), uint32_t set_us)
{	
//	cli();
	TIMSK1 &= ~(1<<TOIE1);//запретить прерывания по таймеру1
	func = *isr; 	//указатель на функцию
	TCCR1A = 0;		//timer1 off
	TCCR1B = 0; 	//prescaler off (1<<CTC1)-3й бит

	//uint8_t oldSREG = SREG;

	//if(set_us < 6) set_us = 6;	//min
	//if(set_us > 4194304) set_us = 4194303;  //max
	if(set_us > 5 && set_us < 4096) { set_us = 65584 - (set_us << 4); DIV_0;} else
	if(set_us > 4095 && set_us < 32768) { set_us = 65542 - (set_us << 1); DIV_8; } else
	if(set_us > 32767 && set_us < 262144) { set_us = 65536 - (set_us >> 2); DIV_64;} else
	if(set_us > 262143 && set_us < 1048576) { set_us = 65536 - (set_us >> 4); DIV_256; } else
	if(set_us > 1048575 && set_us < 4194304) { set_us = 65536 - (set_us >> 6);  DIV_1024;} else TCCR1B = 1;
	
	
	dub_tcnt1 = set_us;
	TCNT1 = 0;//dub_tcnt1;	// выставляем начальное значение TCNT1 
	//OCR1A = dub_tcnt1;	
	//TCNT1H=0;//обнуляем регистр TCNT1
	//TCNT1L=0;
	TIMSK1 |= (1 << TOIE1); // разрешаем прерывание по переполнению таймера	
	sei();   
}

Это из Cyber.cpp

32bit
Offline
Зарегистрирован: 16.02.2016

MacSim пишет:

... и собственно смотрю регистрация свежая... может рано еще библиотеки писать?

До этого как то в гугле все находил. А сейчас такой проблемы что то не встретил ни у кого

32bit
Offline
Зарегистрирован: 16.02.2016

Полный текст ошибки



C:\Program Files (x86)\Arduino\libraries\StepIndi\StepIndi.cpp: In constructor 'StepIndi::StepIndi()':

C:\Program Files (x86)\Arduino\libraries\StepIndi\StepIndi.cpp:26:34: error: cannot convert 'StepIndi::Timer1_action' from type 'void (StepIndi::)()' to type 'void (*)()'

   StartTimer1(Timer1_action, 1000);

                                  ^

exit status 1
Ошибка компиляции.
32bit
Offline
Зарегистрирован: 16.02.2016

Ну и сам скетч

#include <StepIndi.h>


int inInt;
//StepIndi Indi;

void setup()
{
  Serial.begin(9600);
  Serial.setTimeout(500);
  Indi.Reset();
}

void loop()
{
  if (Serial.available() > 0)
  {
    inInt = Serial.parseInt();
    Indi.setPosition = inInt;
  }
  Serial.print("Set position: ");
  Serial.print(inInt);
  Serial.print("\n");
}

 

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Цитата:
C:\Program Files (x86)\Arduino\libraries\StepIndi\StepIndi.cpp: In constructor 'StepIndi::StepIndi()':

C:\Program Files (x86)\Arduino\libraries\StepIndi\StepIndi.cpp:26:34: error: cannot convert 'StepIndi::Timer1_action' from type 'void (StepIndi::)()' to type 'void (*)()'

   StartTimer1(Timer1_action, 1000);

Попробуй переопределить тип при вызове: StartTimer1((void*)Timer1_action, 1000);

DIYMan
DIYMan аватар
Offline
Зарегистрирован: 23.11.2015

Ключевое слово - static. У вас функция-член класса - не статическая, поэтому указатель на неё - двойной, т.е. складывается из указателя на экземпляр класса, плюс указателя на функцию. Это грубое объяснение, конечно же, но смысл передаёт.

Функция же StartTimer ждёт в качестве параметра указатель на функцию, не возвращающую ничего, и не имеющую параметров, и подсовывать её просто за вот так вот здрасьте функцию-член класса - не выйдет. Чтобы подсунуть - надо функцию-член класса объявить статической, но тогда будьте готовы к тому, что вызываемый контекст для этой функции станет неизвестен - грубо говоря, вы не сможете понять изнутри функции, для какого экземпляра класса была вызвана эта функция. Если это несущественно, то повторюсь - ключевое слово: static.

Добро пожаловать в мир ООП ;)

32bit
Offline
Зарегистрирован: 16.02.2016

Вооот....

Почитав инфу про эти указатели, я понял примерно следующее. Функция StartTimer1 принимает указатель на функцию, а я передаю(вернее смог передать через какое то время) указатель на метод класса(вернее на метод созданого объекта класса StepIndi). А это как оказалось разные типы указателей(указатель на функцию это реальный адрес, а указатель на метод объекта это смещение от какого то адреса)! А чем мне компилятор долго и упорно сообщал(типа не мого преобразовать этот тип). Есть несколько способов передать указатель на метод объекта. Сделать метод статитичным(я так понял что это просто метод класса), но получается что метод используется без объекта и соотвественно все вызываемые внутри метода переменные и функции ни имеют смысла(адресов?). А чем мне компилятор сообщил выдачей порцией в 100500 ошибок. Есть другие методы с использование других функций(переменных), туда сюда присваивать, передавать....Короче я там запутался п...просто. Конкретного способа нету, каждый свое пытается придумать. Я пару попробывал и получил кучу ошибок что внутри Timer_action1 то не видит адресов переменных, то их объявление, то их принаждежность к классу...

 

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

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

Даже если бы Вам удалось как-то обмануть компилятор с типами, работать-то это не может.

Нестатическому методу класса всегда передаётся "скрытый параметр" - this. Какая зараза и с какого перепугу Вам его передаст-то? Так что, как сказал коллега выше, "добро пожаловать в мир ООП".