Embedded 如何修复此代码以允许我的AVR通过串行端口进行对话?

Embedded 如何修复此代码以允许我的AVR通过串行端口进行对话?,embedded,serial-port,avr,Embedded,Serial Port,Avr,最近我一直在努力让我的STK200上的ATmega162通过RS232与我的电脑通话。我检查并确保STK200包含MAX202CPE芯片 我已将芯片配置为使用其内部8MHz时钟,并将其除以8 我试图从数据表中复制代码(并在编译器抱怨的地方进行了更改),但没有效果 我的代码如下,有人能帮我解决我遇到的问题吗 我已经确认我的串行端口可以在其他设备上工作,并且没有故障 谢谢 #include <avr/io.h> #include <avr/iom162.h> #define

最近我一直在努力让我的STK200上的ATmega162通过RS232与我的电脑通话。我检查并确保STK200包含MAX202CPE芯片

我已将芯片配置为使用其内部8MHz时钟,并将其除以8

我试图从数据表中复制代码(并在编译器抱怨的地方进行了更改),但没有效果

我的代码如下,有人能帮我解决我遇到的问题吗

我已经确认我的串行端口可以在其他设备上工作,并且没有故障

谢谢

#include <avr/io.h>
#include <avr/iom162.h>

#define BAUDRATE 4800

void USART_Init(unsigned int baud)
{
    UBRR0H = (unsigned char)(baud >> 8);
    UBRR0L = (unsigned char)baud;

    UCSR0B = (1 << RXEN0) | (1 << TXEN0);

    UCSR0C = (1 << URSEL0) | (1 << USBS0) | (3 << UCSZ00);
}

void USART_Transmit(unsigned char data)
{
    while(!(UCSR0A & (1 << UDRE0)));

    UDR0 = data;
}

unsigned char USART_Receive()
{
    while(!(UCSR0A & (1 << RXC0)));

    return UDR0;
}

int main()
{

    USART_Init(BAUDRATE);

    unsigned char data;

    // all are 1, all as output
    DDRB = 0xFF;

    while(1)
    {
        data = USART_Receive();

        PORTB = data;

        USART_Transmit(data);


    }
}
#包括
#包括
#定义波特率4800
无效USART_Init(无符号整数波特)
{
UBRR0H=(无符号字符)(波特率>>8);
UBRR0L=(无符号字符)波特;

UCSR0B=(1我手头没有参考资料,但波特率寄存器UBRR通常包含一个除数值,而不是期望的波特率本身。a表示4800波特的正确除数值可能是239。请尝试:

divisor = 239;
UBRR0H = (unsigned char)(divisor >> 8);
UBRR0L = (unsigned char)divisor;

如果这不起作用,请查阅特定芯片的参考文档,以了解正确的除数计算公式。

我已经对格雷格的答案发表了评论,但想补充一点。对于这类问题,调试它的黄金标准方法是先了解异步串行通信,然后获得oscilloscope并查看线上发生的情况。如果正在交换字符,而这只是波特率问题,这将特别有用,因为您可以计算看到的波特率,然后相应地调整除数

这是一个超级快速入门,毫无疑问,你可以在维基百科或其他地方找到更全面的内容

假设8位,无奇偶校验,1个停止位(最常见的设置)

...--+   +---+---+---+---+---+---+       +---+--...
     | S | 1   1   1   1   1   1 | 0   0 | E
     +---+                       +---+---+
芯片的高(1)电平为+5V,转换为RS232电平后为-12V

芯片的低(0)电平为0V,转换为RS232电平后为+12V

S是起始位

然后我们有8个数据位,首先是最低有效位,所以这里00111111=0x3f='?'

E是停止(E表示结束)位

时间从左向右推进,就像示波器显示一样,如果波特率为4800,则每个位的跨度(1/4800)秒=0.21毫秒(约)


接收器的工作原理是对线路进行采样并寻找下降沿(静态线路始终只是逻辑“1”)。接收器知道波特率和起始位的数量(1),因此它从下降沿开始测量半位时间,以找到起始位的中间位置,然后依次对行进行8位采样以收集数据位。然后接收器再等待一个位时间(直到停止位的一半),并开始寻找另一个起始位(即下降沿)。同时,系统的其余部分可以读取字符。变送器保证在停止位完成之前,下一个下降沿不会开始。变送器可编程为始终等待更长时间(使用附加停止位)但这是一个遗留问题,只有在硬件和/或软件设置非常慢的情况下才需要额外的停止位。

在更彻底地阅读数据表后,我错误地设置了波特率。ATmega162数据表有一个时钟频率图表,该图表根据波特率和相应错误绘制

对于4800波特率和1MHz时钟频率,误差为0.2%,这对我来说是可以接受的。诀窍是将12传递给USART_Init()函数,而不是4800


希望这对其他人有所帮助!

对于调试UART通信,有两件有用的事情要做:

1) 在连接器上做一个回环,确保你能读回你写的内容。如果你发送一个字符并准确地取回,你就知道硬件接线正确,并且至少UART寄存器的基本配置是正确的


2) 重复发送字符0x55(“U”)-二进制位模式01010101将允许您快速查看示波器上的位宽度,这将让您验证速度设置是否正确。

我查找了一个我参与的旧AVR项目,最相关的代码行是;除数=(u16)(系统时钟/(波特率*16))-1;根据我的系统时钟频率计算,结果是191。根据你的,可能是13?。但格雷格的答案可能更准确。在这种情况下,芯片和时钟发生器的确切味道非常重要。第二种方法令人惊讶且有用。它还负责起始位和sop位。