Search code examples
timerembeddedatmega32

measuring a generated wave frequency using ICU - Atmega32


I'm trying to use the ATMega32 Input Capture Unit in the following manner:

I have a wave generated using TIMER0 (through OC0 pin) (XTAL=8MHz, prescaler =1024, CTC mode, OCR0=244, giving ~32Hz). I am then trying to capture this wave using TIMER1 (through ICP pin) (XTAL=8MHz, prescaler=1024, normal mode, resulting in ~7812.5 Hz)

The code snippet provides more details.

The problem that I have only result of 0.

**

MODIFIED.

** thanks alot @clifford , according to the below code ,it works ,but :

1- there's a little error (results aren't accurate).

2- when i change my equation

from

        count=(capture2+(captOVf*65536))-capture1;

           to   
   count=capture2-capture1; 

i get garbage displayed on the LCD .

very sorry for the bad question formatting .

typedef enum{
    CAPTURE1,
    CAPTURE2,
    WAIT
}timer_states_t;

volatile timer_states_t flag= WAIT;
volatile u8 x,y,captOVf,TOVfs=0;
volatile u16 capture1,capture2;

void setup_pins(){

    SET_BIT(DDRB,3); //SET OC0 pin as output
    CLEAR_BIT(DDRD,6); //set ICP pin as input
    SET_BIT(PORTD,6);  //set ICP pin pullup resistance

}

//Timer0 Configurations / wave generator .
void timer0_init(){
    OCR0=244;
    TCCR0=0x1D; //ctc , 1024 , toggle OC0 pin on compare match ;
}

//Timer1 Configurations / capturer .
void timer1_init(){
    TCCR1A=0x00; // Timer1 , normal mode, no on compare output ,
    TCCR1B=0x45; // prescaler 1024, Input capture edge as rising .
    SET_BIT(TIMSK,TICIE1); // enable input capture interrupt .
    SET_BIT(TIMSK,TOIE1); //enable timer1 overflow interrupt .
    CLEAR_BIT(ACSR,ACIC);  //disable Analog comparator .
    SET_BIT(SREG,7); //GLOOBAL ITERRUPT

}

ISR(TIMER1_OVF_vect){
    TOVfs++;

}

ISR(TIMER1_CAPT_vect){
    switch(flag){
    case CAPTURE1:
        //capture1=ICR1;
        x=ICR1L;
        y=ICR1H;
        capture1=x | (y<<8);
        TOVfs=0;
        flag=CAPTURE2;
        break;

    case CAPTURE2:
        //capture2=ICR1;
        x=ICR1L;
        y=ICR1H;
        capture2=x | (y<<8);
        flag=WAIT;
        captOVf=TOVfs;
        break;
    }
}
int main(){

setup_pins();
timer0_init();
timer1_init();
LCD_init();

unsigned long count  ;
u8* countString ;

while(1){
    flag=CAPTURE1;

    while(flag != WAIT);

        count=(capture2+(captOVf*65536))-capture1;
        itoa(count,countString,10);
        LCD_send_string("count:");
        LCD_send_string(countString);
        _delay_ms(500);
        LCD_send_cmd(lcd_Clear);

    }
}

Solution

  • Nothing ever modifies capture1 or capture2 which are themselves unitialised.

    capture1 = x | (y<<8);
    ...
    capture2 = x | (y<<8);
    

    perhaps? temp1, and temp2 appear to serve no purpose; being set in the ISR and not referenced elsewhere.

    Given that TIMER2 count will be about 244 for a single 32Hz cycle, is the overflow counter not unnecessary? Simply reset the TIMER1 count at CAPTURE1 and get the count at CAPTURE2, removing the arithmetic and one of the capture variables.

    All shared variables need to be declared volatile, all non shared variables need not be global.