I am new to AVR programming, so sorry if question is trivial.
Using :
- OS : Windows7
- IDE : Atmel studio
- uC = m328p
Pins:
- ADC signal - ADC0/PC0
- LED_values - (PB0 - PB7)
- LED_START - PD1
- LED_LIGHT - PD0
- BUTTON - PD2
Goal: When you press the button it turns On the LED_START and it needs to start with conversion. AVR gets interrupt and starts ADC conversion. Basically program has two interrupts. I know that INT0 interrupt has highest priority.
I dont know how to deal with them. I have tried several things like adding global variable "start" and changing it. And also when i only set LED START it turns On and it stays in that state until LED_values reach certain value, then LED START turns Off by it self.
So please can you show me how to handle two interrupts so that fulfills stated goal and explain me what im doing wrong.
#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define F_CPU 1000000UL
#define BIT_IS_SET(byte, bit) (byte & (1 << bit))
#define BIT_IS_CLEAR(byte, bit) (!(byte & (1 << bit)))
typedef enum{false, true} bool;
bool previousState = false;
bool start = false;
char num;
void setup();
void loop();
void ADC_init();
void EI_init(); // External Interrupt
int main(void)
{
setup();
loop();
}
void setup(){
DDRC &= ~(0x1); // LDR Input
DDRB = 0xFF; //LEDs value Output
DDRD |= 0x3; //LED light LED start Output
DDRD &= ~(1 << PIND2); //Button Input
}
void loop(){
PORTD |= (1 << PIND2);
EI_init();
ADC_init();
sei();
if(start){
ADCSRA |= (1 << ADSC);
}
while(1){}
}
void ADC_init(){
ADMUX = 0x60;
ADCSRA = 0x8B;
ADCSRB = 0x0;
ADCH = 0x0;
}
ISR(ADC_vect) {
PORTB = ADCH; // assign contents of ADC high register to Port D pins
int b = (int)ADCH;
if(b > 180) { //100
PORTD = 0x1;
}else{
PORTD &= ~(0x1);
}
_delay_ms(100);
ADCSRA |= (1 << ADSC); // start next ADC
}
void EI_init(){
EIMSK |= (1 << INT0); // Interrupt enabled
EICRA |= (1 << ISC00); // any state change
}
ISR(INT0_vect){
if(BIT_IS_CLEAR(PORTD,PIND2)){
start = true;
}else{
start = false;
}
}
Here is scheme : scheme
typedef enum{false, true} bool;
, do#include <stdbool.h>
. – KamilCukvolatile bool int0_irq, adc_irq;
. Inside interrupts only set them to trueISR(INT0_vect) { int0_irq = true; } ISR(ADC_vect) { adc_irq = true; }
. Then inside your main loop simply and cleanly react for interruptswhile (1) { if (int0_irq) { int0_irq= false; start_adc_conversion_if_it_isnt_started(); } if (adc_irq) { adc_irq = false; och_adc_conversion_ended_get_data(); }
. This is a simple way of observing both interrupts. Also, try to get printf working, printf debugging is the best. – KamilCuk