кофликт servotimer2 и arduino ng atmega8

dethdron
Offline
Зарегистрирован: 10.08.2016

Всем привет делаю радиоуправляемую машинку с использованием модулей на433мгц. Как известно VirtualWire и обычная библиотека servo конфликтуют в связи с этим исользуетсядругая библиотека ServoTimer2. При использовании про мини все компилируется отлично. Но при использовании Atmega 8 вылезают следующие ошибки

C:\Users\1\Documents\Arduino\libraries\ServoTimer2\ServoTimer2.cpp: In function 'void initISR()':
C:\Users\1\Documents\Arduino\libraries\ServoTimer2\ServoTimer2.cpp:124: error: 'TIMSK2' was not declared in this scope
C:\Users\1\Documents\Arduino\libraries\ServoTimer2\ServoTimer2.cpp:125: error: 'TCCR2A' was not declared in this scope
C:\Users\1\Documents\Arduino\libraries\ServoTimer2\ServoTimer2.cpp:126: error: 'TCCR2B' was not declared in this scope
C:\Users\1\Documents\Arduino\libraries\ServoTimer2\ServoTimer2.cpp:128: error: 'TIFR2' was not declared in this scope

Я так понимаю у меги8 таймеры обзываются подругому как подправить библиотеку под мегу8?

Вот библиотека


/* ServoTimer2.cpp*/
extern "C" {
  // AVR LibC Includes
  #include <inttypes.h>
  #include <avr/interrupt.h>
}
#include <Arduino.h>
#include "ServoTimer2.h"
static void initISR();
static void writeChan(uint8_t chan, int pulsewidth);

#define FRAME_SYNC_INDEX   0		 // frame sync delay is the first entry in the channel array
#define FRAME_SYNC_PERIOD  20000	   // total frame duration in microseconds
#define FRAME_SYNC_DELAY   ((FRAME_SYNC_PERIOD - ( NBR_CHANNELS * DEFAULT_PULSE_WIDTH))/ 128) // number of iterations of the ISR to get the desired frame rate
#define DELAY_ADJUST	 8		 // number of microseconds of calculation overhead to be subtracted from pulse timings

static servo_t servos[NBR_CHANNELS+1];    // static array holding servo data for all channels

static volatile uint8_t Channel;   // counter holding the channel being pulsed
static volatile uint8_t ISRCount;  // iteration counter used in the interrupt routines;
uint8_t ChannelCount = 0;	    // counter holding the number of attached channels
static boolean isStarted = false;  // flag to indicate if the ISR has been initialised

ISR (TIMER2_OVF_vect)
{
  ++ISRCount; // increment the overlflow counter
  if (ISRCount ==  servos[Channel].counter ) // are we on the final iteration for this channel
  {
	TCNT2 =  servos[Channel].remainder;   // yes, set count for overflow after remainder ticks
  }
  else if(ISRCount >  servos[Channel].counter)
  {
	// we have finished timing the channel so pulse it low and move on
	if(servos[Channel].Pin.isActive == true)	     // check if activated
	    digitalWrite( servos[Channel].Pin.nbr,LOW); // pulse this channel low if active

	  Channel++;    // increment to the next channel
	ISRCount = 0; // reset the isr iteration counter
	TCNT2 = 0;    // reset the clock counter register
	if( (Channel != FRAME_SYNC_INDEX) && (Channel <= NBR_CHANNELS) ){	     // check if we need to pulse this channel
	    if(servos[Channel].Pin.isActive == true)	   // check if activated
		 digitalWrite( servos[Channel].Pin.nbr,HIGH); // its an active channel so pulse it high
	}
	else if(Channel > NBR_CHANNELS){
	   Channel = 0; // all done so start over
	}
   }
}

ServoTimer2::ServoTimer2()
{
   if( ChannelCount < NBR_CHANNELS)
	this->chanIndex = ++ChannelCount;  // assign a channel number to this instance
   else
	this->chanIndex = 0;  // todo	// too many channels, assigning 0 inhibits this instance from functioning
}

uint8_t ServoTimer2::attach(int pin)
{
	if( isStarted == false)
	 initISR();
	if(this->chanIndex > 0)
	{
	 //debug("attaching chan = ", chanIndex);
	 pinMode( pin, OUTPUT) ;  // set servo pin to output
	 servos[this->chanIndex].Pin.nbr = pin;
	 servos[this->chanIndex].Pin.isActive = true;
	}
	return this->chanIndex ;
}

void ServoTimer2::detach()
{
    servos[this->chanIndex].Pin.isActive = false;
}

void ServoTimer2::write(int pulsewidth)
{
   writeChan(this->chanIndex, pulsewidth); // call the static function to store the data for this servo
}

int ServoTimer2::read()
{
  unsigned int pulsewidth;
   if( this->chanIndex > 0)
	pulsewidth =  servos[this->chanIndex].counter * 128 + ((255 - servos[this->chanIndex].remainder) / 2) + DELAY_ADJUST ;
   else
	 pulsewidth  = 0;
   return pulsewidth;
}

boolean ServoTimer2::attached()
{
    return servos[this->chanIndex].Pin.isActive ;
}

static void writeChan(uint8_t chan, int pulsewidth)
{
   // calculate and store the values for the given channel
   if( (chan > 0) && (chan <= NBR_CHANNELS) )   // ensure channel is valid
   {
	if( pulsewidth < MIN_PULSE_WIDTH )		    // ensure pulse width is valid
	    pulsewidth = MIN_PULSE_WIDTH;
	else if( pulsewidth > MAX_PULSE_WIDTH )
	    pulsewidth = MAX_PULSE_WIDTH;

	  pulsewidth -=DELAY_ADJUST;			 // subtract the time it takes to process the start and end pulses (mostly from digitalWrite)
	servos[chan].counter = pulsewidth / 128;
	servos[chan].remainder = 255 - (2 * (pulsewidth - ( servos[chan].counter * 128)));  // the number of 0.5us ticks for timer overflow
   }
}

static void initISR()
{
	for(uint8_t i=1; i <= NBR_CHANNELS; i++) {  // channels start from 1
	   writeChan(i, DEFAULT_PULSE_WIDTH);  // store default values
	}
	servos[FRAME_SYNC_INDEX].counter = FRAME_SYNC_DELAY;   // store the frame sync period

	Channel = 0;  // clear the channel index
	ISRCount = 0;  // clear the value of the ISR counter;

	/* setup for timer 2 */
	TIMSK2 = 0;  // disable interrupts
	TCCR2A = 0;  // normal counting mode
	TCCR2B = _BV(CS21); // set prescaler of 8
	TCNT2 = 0;     // clear the timer2 count
	TIFR2 = _BV(TOV2);  // clear pending interrupts;
	TIMSK2 =  _BV(TOIE2) ; // enable the overflow interrupt

	isStarted = true;  // flag to indicate this initialisation code has been executed
}  

 

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

Ну, да, у неё регистры по-другому немного организованы. "Как поправить"? Ну, даташит на 8-ку имеется, надо читать и править как там написано. Если не умеете, то лучше поискать готовую библиотеку для 8-ки.

dethdron
Offline
Зарегистрирован: 10.08.2016

ЕвгенийП пишет:

Ну, да, у неё регистры по-другому немного организованы. "Как поправить"? Ну, даташит на 8-ку имеется, надо читать и править как там написано. Если не умеете, то лучше поискать готовую библиотеку для 8-ки.

Смотрел я датащиты на оба контроллера в разделах register description, много часов, не смог сопоставить из за тудностей перевода, готовой библиотеки под atmega8 не нашел в сети. Поэтому и пришел за помощью сюда. Весь день потратил.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

dethdron, попробуйте вставить этот блок в начало файла ServoTimer2.cpp

#if defined(__AVR_ATmega8__)
  #define TCCR2A TCCR2
  #define TCCR2B TCCR2
  #define TIFR2  TIFR
  #define COM2A1 COM21
  #define COM2A0 COM20
  #define OCR2A OCR2
  #define TIMSK2 TIMSK
  #define OCIE2A OCIE2
  #define TIMER2_COMPA_vect TIMER2_COMP_vect
  #define TIMSK1 TIMSK
  #endif

 

dethdron
Offline
Зарегистрирован: 10.08.2016

dimax пишет:

dethdron, попробуйте вставить этот блок в начало файла ServoTimer2.cpp

#if defined(__AVR_ATmega8__)
  #define TCCR2A TCCR2
  #define TCCR2B TCCR2
  #define TIFR2  TIFR
  #define COM2A1 COM21
  #define COM2A0 COM20
  #define OCR2A OCR2
  #define TIMSK2 TIMSK
  #define OCIE2A OCIE2
  #define TIMER2_COMPA_vect TIMER2_COMP_vect
  #define TIMSK1 TIMSK
  #endif

 

Ого, сразу скомпилировалось, Как вы так быстро)))Я поражен, то есть на русский если перевести спомощью данной дерективы define если программа к примеру обнаружила упоминание о TIMSK2 то она заменит ее на TIMSK и это применится только К Atmega8 котрую мы задали в самом начале с помощью if define? А как вы так быстро сопоставили регистры таймеров? я весь день потратил и безуспешно! Не судите строго я просто хочу для себя разобраться!

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

dethdron, да я вспомнил, что однажды уже где-то видел переопределение регистров через дефайн . Забил в гугль правильный вопрос -и вуаля.