【问题标题】:Having trouble setting up the UART on an AVR Atmega88-PA在 AVR Atmega88-PA 上设置 UART 时遇到问题
【发布时间】: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

标签: c avr avr-gcc


【解决方案1】:

我不知道这是否对你有用,但我确实只看到了一些可能成为问题的事情。

首先,我能找到的所有设置 BAUD 预分频器的示例都使用了两条指令,高低寄存器为UBRR0。如果您已经单步执行了代码并检查了该寄存器以确保其配置正确,那么这不是问题所在。否则,我建议将其设置为您在代码中设置的值:

UBRR0H = 12;
UBRR0L = 0;

我看到的另一件事是你从来没有设置UCSR0C。您已将其注释掉,我希望它能够在其默认(重置条件)设置下正常运行,但为了以防万一,明确说明总是好的。

最后,您可能想在Simple Serial Communications 上查看此页面。

编辑
根据您最近的编辑,我会将蓝牙从图片中删除。我建议将逻辑分析仪连接到微控制器的 UART 发送引脚,看看从 atmega 输出的数据是否符合您的预期。如果该数据很好,我将开始研究为什么蓝牙无法按预期工作。

【讨论】:

  • 我已经尝试了很多方法,包括那个方法。我还设置了 UCSR0C ,我认为这是寄存器的默认配置。感谢您的链接。
  • 感谢重播。不,问题不是蓝牙。昨天我的笔记本电脑蓝牙停止了。我试图重新安装驱动程序,但没有回答:))。所以我就像我说的那样使用三星银河。在花费了很多时间之后,我在每个字节发送后放置了一个 _delay_ms(1) 。神奇的是,现在一切正常。正如我所相信的那样:while ((UCSR0A & (1
  • 关于笔记本电脑的蓝牙,昨天我多次重启笔记本电脑,重新安装了我在互联网上找到的所有驱动程序,但什么也没有。今天我打开笔记本电脑,蓝牙工作正常。我相信微软必须更换一些工程师。
  • @Manu 您可以使用示波器或逻辑分析仪轻松验证微控制器的输出。然后您将确定您的代码是否按预期运行。之后,您可以开始对蓝牙和设备驱动程序进行故障排除。一开始就保持系统简单。在我看来,您正在调试功能代码,而问题出在其他地方……但您始终可以验证系统的 部分
  • 没错,只是一些调试。我让 USART 工作,但突然不工作了。所以我从模块测试开始。
【解决方案2】:

尝试使用至少 2MHz 的 F_CPU

【讨论】:

  • 尝试更具描述性。您可以对您的答案提供某种解释。
  • 当我使用 #define F_CPU 1000000UL 时,我的 UART 有一些问题,我的代码没有任何问题,但是当我将该行更改为 #define F_CPU 2000000UL 时,整个问题都得到了解决
【解决方案3】:

让你的 ReceivedByte 不稳定,试试这样:

volatile unsigned char ReceivedByte;

【讨论】:

    猜你喜欢
    • 2023-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-01
    • 2021-06-19
    • 1970-01-01
    • 2021-04-04
    • 2011-09-28
    相关资源
    最近更新 更多