AVR - 高速中断驱动的 UART 代码不工作

AVR - High speed interrupt driven UART code not working

我想制作一个中断驱动的 uart 程序,以绝对最小的 cpu 开销高速发送大量数据。我结合现有代码和数据表的阅读来制作这段代码。它在 atmega328p (Atmega328p Xplained Mini) 上的 Atmel Studio 7 中编译时没有错误或警告。

我遇到的问题是数据不稳定,有时会发送 'ello!' 有时一段时间什么也没有。 'H' 经常被跳过,我不明白这一点,因为 ISR 不应该在 'H' 从 UDR0 复制到要发送之前执行。

如有任何帮助,我们将不胜感激!

你好,

伯特

#define F_CPU 16000000

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <string.h>

volatile uint8_t transmit_index = 0;
volatile char str[] = "Hello!\n";
volatile uint8_t len = 6;

int main(void){
    UCSR0A = 0b00000010;
    UCSR0B = 0b00111000;
    UCSR0C = 0b00000110;

//9600 baud
    UBRR0L = 207; 
    UBRR0H = 0;

    DDRD |= 0x02;

    sei();

    //Flash led
    DDRB |= 0b00100000;
    PORTB |= 0b00100000;
    _delay_ms(1000);
    PORTB &= ~0b00100000;
    _delay_ms(1000);

    while (1){  
        transmit_index = 1;

        //Enable udre interrupt
        UCSR0B |= 0b00100000; //enable interrupt

        //Send first byte in main()
        while (!(UCSR0A & 0b00100000)) {} //Wait for register empty
        UDR0 = str[0]; //send first byte

        _delay_ms(1000);
    }
}

ISR(USART_UDRE_vect) {
    //Buffer empty, ready for new data
    if (transmit_index < (len + 1)) {
        UDR0 = str[transmit_index];
        transmit_index++;
    } else {
        UCSR0B &= ~0b00100000; //disable interrupt
    }
}

根据数据表:

"When the Data Register Empty Interrupt Enable (UDRIE) bit in UCSRnB is written to '1', the USART data register empty interrupt will be executed as long as UDRE is set"

一旦启用中断,ISR 就会被触发,从而跳过 "H"。你有几个选择。 1) 发送 H. 2) 只需使用 ISR 发送整个消息,包括 H(例如,不要在主例程中发送任何内容。 3)使用Tramsmit Complete((TXC)中断。如果你使用这个,在主程序中发送H,一旦传输,ISR将触发,你的ISR将发送剩余的消息。

最后,将 "transmit_index < (len + 1)" 更改为 transmit_index <= len。无需在 ISR

中浪费指令

在您的主循环中,更改此行:

transmit_index = 1;

对于这一行:

transmit_index = 0;

str[0] = 'H' 但您从索引 [1] 开始...