使用ATmega328P的UDRE进行中断驱动的USART通信

3
我在使用C语言为Arduino编程时遇到了串行通信的问题。由于应用需要速度,所以我需要使用C语言进行编程。我使用Codeblocks进行编译,因为它很容易使用。
我希望串行功能不会阻塞应用程序并具有调试能力,因此我正在尝试编写一个循环缓冲区类型的串行库。应用程序不需要接收数据,只需要打印输出。
问题出在串行中断似乎没有触发,导致程序被阻塞,编译器也会发出警告:
main.c|11|warning: ‘UART_UDRE_vect’ appears to be a misspelled signal handler|

测试程序如下:
#include<avr/io.h>
#include<avr/interrupt.h>

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

char ok = 0;

ISR(UART_UDRE_vect) {
    ok = 1;
    UCSR0B &= ~(1<<5);
}

int main(void) {
  UBRR0H  = (BAUD_PRESCALE >> 8);
  UBRR0L  = BAUD_PRESCALE;
  UCSR0B |= (1<<TXEN0);
  UCSR0C |= (1<<UCSZ00) | (1<<UCSZ01);
  sei();
  while(1){
    // write the byte to the serial port
    UDR0 = '0';
    UCSR0B |= (1<<5);
    while(ok != 1){}
    ok = 0;
    UDR0 = '\n';
    UCSR0B |= (1<<5);
    while(ok != 1){}
    ok = 0;
  }
  return 0;
}

配置和波特率是正确的,因为找到的回显示例(此处链接)确实有效。

此外,其他示例不使用UDRE,只使用RX中断,这不是我要找的。

我有遗漏什么吗?


中断在AVR interrupt.h库中列出,文档在此处记录:链接 - BigFilhao
是的,刚刚编辑了问题,但问题仍然存在,现在只打印第一个字符,“ok”再也没有被设置过。 - BigFilhao
1
与中断共享的变量必须声明为 volatile,否则编译器可能无法理解它们被使用,因此在优化时会破坏您的程序。static volatile char ok; - Lundin
它成功了!非常感谢! - BigFilhao
我对问题进行了回滚,以便它包含有错误向量名称的初始问题。以防将来有人遇到相同的问题并找到这个问题。 - Lundin
显示剩余5条评论
1个回答

1

两个问题:

  • 根据您提供的文档,您特定的ATmega328p部件的中断向量应命名为USART_UDRE_vect

  • 与中断共享的变量必须始终声明为volatile,否则编译器可能无法理解它们的使用情况,从而在优化时破坏您的程序。基本上,编译器认为变量ok永远不会获得除0以外的其他值,因为它没有看到ISR的函数调用(因为它是由硬件而不是程序调用的)。将声明更改为static volatile char ok;


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接