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

发布于 2024-07-19 15:01:10 字数 1066 浏览 6 评论 0原文

最近,我一直在绞尽脑汁地尝试在 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);


    }
}

I've been pulling my hair out lately trying to get an ATmega162 on my STK200 to talk to my computer over RS232. I checked and made sure that the STK200 contains a MAX202CPE chip.

I've configured the chip to use its internal 8MHz clock and divided it by 8.

I've tried to copy the code out of the data sheet (and made changes where the compiler complained), but to no avail.

My code is below, could someone please help me fix the problems that I'm having?

I've confirmed that my serial port works on other devices and is not faulty.

Thanks!

#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);


    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

稚然 2024-07-26 15:01:10

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

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

我们假设 8 位、无奇偶校验、1 个停止位(最常见的设置)。 那么如果正在传输的字符是 0x3f (= ascii '?'),那么该行看起来像这样;

...--+   +---+---+---+---+---+---+       +---+--...
     | 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 位采样以收集数据位。 然后接收器再等待一个位时间(直到停止位的一半)并开始寻找另一个起始位(即下降沿)。 同时,读取的字符可供系统的其余部分使用。 发送器保证在停止位完成之前不会开始下一个下降沿。 发送器可以编程为始终等待更长的时间(使用额外的停止位),但这是一个遗留问题,只有非常慢的硬件和/或软件设置才需要额外的停止位。

I have commented on Greg's answer, but would like to add one more thing. For this sort of problem the gold standard method of debugging it is to first understand asynchronous serial communications, then to get an oscilloscope and see what's happening on the line. If characters are being exchanged and it's just a baudrate problem this will be particularly helpful as you can calculate the baudrate you are seeing and then adjust the divisor accordingly.

Here is a super quick primer, no doubt you can find something much more comprehensive on Wikipedia or elsewhere.

Let's assume 8 bits, no parity, 1 stop bit (the most common setup). Then if the character being transmitted is say 0x3f (= ascii '?'), then the line looks like this;

...--+   +---+---+---+---+---+---+       +---+--...
     | S | 1   1   1   1   1   1 | 0   0 | E
     +---+                       +---+---+

The high (1) level is +5V at the chip and -12V after conversion to RS232 levels.

The low (0) level is 0V at the chip and +12V after conversion to RS232 levels.

S is the start bit.

Then we have 8 data bits, least significant first, so here 00111111 = 0x3f = '?'.

E is the stop (e for end) bit.

Time is advancing from left to right, just like an oscilloscope display, If the baudrate is 4800, then each bit spans (1/4800) seconds = 0.21 milliseconds (approx).

The receiver works by sampling the line and looking for a falling edge (a quiescent line is simply logical '1' all the time). The receiver knows the baudrate, and the number of start bits (1), so it measures one half bit time from the falling edge to find the middle of the start bit, then samples the line 8 bit times in succession after that to collect the data bits. The receiver then waits one more bit time (until half way through the stop bit) and starts looking for another start bit (i.e. falling edge). Meanwhile the character read is made available to the rest of the system. The transmitter guarantees that the next falling edge won't begin until the stop bit is complete. The transmitter can be programmed to always wait longer (with additional stop bits) but that is a legacy issue, extra stop bits were only required with very slow hardware and/or software setups.

挽袖吟 2024-07-26 15:01:10

在更彻底地阅读数据表后,我错误地设置了波特率。 ATmega162 数据表有一张时钟频率与波特率和相应误差的图表。

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

希望这对其他人有帮助!

After reading the data sheet a little more thoroughly, I was incorrectly setting the baudrate. The ATmega162 data sheet had a chart of clock frequencies plotted against baud rates and the corresponding error.

For a 4800 baud rate and a 1 MHz clock frequency, the error was 0.2%, which was acceptable for me. The trick was passing 12 to the USART_Init() function, instead of 4800.

Hope this helps someone else out!

征棹 2024-07-26 15:01:10

我手边没有参考资料,但波特率寄存器 UBRR 通常包含一个除数值,而不是所需的波特率本身。 快速 Google 搜索表明 4800 波特率的正确除数值可能是 239。因此尝试:

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

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

I don't have reference material handy, but the baud rate register UBRR usually contains a divisor value, rather than the desired baud rate itself. A quick google search indicates that the correct divisor value for 4800 baud may be 239. So try:

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

If this doesn't work, check with the reference docs for your particular chip for the correct divisor calculation formula.

心碎无痕… 2024-07-26 15:01:10

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

1) 在连接器处进行环回,并确保您可以读回您写入的内容。 如果您发送一个字符并准确地返回它,您就知道硬件接线正确,并且至少 UART 寄存器配置的基本设置是正确的。

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

For debugging UART communication, there are two useful things to do:

1) Do a loop-back at the connector and make sure you can read back what you write. If you send a character and get it back exactly, you know that the hardware is wired correctly, and that at least the basic set of UART register configuration is correct.

2) Repeatedly send the character 0x55 ("U") - the binary bit pattern 01010101 will allow you to quickly see the bit width on the oscilloscope, which will let you verify that the speed setting is correct.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文