Как реализовать прерывание для последовательной связи USART для Atmega328p / Arduino Nano? - PullRequest
0 голосов
/ 01 ноября 2018

У меня есть небольшой проект для школы, который требует от меня загрузки данных в EEPROM Atmega328p через последовательную связь USART. Я собираюсь выяснить, ЭСППЗУ читать / писать самостоятельно.

У меня проблемы с отправкой данных с использованием прерываний. По сути, я хочу сделать так, чтобы цикл Arduino Nano проходил через код, и когда я отправляю что-либо через последовательную связь USART с использованием последовательного монитора IDE Arduino, произойдет прерывание, и отправленные данные будут сохранены в переменная.

Мой CLOCK - 16 МГц со скоростью 9600 бод; и, как я уже сказал, я использую Arduino IDE.

Вот что я пробовал до сих пор:

#define USART_BAUDRATE 9600
#define MYUBRR (((F_CPU / (USART_BAUDRATE * 16UL))) - 1)

void setup() {

   UCSR0B = (1 << RXEN0) | (1 << TXEN0);   // Turn on the transmission and reception circuitry
   UCSR0C = (1 << UCSZ00) | (1 << UCSZ01); // Use 8-bit character sizes

   UBRR0H = (MYUBRR >> 8); // Load upper 8-bits of the baud rate value into the high byte of the UBRR register
   UBRR0L = MYUBRR; // Load lower 8-bits of the baud rate value into the low byte of the UBRR register

   UCSR0B |= (1 << RXCIE0); // Enable the USART Recieve Complete interrupt (USART_RXC)

   sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed  

}

//intrerupt on receive
ISR (USART_RXC_vect)
{
   char ReceivedByte;
   ReceivedByte = UDR0; // Fetch the received byte value into the variable "ByteReceived"
   UDR0 = ReceivedByte; // Echo back the received byte back to the computer
}

//use eeprom function to read/write to EEPROM
void loop() {

}

Я скопировал и адаптировал код с этого сайта (первое сообщение)

(В регистре UCSR0C нет ни одного бита URSEL, который упоминается в этом посте - лист данных не упоминает об этом и выдает ошибку при попытке его использовать)

Но похоже, что прерывание (как оно представлено в последней части поста) не работает для меня. Я проверил, могу ли я читать и писать на последовательном мониторе, используя следующий код:

while ((UCSRA & (1 << RXC)) == 0) {}; // Do nothing until data have been received and is ready to be read from UDR
ReceivedByte = UDR; // Fetch the received byte value into the variable "ByteReceived"

while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it
UDR = ReceivedByte; // Echo back the received byte back to the computer

Но это заставляет контроллер ждать передачи данных через последовательный монитор, а затем печатает их на последовательном мониторе. Я не хочу такого поведения.

Вот лист данных, который я использовал для проверки моего кода: Лист данных Atmega328p

У меня вопрос, я что-то не так сделал? я что-то забыл в своей реализации прерывания последовательной связи USART? Что на самом деле не так с моей реализацией, почему она не работает?

Заранее спасибо!

1 Ответ

0 голосов
/ 01 ноября 2018

Я думаю, вы ошибаетесь:

ISR (USART_RXC_vect)
{
    char ReceivedByte;
    ReceivedByte = UDR0; // Fetch the received byte value into the variable "ByteReceived"
    UDR0 = ReceivedByte; // Echo back the received byte back to the computer
}

В приведенном выше коде вы в основном говорите UDR0 = UDR0. Вам нужно дать некоторое время между этими двумя строками кода, чтобы получить желаемый эффект. Если вы посмотрите на опубликованную вами ссылку на уродцев AVR, у них будет следующая строка:

  while ((UCSRA & (1 << UDRE)) == 0) {}; // Do nothing until UDR is ready for more data to be written to it

Надеюсь, это поможет!

...