Serial port 从AVR USART传输读取的损坏数据

Serial port 从AVR USART传输读取的损坏数据,serial-port,avr,atmega,usart,Serial Port,Avr,Atmega,Usart,我在stk500开发板上有一个atmega162芯片,通过串行电缆连接到ubuntu。 在atmega上,我初始化usart并写入一些字节。在Ubuntu方面,有些东西是从管道中出来的,但它肯定不是发送的东西 更准确地说:对于发送的每个字节,我得到一系列大约6或7个字节,每个字节都有0x00或0xC0值 我的代码的相关片段: 编译标志: CFLAGS = -g CFLAGS += -mmcu=atmega162 CFLAGS += -W -Wall -Wshadow CFLAGS += -Os

我在stk500开发板上有一个atmega162芯片,通过串行电缆连接到ubuntu。 在atmega上,我初始化usart并写入一些字节。在Ubuntu方面,有些东西是从管道中出来的,但它肯定不是发送的东西

更准确地说:对于发送的每个字节,我得到一系列大约6或7个字节,每个字节都有0x00或0xC0值

我的代码的相关片段:

编译标志:

CFLAGS = -g
CFLAGS += -mmcu=atmega162
CFLAGS += -W -Wall -Wshadow
CFLAGS += -Os
CFLAGS += -mcall-prologues
CFLAGS += -finline-limit=10
CFLAGS += -mno-interrupts
CFLAGS += -ffunction-sections
CFLAGS += -DF_CPU=7372800ULL
usart功能:

void Serial0Init(int baud)
{
        unsigned int    ubrr;

        ubrr = ((F_CPU+8*baud)/(16*baud))-1;
        // Baud rate
        UBRR0H = (unsigned char)(ubrr>>8);
        UBRR0L = (unsigned char)ubrr;
        UCSR0A &= ~(1 << U2X0); // U2X off
        // Transmission settings
        UCSR0C = (1<<URSEL0)|(3<<UCSZ00);       // 8N1
        UCSR0B = (1<<RXEN0)|(1<<TXEN0);
}

unsigned char Serial0CheckTxReady()
{
        return (UCSR0A&_BV(UDRE0));     // nonzero if transmit register is ready to receive new data.
}

void Serial0Write(unsigned char data)
{
        while (Serial0CheckTxReady()==0)        // while NOT ready to transmit
                {}
        UDR0 = data;
}
我使用简单的python脚本接收数据:

import serial
import os

port = serial.Serial('/dev/ttyS0', 9600)

print 'Reading from serial...'
while True:
  c = port.read()
  print c, ord(c)
我仔细检查了字节大小设置和波特率计算,一切似乎都正常。。。知道我做错了什么吗?

据我所知(评论中已经怀疑),波特率计算是错误的。
试一试

结果是什么

UBRR = 47

对于9600@7372800MHz。

这个问题看起来肯定是波特率问题。您确定您的MCU正在以7.372 MHz的频率运行吗?我建议检查时钟源的保险丝设置。如果选择外部振荡器作为时钟源,则还应检查其设置(例如STK500时钟发生器频率)。同时检查Atmega161兼容性保险丝。只要您为Atmega162编译,应禁用兼容模式以防止可能的副作用。还应检查用于计算
ubrr
的表达式。当sizeof(int)==2时,其计算可能会导致溢出,从而导致不正确的结果。我建议为测试目的对
UBRR0
值进行硬编码。好的,您的提示非常有用。我发现了问题。这确实是波特率计算。固定公式如下所示:ubrr=((F_CPU+8*(长整数)波特)/(16*(长整数)波特))-1;换句话说,唯一的问题是隐藏到16位int的转换,这破坏了结果。问题不在于公式本身(我在avr库中找到它,所以我很确定它是可以的),而是转换到16位int。事实上,在转换到long int之后,我得了47分,一切都很好。@Bob:演员阵容是问题所在,你是对的,但是你等式中的(8*(长整数)波特)部分是错误的。然而,这并不是什么大问题,因为它只会产生47.5,由于整数除法,它会变成47。就像我说的:我在avr库中看到了这个技巧-它显然是用来将结果四舍五入到最接近的整数值。换句话说,它是圆形(ubrr)而不是地板(ubrr)。(事实上,当使用usart友好的时钟频率时,这并不重要)@Bob:好吧,这是有道理的。这里没有进一步的论证;)
UBRR = ((fOSC / (16 * BAUD)) - 1
UBRR = 47