我想制作一个中断驱动的uart程序,以绝对最小的cpu开销高速发送大量数据。我结合现有代码和数据表阅读来制作这段代码。它在Atmega88p(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
}
}
答案 0 :(得分:4)
根据数据表:
“当UCSRnB中的数据寄存器空中断使能(UDRIE)位时 写入'1',USART数据寄存器为空中断 只要UDRE设置为“
,就会执行
一旦启用中断,ISR就会被触发,从而跳过“H”。你有几个选择。 1)发送H后启用中断 2)只需使用ISR发送整个消息,包括H(例如,不要在主例程中发送任何内容。 3)使用Tramsmit Complete((TXC)中断。如果你使用它,在主程序中发送H,一旦传输,ISR将触发,你的ISR将发送剩余的消息。
最后,将“transmit_index&lt;(len + 1)”更改为transmit_index&lt; = len。没有必要在ISR中浪费指令
答案 1 :(得分:0)
在主循环中,更改此行:
transmit_index = 1;
这一行:
transmit_index = 0;
str [0] =&#39; H&#39;但你从索引[1] ...
开始