如何为ATmega328P/Arduino Nano实现串行USART通信中断



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

我在使用中断发送数据时遇到问题。基本上,我想让Arduino Nano循环通过代码,当我使用Arduino IDE的串行监视器通过USART串行通信发送东西时,会发生中断,发送的数据将保存在变量中。

我的时钟为16 MHz,波特率为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 Receive Complete interrupt (USART_RXC)
sei(); // Enable the Global Interrupt Enable flag so that interrupts can be processed
}
// Interrupt 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 the 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串行通信中断时忘记了什么吗?我的实现到底出了什么问题?为什么它不起作用?

我认为你在这里出错了:

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

也许您还应该禁用中断处理程序中的中断。这是正常的做法,除非你有特别的打算。也许现在的工作方式是每一位都触发中断。

最新更新