Hi fellas,
I need some help to implement an external INT0 interrupt which powers the MCU from power down mode to idle mode and start ADC conversion. I have only 2 months worth experience of ATMEL studio 7 and needless to say I am yet to gain a strong foothold.
The program I am trying to interrupt has the following algorithm -
- Set ATTiny20 in power down mode with ADC switched off (for reduced power consumption).
- Set an external interrupt INT0 (on Pin B2) as rising edge level which detects an external signal.
- Once rising edge is detected up to few clock cycles, the Tiny20 is woken up through the ISR routine and ADC parameters are set.
- execute ADC in free run mode.
I am attaching my code below -
#include <avr/io.h> #include <avr/sleep.h> #include <avr/interrupt.h> uint16_t adcValue; //Stores all 10 bits uint8_t low; // stores bits 0 and 1 of ADCL ISR(INT0_vect) // called immediately on encountering sei() { MCUCR |= (0<<SE); //Clear enable sleep MCUCR |= (0 << SM1); // powering up the controller to idle mode PRR |= (0 << PRADC); // powering up the ADC ADCSRA |= (0 << ACD); // powering up the comparator DDRA |= (1 << 1)|(1 << 2)|(1 << 3)|(1 << 4)|(1 << 5)|(1 << 6)|(1 << 7); //PA1 - 7 set as outputs DIDR0 |= (1 << ADC0D); //PA0 input buffer disabled to reduce current DDRB |= (1<<1)|(1<<3)|(1 <<4); //PB1,3,4 set as outputs ADMUX |= (0 << REFS); // Reference = Vcc ADCSRA |= (1 << ADATE); ADCSRB |= (1 << ADLAR) | (0 << ADTS2) | (1 << ADTS1) | (0 << ADTS0); // rising edge of int0 ADCSRA |= (1 << ADPS2) | (1 << ADEN) | (1 << ADSC); } int main (void) { ADCSRA |= (0 << ADEN); // disabling the ADC before shutting it down PRR |= (1 << PRADC); // shutting down the ADC // comparator disabled automatically MCUCR |= (1 << SE); // sleep enable bit set to 1 MCUCR |= (1 << SM1); // powering down the controller GIMSK |= (1 << INT0);//Enable INT0 interrupt MCUCR |= (1 << ISC00) |(1 << ISC01);//INT0 interrupt = rising level interrupt sei(); // triggers the interrupt ADCSRA |= (1 << ADSC); for(;;) // Loop Forever { //ADCSRA |= (1 << ADSC); uint8_t low = ADCL; uint16_t adcValue = (ADCH<<2)|(low>>6); //This variable stores the total 10 bits value if(adcValue <= 32 && adcValue >=0) { PORTA |= (1 << 1); // LED 1 ON, Rest others OFF PORTA &= ~(1 << 2) &~(1 << 3) &~(1 << 4) &~(1 << 5) &~(1 << 6) &~(1 << 7); PORTB &= ~(1 << 1) &~(1 << 3); } else if(adcValue <= 64 && adcValue >32) { /* switch on other LEDs for different values of ADC output*/ } else { } } }
I programmed the above code and I get the following behavior -
- The controller is powered down.
- When an external signal interrupt is applied to Pin B2 (INT0), the ADC apparently turns ON. This is because the first IF case gets executed and LED1 gets turned on.
- However, with changing analog input values at Pin A0, I do not get corresponding changes in other LEDs.
Further note - This program when run in free running mode without any interrupts works perfectly fine. The main goal of this code was to display each bit of the ten bit value as an LED light. (Yes, I am still working on Fleury's LCD display!).