0
votes

I am new to AVR programming, so sorry if question is trivial.

Using :

  1. OS : Windows7
  2. IDE : Atmel studio
  3. uC = m328p

Pins:

  1. ADC signal - ADC0/PC0
  2. LED_values - (PB0 - PB7)
  3. LED_START - PD1
  4. LED_LIGHT - PD0
  5. 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

1
Don't ` _delay_ms(100);` inside ISR.KamilCuk
Don't typedef enum{false, true} bool;, do #include <stdbool.h>.KamilCuk
Do a main loop inside your main function and two global variables volatile bool int0_irq, adc_irq;. Inside interrupts only set them to true ISR(INT0_vect) { int0_irq = true; } ISR(ADC_vect) { adc_irq = true; }. Then inside your main loop simply and cleanly react for interrupts while (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

1 Answers

0
votes

First of all, you should make start be volatile since it is being used by both the main loop and the interrupt. The volatile keyword tells the compiler that the variable might be modified by things outside of its control, so it cannot optimize away any reads or writes to the variable:

volatile bool start = false;

Secondly, you probably want to remove this line you wrote at the end of loop:

while(1){}

That line is bad because it causes your program to go into an infinite loop where it does nothing. I think you actually want the code you wrote about it in the loop function to run multiple times.

Secondly, after you detect that the start flag has been set, you probably need to set it to 0, or else it will just be 1 forever.

Third, setting start to false in the INT0 ISR might be a bad idea, because it might get set to false before you main loop has a chance to observe it being true and handle the event. I guess it really depends on exactly what you are trying to do. You could try adding details to your question about exactly what problem you are trying to solve using the AVR. See What is the XY problem?.

There are probably other issues with your code that need to be debugged. Can you think of any ways to make this simpler? Maybe you can reduce the number of interrupts you are using. To debug, you can try blinking some LEDs to figure out what parts of your program are executing.