2017-01-09 2 views
-3

Недавно я столкнулся с проблемой, когда играл с ATmega2560, и я действительно не понимаю, что с ним не так.ATmega2560 с использованием прерывания UART для управления глобальным флагом

Вот мой код.

главная:

#include "Definitions.h" 

int main(void) { 
    Initialization(); 
    while (1) { 
     //_delay_ms(1); // or printf... 
     //wait for RXC flag 
     if (RxFlag) { 
      //wait for new byte in 
      //PORTB &= ~(1 << PB7); 
      PORTB |= (1 << PB7); 
      rxcount = 0; 
      UDR0 = 'R'; 
      RxFlag = false; 
      TxFlag = false; 
     } 
    } 
} 

IRQ:

#include "Definitions.h" 

ISR(USART0_RX_vect) { 
    while(!(UCSR0A & (1 << RXC0))) 
    //wait for RXC flag 
     ; 
    /* Loop-back test */ 
    //PORTB |= (1 << PB7); 
    //test_data = UDR0; 
    TxFlag = true; 
    //enableUDRI0(); 
    //PORTB &= ~(1 << PB7); 
    //PORTB |= (1 << PB7); 
    RxBuffer[rxcount++] = UDR0; 
    if(!(rxcount < RX_BUF_SZ)) { 
     //rxcount = 0; 
     PORTB |= (1 << PB7); 
     RxFlag = true; 
    } 
} 

ISR(USART0_UDRE_vect) { 
    while(!(UCSR0A & (1 << UDRE0))) 
    //wait for udr to be empty 
     ; 
    /* Loop-back test */ 
    UDR0 = 0x30 + rxcount; 
    disableUDRI0(); 
} 

Проблема заключается в том, когда я получил некоторые ДАННЫЕ от USART, я попытался установить RxFlag, который может активнее Условный оператор в главном цикле , Но это не сработало, пока я не раскомментировал функцию до if-statement, который может быть _delay_ms() или printf().

Это не имеет никакого смысла. Я помню, что мне не нужны эти функции, и он все равно может заставить глобальные переменные влиять на основной цикл. Или есть какие-то подробности, которые я пропустил? Пожалуйста, дайте мне подсказку, чтобы понять это, я смущен.

+0

Пожалуйста, разместите здесь свой код, а не внешние ссылки. –

+3

В то время как ISR является худшей идеей ... когда-либо ... Думаю, вы скопировали эту форму, не приводящую к прерыванию код. – LPs

+0

Похоже, есть некоторые основные недоразумения о том, как работают прерывания. И код отсутствует. Прочтите [ask] и следуйте советам! – Olaf

ответ

0

Невозможно быть определенным, однако я думаю, что это объясняет вашу проблему, так что это может быть ошибка.

Вы не указали объявление RXFlag, но я предполагаю, что вы не объявляете его volatile. Если вы этого не сделаете, компилятор может предположить, что он знает все о том, что произойдет с этой переменной. В частности, он знает, что, если main() не вызывает никаких других функций, значение RxFlag никогда не изменится. Таким образом, он может оптимизировать выражение if, перемещая его за пределы цикла. В действительности это изменение кода, как это:

#include "Definitions.h" 

int main(void) 
{ 
    register bool x; 

    Initialization(); 

    x = RxFlag; 

    while (1) 
    { 
     //wait for RXC flag 
     if (x) //wait for new byte in 
     { 
      //PORTB &= ~(1 << PB7); 
      PORTB |= (1 << PB7); 
      rxcount = 0; 
      UDR0 = 'R'; 
      RxFlag = false; 
      TxFlag = false; 

     } 
    } 
} 

Однако, если main() вызывает другую функцию, то компилятор отказывается пытается сохранить RxFlag в реестре по этому вызову. Другая функция может изменить регистр, в котором удерживается RxFlag. Он должен был бы вставить его в стек или что-то еще. Чтение его снова дешевле по коду и времени, и поэтому он будет читать его каждый раз, когда он обходит цикл.

Правильное исправление для этой ошибки заключается в объявлении любых переменных, разделяемых между основным потоком и ISR, как volatile.

+0

С помощью gcc половина регистров AVR * сохранена в памяти *. И gcc использует это при оптимизации и может сохранять значения в регистрах даже по вызовам функций. Вызов функции также может быть встроен, чтобы оптимизатор даже не выполнялся как вызов. – JimmyB

Смежные вопросы