How to get GPS Data when switch is pressed in Atmega328p

91 Views Asked by At

So I am working on getting the gps data when the button is pressed using external interrupt. My problem is , it is working without the external interrupt but when I added it, it's not getting the data. Is something wrong with my code? I am using quectel l80-m39 for gps connected to the rx of atmega328p. Provided below is my code. The button is connected to PD3 of atmega.

#define F_CPU 8000000UL // Defining the CPU Frequency

#include <avr/io.h>     // Contains all the I/O Register Macros
#include <util/delay.h> // Generates a Blocking Delay
#include <avr/interrupt.h>

#define USART_BAUDRATE 9600 // Desired Baud Rate
#define BAUD_PRESCALER (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

void USART_Init()
{
    // Set Baud Rate
    UBRR0H = (unsigned char)(BAUD_PRESCALER >> 8);
    UBRR0L = (unsigned char)BAUD_PRESCALER;

    // Enable Receiver
    UCSR0B |= (1 << RXEN0);

    // Set data frame format: asynchronous mode,no parity, 1 stop bit, 8 bit size
    UCSR0C |= (1 << UCSZ01) | (1 << UCSZ00);
}

unsigned char USART_ReceivePolling(void)
{
    while (!(UCSR0A & (1 << RXC0)));
        return UDR0;
}


void readgps()
{
    uint8_t lati_value[15];
    unsigned char LocalData;
    int i = 0;
    LocalData = USART_ReceivePolling();
    if (LocalData == '$')
    {
        LocalData = USART_ReceivePolling();
        if (LocalData == 'G')
        {
            LocalData = USART_ReceivePolling();
            if (LocalData == 'P')
            {
                LocalData = USART_ReceivePolling();
                if (LocalData == 'G')
                {
                    LocalData = USART_ReceivePolling();
                    if (LocalData == 'G')
                    {
                        LocalData = USART_ReceivePolling();
                        if (LocalData == 'A')
                        {
                            LocalData = USART_ReceivePolling();
                            if (LocalData == ',')
                            {
                                LocalData = USART_ReceivePolling();
                                while (LocalData != ',')
                                {
                                    LocalData = USART_ReceivePolling();
                                }
                                LocalData = USART_ReceivePolling();
                                while (LocalData != ',')
                                {
                                    lati_value[i] = LocalData;
                                    ++i;
                                    LocalData = USART_ReceivePolling();
                                }
                                PORTD |= (1 << PD2);
                                _delay_ms(100);
                            }
                        }
                    }
                }
            }
        }
    } else 
    {
        PORTD &= ~(1 << PD2);
    }
}

int main(void)
{
    EICRA |= (1 << ISC10) | (1 << ISC11); // interrupt on rising edge of INT1
    EIMSK |= (1 << INT1);                 // external interrupt enable on INT1
    
    sei();
    while (1)
    {

    }
}

ISR(INT1_vect)
{
    if (PIND & (1 << 3))
    {
        DDRD = 0b01110110;
        USART_Init();
        readgps();
    }
} 
1

There are 1 best solutions below

8
Armandas On

USART_ReceivePolling() is blocking the ISR. You should never block the ISR. In the ISR just set a flag and check it in the main loop. Something like this (unchanged code removed):

// ...

// Flag for reading the GPS
volatile unsigned char g_read_gps = 0;

// ...

int main(void)
{
    // ...

    while (1)
    {
        if (g_read_gps) {
            readgps();
            g_read_gps = 0;
        }
    }
}

ISR(INT1_vect)
{
    if (PIND & (1 << 3))
    {
        g_read_gps = 1;
    }
}