arduino - 如何为 Atmega328p/Arduino Nano 实现串行 USART 通信中断?
问题描述
我有一个学校的小项目,需要我通过 USART 串行通信将数据加载到 Atmega328p 的 EEPROM 中。我要自己弄清楚EEPROM读/写。
我在使用中断发送数据时遇到问题。基本上,我想做的是让Arduino Nano循环通过代码,当我使用Arduino IDE的串行监视器通过USART串行通信发送一些东西时,会发生中断,发送的数据将保存在一个多变的。
我的CLOCK是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() {
}
我已经复制并改编了这个网站的代码(第一篇文章)
(在 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
希望这可以帮助!
推荐阅读
- javascript - 选择两个 array[index] 选择器之间的所有内容
- javascript - 如何在不使用服务器的情况下将表单数据存储在 HTML 文档中?
- core-data - SwiftUI 对 List 中的 CoreData 对象重新排序
- android - 使recyclerview选择跟踪器的选择模式仅在长按时激活
- swift - 如何在方法签名中使用协议类型?
- python - 如何堆叠多个调用?
- kubernetes - 如何在分布式系统中维护套接字或通信通道
- r - 名义尺度变量和基数尺度变量之间的相关系数
- php - PHP ZipArchive->extractTo() 无法正常使用仅以波兰语保存的文件名
- html - 如何防止此表格行出现在表格标题后面?