如何为Atmega328p / Arduino Nano的串行USART通信实现中断?

时间:2018-11-01 15:32:28

标签: arduino interrupt serial-communication atmega usart

我有一个上学的小项目,要求我通过USART串行通信将数据加载到Atmega328p的EEPROM中。我要自己弄清楚EEPROM的读/写。

我在使用中断发送数据时遇到问题。基本上,我想做的是通过代码进行Arduino Nano循环,当我使用Arduino IDE的串行监视器通过USART串行通信发送某些内容时,将发生中断,并且将发送的数据保存在变量。

我的时钟为16MHz,波特率为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() {

}

我已经复制并改编了代码from this site (first post)

(在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 datasheet

我的问题是,我做错了什么吗?我在执行USART串行通信中断时忘记了什么吗?我的实现实际上有什么问题,为什么不起作用?

提前谢谢!

1 个答案:

答案 0 :(得分:0)

我认为您在这里出错:

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

希望这会有所帮助!