Nano Hash - криптовалюты, майнинг, программирование

Как выйти из USART ISR на атмеге?

У меня проблема с atmega 1284p, я написал этот ISR для получения команд через последовательный порт. Если я отправлю CR или LF в конец команды, программа работает правильно, но если я не отправлю ни одного из них, программа останется в ISR, блокируя мою программу.

Поскольку ISR отключает мне все прерывания, я не знаю, как выйти из этого!

Кто-нибудь может мне помочь?

void USART_init(void)
{   
UCSR0B |= (1<<RXEN0) | (1<<TXEN0);
UCSR0C &= ~(1<<USBS0);                  //Stop bits 1
UCSR0C &= ~((1<<UPM00) | (1<<UPM01));   //Parity check disabled

UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);    //8 bit data
UCSR0B &= ~(1<<UCSZ02);             //8 bit data continue

UCSR0B |= (1 << RXCIE0);

UBRR0H = 0;
UBRR0L = 64; //9600 baud for a 16MHz Clock.
}


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


ISR(USART0_RX_vect)
{
clean_variables();

do {
    cmd[inc] = USART_receive();
    inc++;
} while ((cmd[inc - 1] != '\n') && (command[inc - 1] != '\r'));
inc = 0;                            
comd = 1;
split();
}
08.10.2019

Ответы:


1

Эта программа противоречит самой цели использования прерываний. Вы запускаете прерывание при получении первого символа, а затем опрашиваете его. Вместо этого вы должны вызвать прерывание один раз для каждого символа, а затем как можно скорее выйти из ISR.

Распространенным методом приема UART на основе прерываний является использование кольцевого буфера, который вы заполняете из ISR и очищаете от вызывающего. Также имейте в виду повторный вход! Всегда, для каждого отдельного прерывания, которое вы пишете, без исключений.

08.10.2019

2

Ваша проблема в том, что вы будете продолжать проверять UART на наличие данных, даже если их нет. Могу ли я предложить вам изменить USART_receive так, чтобы он возвращал флаг успеха/неудачи и записывал данные в ваш буфер, используя указатель, который вы ему передаете.

Затем в обработчике прерывания вы не только проверяете символы завершения, но и запускаете цикл while, пока USART_receive возвращает true.

Вы должны учесть тот факт, что прерывание может сработать до того, как ваше полное сообщение будет получено, т.е. нет новой строки или возврата каретки.

08.10.2019

3

Хорошей практикой было бы ограничить код в ISR до минимума (и неблокирующего!). Вам нужно только прочитать новый символ из UDR0 в буфер. Выполните всю остальную обработку в основном цикле.

ISR(USART0_RX_vect) {
    // no need to check RXC0, the byte is available when the ISR is called
    cmd[inc] = UDR0;
    inc++;        
}

main() {
    if ((cmd[inc - 1] == '\n') || (cmd[inc - 1] == '\r')) {
        // process...
    }
}

Несколько мыслей, чтобы указать

  • Там могут быть синтаксические ошибки, я просто записал это
  • Вы должны обрабатывать потенциальное переполнение буфера, когда inc становится большим
  • Объявите inc и cmd как volatile, так как они доступны из ISR и основного контекста.
  • Чтобы избежать потенциальных условий гонки, вам нужно будет сделать это "поточно-безопасным". Например, отключив прерывания (как можно короче) при доступе к cmd и inc в основном цикле. Что-то типа отключить->копировать значения->повторно включить->работа с копиями->повторить.
08.10.2019
  • Кроме того, запускайте проверки cmd[inc-1] только в том случае, если inc>=1. В основном цикле может потребоваться переместить уже полученные символы за проанализированную команду в начало буфера, что необходимо сделать с отключенным прерыванием. А тут переполнение буфера. Может подойти кольцевой буфер. 11.10.2019
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

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

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..