как очистить флаг прерывания UART вручную?

Я использую ATmega32. У меня есть ISR (USART_RXC_vect) следующим образом

ISR(USART_RXC_vect)
{
    char ReceivedChar ;     
    ReceivedChar = UDR; // Fetch the received byte value into the variable "ReceivedChar"

    if(ReceivedChar == '\n'){       
        RxBuffer[RxPos] = '\0' ;                    
        RxReady=0;
        USART_Cmd_Eval();            
    }
    else{
        RxBuffer[RxPos] = ReceivedChar;
        RxPos++; 
    }
}

После запуска ISR он вызывает следующую функцию, чтобы определить, какая команда получена от ПК.

void USART_Cmd_Eval(void)
{
            strcpy(RxCommand,RxBuffer);

            if(strcmp(RxCommand, "c") == 0){
                    RxReady = 1;                     
                    ADC_measure();
            }   
}

Для каждой команды будет вызываться относительная функция. Как показано ниже:

void ADC_measure(void)
{
        while(RxReady ==1)
        {
                _delay_ms(50);
                // Measrung ADC values and send them to USART
        }
}

Проблема в том, что я не могу отправить другую команду, потому что она застряла в функции ADC_measure. По сути, он не хочет получать другую команду через ISR, я думаю, что он будет продолжать открываться. Поэтому я думаю, что должен сбросить флаг прерывания перед вызовом ADC_measure. Верно? Как это сделать?

Ответы (1)

Когда выполняется любая процедура прерывания, бит I SREG сбрасывается, чтобы избежать следующего выполнения прерывания. Бит сбрасывается RETI . Т.е. это можно сделать и вручную SBI SREG,I (или через uint8_t sreg = SREG; sreg |= _BV(I); SREG = sreg; ).

Но также может быть вызван повторный вызов USART_RXC_vect ! Мне не нравятся какие-либо _delay() в подпрограммах прерывания, поскольку они должны быть как можно короче. Вы должны перекодировать его.

большое спасибо за ваш ответ. Моя цель — разрешить повторный вызов USART_RXC при выполнении функции adc_meassure. Кроме того, какую задержку надо убрать??
USART_RXC_vect->USART_Cmd_Eval->ADC_measure->_delay_ms() и в функции ADC_measure есть даже длинный цикл while .
о, вы имеете право. У вас есть другое решение для этого? я имею в виду, где я могу выполнить цикл while после закрытия USART_RXC и USART_Cmd_Eval?
Я бы сделал основной цикл программы (если вы используете Arduino, это loop() ). Просто чтобы посмотреть флаг RxReady , объявить его как volatile и добавить некоторые вещи, препятствующие гонке.