Zurück (C) Christof Ermer, Regensburg

31.01.2012


Diese Seite ist eine Arbeisthilfe

Kurzer Kurs :  http://dl.dropbox.com/u/48183013/PDFs/Timer-Frequenzgenerator.pdf


INTERRUPT  Reihenfolge der "Timer Events"
#define TIMER2_COMP_vect        _VECTOR(3)
#define TIMER2_OVF_vect            _VECTOR(4)

#define TIMER1_CAPT_vect        _VECTOR(5)
#define TIMER1_COMPA_vect        _VECTOR(6)
#define TIMER1_COMPB_vect        _VECTOR(7)
#define TIMER1_OVF_vect            _VECTOR(8)

#define TIMER0_OVF_vect            _VECTOR(9)
#define TIMER0_COMP_vect        _VECTOR(19)



//Header Definitionen, aus der zur CPU gehörenden PDF extraiert. z.B au s der iom16..h
// ******************************
// SPEZIFISCHE DEFINITIONEN; JE NACH HARDWARE
//BEI 16 MHz Quarz = F_CPU / Teiler
// QUARZ/DIVIDE = FREQUENZ
#define TIMER_DIVIDE_FRQ_1    ((float)F_CPU)    // 16000000UL
#define TIMER_DIVIDE_FRQ_8    (F_CPU / 8.0) //2000000UL       
#define TIMER_DIVIDE_FRQ_64    (F_CPU / 64.0) //250000UL
#define TIMER_DIVIDE_FRQ_256    (F_CPU / 256.0) //62500U
#define TIMER_DIVIDE_FRQ_1024    (F_CPU / 1024.0) //15625U

#define T1_FRQ_MAXIMAL_FRQ    16000000
#define T1_FRQ_MINIMAL_FRQ    0.238422217  // 16^6/1024/65535


// ******************************
//TIMER REGISTER
#define TCCR0_FAST_PWM    0x48    //Mode 3
#define TCCR0_OC0_MODE    0x20    //Clear Timer on Compare Match
#define TCCR0_OC0_DISCONNECT_MODE    0x00
#define TCCR0_CTC_MODE    0x08
#define TCCR0_CLK_STOP    0x00   
#define TCCR0_CLK_STOP_MASK    0xF8   
#define TCCR0_CLK_1        0x01    //62500 PWM
#define TCCR0_CLK_8        0x02    //7812 Hz PWM
#define TCCR0_CLK_64    0x03    //976,56Hz PWM
#define TCCR0_CLK_256    0x04    //244,14Hz PWM
#define TCCR0_CLK_1024    0x05    //~61,035 PWM
#define TCCR0_EXT_CLK_FALL_T0    0x06   
#define TCCR0_EXT_CLK_RISE_T0    0x07

// ******************************
//TCCR1A
#define TCCR1A_CTC_MODE            0x00    //WGM11 WGM10  = 0
#define TCCR1A_FAST_PWM_ICR1    0x02 //WGM11
#define TCCR1A_FAST_PWM_8BIT    0x01 //WGM11 WGM10 n TCCR1A
#define TCCR1A_FAST_PWM_9BIT    0x02 //WGM11 WGM10 n TCCR1A
#define TCCR1A_FAST_PWM_10BIT    0x03 //WGM11 WGM10 n TCCR1A
#define TCCR1A_CLEAR_WGMX_MASK 0xFC // Lösche WGM 11/10
#define TCCR1A_PWM_CLR_OC1A    0x80    //Clear OC1A=C1B

// ******************************
//#define TCCR1B_CLOCKSEL_CTC1    0x08    //Clear Timer/Counter  on Compare Match Timer/Counter 1
#define TCCR1B_CLOCKSEL_STOP    0x00    //Clock Select Bits
#define TCCR1B_CLOCKSEL_MSK        0xF8    //zum Stoppen der CLK
#define TCCR1B_CTC_MODE            0x08    //WGM12 ClearTimeronCompare
#define TCCR1B_FAST_PWM_XBIT    0x08    //WGM12 only
#define TCCR1B_CLOCKSEL_CPU_1    0x01    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_8    0x02    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_64    0x03    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_256    0x04    //Clock Select Bits
#define TCCR1B_CLOCKSEL_CPU_1024    0x05    //Clock Select Bits
#define TCCR1B_CLK_STOP_MSK        0xF8//TCCR1A

// ******************************
//TCCR2
#define TCCR2_WGM_NORMAL    0x00
#define TCCR2_CTC_MODE        0x08 //WGM12 0000 1000
#define TCCR2_CTC_FAST_PWM    0x08 //WGM12 0000 1000
#define TCCR2_COM_NORMALPORT    0x00
#define TCCR2_CLK_STOP    0x00
#define TCCR2_FAST_PWM    0x48    //Mode 3
#define TCCR2_CLK_1        0x01
#define TCCR2_CLK_8        0x02
#define TCCR2_CLK_32        0x03
#define TCCR2_CLK_64        0x04
#define TCCR2_CLK_128    0x05
#define TCCR2_CLK_256    0x06
#define TCCR2_CLK_1024    0x07
#define TCCR2_CLK_STOP    0x00
#define TCCR2_CLK_STOP__MSK    0xF8   
//TIMER2 WIRD BERECHNET /z.B:OverFLow SYSCLK /  256 / TCCR2_CLK_64 =  OVL/Sec

//TIMER
#define TIMSK_TOIE0_FLAG    0x01
#define TIMSK_OCIE0_FLAG    0x02
#define TIMSK_TOIE1_FLAG    0x04
#define TIMSK_OCIE1B_FLAG    0x08
#define TIMSK_OCIE1A_FLAG    0x10
#define TIMSK_TICIE1_FLAG    0x20
#define TIMSK_TOIE2_FLAG    0x40
#define TIMSK_OCIE2_FLAG    0x80

#define TIMSK_T0_CLR_ALL_MASK 0b11111100
#define TIMSK_T1_CLR_ALL_MASK 0b11000011
#define TIMSK_T2_CLR_ALL_MASK 0b00111111


Timer aktivieren. Unter Verwendung der #defines,
 z.B: dieser, die mit dem Namen des Regsiter beginnen.
TCCR1B
TCCR1B =  TCCR1B_CTC_MODE | gu8Timer_CSxxClkSelect;  
       
gu8Timer_CSxxClkSelect wird vorher berechnet... Codebeispiele weiter unten...























Code Beispiele:

static volatile uint8_t gu8Timer_CSxxClkSelect;    //z.B.#define TCCR1B_CLOCKSEL_CPU_1024    0x05


// ***** ***********************************************************
ISR( TIMER1_COMPA_vect )// signal handler
//#define SIG_OUTPUT_COMPARE1A    _VECTOR(6)
// *******************************************************************
{//cli(); //I_SREG automtaic clear by Interrupt and Enabled by RETI   
//ALLES WA SZU TUN IST
};



// *************************************
void FRQ_Off(void)
// *************************************
{
cli();
TCCR1B = TCCR1B_CLOCKSEL_STOP;    //Stopen, damit keine geschachtelten Interrrupts passieren...
TIMSK &= ~_BV( OCIE1A );  //Interrupt OFF
sei();
};


// *************************************
void FRQ_On(void)
// *************************************
{
cli();
TCNT1 = 0;  //sicherung gegenen unbeabsichtigten Overrrun
TIMSK |= _BV( OCIE1A );    //Interrupt ein
TCCR1B = TCCR1B_CTC_MODE | gu8Timer_CSxxClkSelect;//Clear Timer on Compare=CTC.  MODE an OCR1A + / CLk/1024
sei();
};


// **********************************************
int32_t Round(double fIn)
// **********************************************
{ return (int32_t)floor(fIn + 0.5); };

// *************************************
void Set_Frq(float fVal)  //Verbessert mit Zielbereichskalierung des Vorteilers.
// *************************************
{
float fComVal;
float fTimerDivider;

if( fVal > MAXIMAL_FRQ ) return;
if( fVal < MINIMAL_FRQ ) return;
//Voreinstellung
fTimerDivider = TIMER_DIVIDE_FRQ_0; //if( pfVal < TIMER_HALFCOMP_FRQ_1024)   
gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_1;
//Clock udn OCR1A so hoch als möglich
if( ( fComVal = F_CPU / fVal )  > 0xFFFF )
    {
    fTimerDivider = TIMER_DIVIDE_FRQ_8; //if( pfVal < TIMER_HALFCOMP_FRQ_1024)   
    gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_8;
    if( ( fComVal = TIMER_DIVIDE_FRQ_8 / fVal )  > 0xFFFF )
        {
        fTimerDivider = TIMER_DIVIDE_FRQ_64; //if( pfVal < TIMER_HALFCOMP_FRQ_1024)   
        gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_64;
        if( ( fComVal = TIMER_DIVIDE_FRQ_64 / fVal )  > 0xFFFF )
            {
            fTimerDivider = TIMER_DIVIDE_FRQ_256; //if( pfVal < TIMER_HALFCOMP_FRQ_1024)   
            gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_256;
            if( ( fComVal = TIMER_DIVIDE_FRQ_256 / fVal )  > 0xFFFF )
                {   
                fTimerDivider = TIMER_DIVIDE_FRQ_1024; //if( pfVal < TIMER_HALFCOMP_FRQ_1024)   
                gu8Timer_CSxxClkSelect = TCCR1B_CLOCKSEL_CPU_1024;
                fComVal = TIMER_DIVIDE_FRQ_1024 / fVal;
                }}}};
cli();
TCNT1 = 0;  //sicherung gegenen unbeabsichtigten Overrrun
OCR1A = (uint16_t)Round( fComVal );
gfSelectedFRQ = fTimerDivider / OCR1A;
TCCR1B = TCCR1B_CTC_MODE | gu8Timer_CSxxClkSelect;//Clear Timer on Compare=CTC.  MODE an OCR1A + / CLk/1024
sei();
};