使用UDRE和ATmega328P的中断驱动USART

时间:2017-10-30 14:34:02

标签: c arduino embedded avr usart

我在使用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;
}

配置和波特率是正确的,因为找到的here回显示例确实有效。

其他例子也没有使用UDRE,只有RX中断,这不是我要找的。

我忘记了什么吗?

1 个答案:

答案 0 :(得分:1)

两个问题:

  • 根据您链接的documentation,您的特定部分ATmega328p的中断向量应命名为USART_UDRE_vect

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