PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : zwei timerdefinitionen - wie?



inka
27.12.2014, 13:10
hallo allerseits,

ich habe ein paar meiner routinen in die lib standard.c/h ausgelagert:


#ifndef STANDARD_H_
#define STANDARD_H_

/************** standard *************************/

void I2C_transmissionError(uint8_t errorState);

void I2C_requestedDataReady(uint8_t dataRequestID);

void writeDoubleLCD(double number, uint8_t width, uint8_t prec);

void writeDouble(double number, uint8_t width, uint8_t prec);

void accuspannung(void);

void acculadung(void);

void accuzustand(void);

void watchDogRequest(void);

void task_LCDHeartbeat(void);

void fahr_bis_schwarz (void);

/************** IR-bake **************************/

void readAllRegisters(void);

void print_Register_30(void);

void read_Register_30(void);

void bake_suche(void);

/******************* gyro & nordsuche ************/

void test_rdir(void);

void korrekrur_richtung(void);

void sensorwerte_holen(void);

void nordsuche (void);

void nordsuche_links (void);

void calculateDir(char *dir, uint16_t heading);

void calculateDetailDir(char *dir, uint16_t heading);


/************ ultraschall **** HC-SR-04 ***********************/

void trig(void);

void messung_SR_04 (void);


#endif /*STANDARD_H_*/



in der standard.c sind bei der trig() auch die zugehörigen variablen und die timer-definition:


/********************* ULTRASCHALL & HC-SR-04 ******************************/

uint16_t distanz = 0;
volatile uint16_t zeit = 0;
volatile uint16_t timestamp_last = 0;


ISR(TIMER1_CAPT_vect)
{
//Wenn steigende Flanke
if(TCCR1B & (1<<ICES1))
{
//Flankenerkennung auf fallend
TCCR1B ^= (1<<ICES1);
//aktuelen timer-wert speichern
timestamp_last = ICR1;
}
//fallende Flanke
else
{
//Flankenerkennung auf steigend
TCCR1B ^= (1<<ICES1);
//Laufzeit = aktueller timerwert - vorheriger timerwert
zeit = ICR1 - timestamp_last;
}

}


in einem meiner testprogramme (es sind vier programm-teile die jeweils mit den 4 buttons der multiIO aus einem menü gestartet werden können). Eines davon ist die frequenzmessung von Dirk. Die timerdefinition steht hier im programm selbst:


/**
* TIMER1 Overflow ISR
*
* In this ISR the ICR1 overflows are counted.
*
*/
ISR (TIMER1_OVF_vect)
{
++ovfcnt; // Count the overflows
}

/**
* TIMER1 Capture ISR
*
* In this ISR the cycles from a rising edge to the falling (or the next
* rising) edge are calculated.
*
*/
ISR (TIMER1_CAPT_vect)
{
static icrcounter_t icrcnt_start;
icrcounter_t icrcnt_end;
if (edgeflag == RISING_EDGE) // Rising edge!
{
icrcnt_start.i8l = ICR1L; // Low byte first
icrcnt_start.i8m = ICR1H; // High byte is buffered
ovfcnt = 0; // Reset overflow counter
#ifndef FREQUENCY
TCCR1B &= ~(1<<ICES1); // Next trigger: Falling edge
#endif
edgeflag = FALLING_EDGE;
}
else // Falling (or next rising) edge!
{
icrcnt_start.i16h = 0; // Reset upper 16 bits (start value)
icrcnt_end.i8l = ICR1L; // Low byte first
icrcnt_end.i8m = ICR1H; // High byte is buffered
// If low ICR1H and waiting overflow interrupt:
if ((icrcnt_end.i8m < 128) && (TIFR & (1<<TOV1)))
{
// Do the job of the waiting timer overflow interrupt:
++ovfcnt;
TIFR = (1<<TOV1); // Clear Timer1 overflow interrupt
}
icrcnt_end.i16h = ovfcnt; // Upper 16 bits (overflow counter)
timediff = icrcnt_end.i32 - icrcnt_start.i32;
#ifndef FREQUENCY
TCCR1B |= (1<<ICES1); // Next trigger: Rising edge
#endif
edgeflag = RISING_EDGE;
}
}


beim kompilieren gibts ärger - es wird die doppelte definition von "_vector_6" beanstandet...

Es liegt an den beiden timer-defs, das weiss ich inzwischen, aber wie löse ich das problem?


- die definition jeweils nur im programm selbst? (Was, wenn ich beide in einem programm bräuchte?)

- beide in der standard lib?

- noch was?

für einen tipp wäre ich sehr dankbar (ich möchte endlich mit der restrukturierung meiner dateien einen abschluss finden :-) )

Besserwessi
27.12.2014, 18:00
Die ISR für Input Capture kann man natürlich nur einmal definieren. Man muss sich halt überlegen, wie man zwischen den Anwendungen umschaltet - das hängt auch mit der Hardware zusammen, denn da kann normal nur ein Signal am ICP Pin hängen. Über den analogen Comparator könnte man natürlich auch einen 2. Eingang wählen.

In Software sollte da dann eine Unterscheidung in die ISR mit rein. Je nach gerade aktiver Funktion kommt dann entweder der eine oder andere Teil. Wenn man beides in einem Programm brauch, muss die Umschaltung zur Laufzeit erfolgen, also mit IF ... ELSE, und nicht mit #ifndef . Was gerade aktiv ist, zeigt dann etwa ein Variable an. In welches File man die ISR dann packt ist noch zu überlegen - ggf. auch als extra File oder zum Hauptprogramm. In den beiden include files wird man wohl mit #IF auswählen welche Version gebraucht wird: entweder A, B oder die neue mit Unterscheidung zu Laufzeit. Ggf. kann man auch den Code nur einmal haben mit ein paar mehr #IF usw. Was man vermeiden sollte ist es in der ISR eine Funktion aufzurufen.