【发布时间】:2014-06-09 15:42:09
【问题描述】:
我想在 ATmega88-PA 上设置 UART。首先,我试图在 UDRE 寄存器上设置一个中断,但这不起作用,所以对于传输,我使用正常轮询。 因为代码不起作用,所以我从 0 开始使用基本程序。
#define F_CPU 1000000UL
#define USART_BAUDRATE 9600
#define BAUD_PRESCALE (((F_CPU / (USART_BAUDRATE * 8UL))) - 1)
char ReceivedByte = '#';
int main (void)
{
UCSR0A = (1 << U2X0);
/* Turn on the transmission and reception circuitry. */
UCSR0B = (1 << RXEN0) | (1 << TXEN0);
/* Use 8-bit character sizes. */
//UCSR0C = (1 << UCSZ00) | (1 << UCSZ01);
/* BAUD prescale */
UBRR0 = 12;
/* Load upper 8-bits of the baud rate value into the high byte of the UBRR register. */
//UBRR0H = (BAUD_PRESCALE >> 8);
/* Load lower 8-bits of the baud rate value into the low byte of the UBRR register. */
//UBRR0L = BAUD_PRESCALE;
UCSR0B |= (1 << RXCIE0);
sei();
DDRB |= 0x04;
PORTB &= ~0x04;
for (;;)
{
/* Do nothing until data have been received and is ready to be read from UDR. */
//while ((UCSR0A & (1 << RXC0)) == 0) {};
/* Fetch the received byte value into the variable "ByteReceived". */
//ReceivedByte = UDR0;
if(ReceivedByte == '1')
PORTB |=0x04;
else
PORTB &=~0x04;
/* Do nothing until UDR is ready for more data to be written to it. */
while ((UCSR0A & (1 << UDRE0)) == 0) {};
/* Echo back the received byte back to the computer. */
UDR0 = ReceivedByte;
}
}
ISR(USART_RX_vect)
{
ReceivedByte = UDR0;
}
并且代码正在运行,但是当我打开一个 arduino 串行监视器并将我的模块连接到该监视器时,我收到了我的可怜的 # 但有一些垃圾。并非所有时间,但大多数情况下,垃圾是 1 或 2 个字节。有人可以帮我吗?
编辑:当我从我的蓝牙数据发送到三星 Galaxy S3 时,数据是完美的......我不知道为什么在串行监视器上,以及使用相同的蓝牙向笔记本电脑发送数据时我有很多垃圾和数据。如果这对你有帮助 回答我的问题,会很棒。
编辑:抱歉忘记了最后一次编辑,它只发送一个字符,我改变了字符,还有垃圾。当我发送一个字符串是不可读的。
编辑:正如我在 embedded_guy 下面的帖子中发表的那样,我解决了在发送每个字节后插入 _delay_ms(1) 的问题。它现在正在工作。我相信这个说法
while ((UCSR0A & (1 << UDRE0)) == 0) {};
没有做它的工作。希望这对其他人有帮助。
【问题讨论】:
-
你收到的垃圾数据是在你的'#'之前还是之后?
-
我注意到它在 # 之后,我还通过蓝牙将数据发送到我的计算机,因为它比显示器更适合阅读。所以我从蓝牙模块收到#然后是垃圾,串行监视器也是如此
-
您的代码看起来像是您尝试实现数据表中的代码示例。然后破解了代码。许多被注释掉的代码行是必要的,不应被注释掉。
-
在数据表中说明了在字节传输后读取 I.O 缓冲区并指示传输完成的要求。我在您的代码中没有看到这一点。
-
看不到确凿证据,但我肯定会将
ReceivedByte声明为volatile。