AVR UART 接收到错误的字节

Posted

技术标签:

【中文标题】AVR UART 接收到错误的字节【英文标题】:AVR UART receives wrong bytes 【发布时间】:2015-06-27 17:26:08 【问题描述】:

在长时间的停顿后,我再次开始对 AVR 进行编程。我能够在我的 Linux 计算机和 Atmega8 之间设置 UART 通信。不幸的是,当我发送大于0x1f 的字节时,Atmega8 似乎收到了错误的字节。 UART 以 9600 波特率和 8N1 数据格式运行。

// clock frequency 1Mhz 
#define F_CPU 1000000UL

// baud rate
#define BAUD 9600
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1)

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdlib.h>


void uart_init (void);
void uart_putc (unsigned char data);
void uart_puts (unsigned char * str, uint8_t size);

// interrupt service routine for UART receiver interupt
ISR(USART_RXC_vect) 

    // get received char
    unsigned char received_char = UDR;

    uart_puts("received=", 9);

    if((received_char & (1<<7)) == (1<<7)) 
        uart_putc('1');
     else 
        uart_putc('0');
    

    if((received_char & (1<<6)) == (1<<6)) 
        uart_putc('1');
     else 
        uart_putc('0');
    

    if((received_char & (1<<5)) == (1<<5)) 
        uart_putc('1');
     else 
        uart_putc('0');
    

    if((received_char & (1<<4)) == (1<<4)) 
        uart_putc('1');
     else 
        uart_putc('0');
    

    if((received_char & (1<<3)) == (1<<3)) 
        uart_putc('1');
     else 
        uart_putc('0');
    

    if((received_char & (1<<2)) == (1<<2)) 
        uart_putc('1');
     else 
        uart_putc('0');
    

    if((received_char & (1<<1)) == (1<<1)) 
        uart_putc('1');
     else 
        uart_putc('0');
    

    if((received_char & (1<<0)) == (1<<0)) 
        uart_putc('1');
     else 
        uart_putc('0');
    

    uart_puts("\n\r",2);



// function to initialize UART
// dataformat 8N1
void uart_init (void) 

    // shift the register right by 8 bits
    UBRRH = (BAUDRATE>>8);

    // set baud rate
    UBRRL = BAUDRATE;            

    // enable receiver, transmitter and receiver interrupt
    UCSRB|= (1<<TXEN)|(1<<RXEN)|(1<<RXCIE);

    // 8bit data format
    UCSRC|= (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1);   



// sends a single char over the UART
void uart_putc (unsigned char data) 

    // wait while register is free
    while (!( UCSRA & (1<<UDRE)));
    // load data in the register
    UDR = data;


// sends a string over the UART
void uart_puts (unsigned char * str, uint8_t size) 

    uint8_t i; 

    for(i = 0; i < size; i++) 
        uart_putc(str[i]);
    


// receives a single char over the UART
unsigned char uart_getc (void) 

    // wait while data is being received
    while(!(UCSRA) & (1<<RXC));
    // return 8-bit data
    return UDR;



uint8_t main (void) 

    // enable interrupts
    sei();

    // enable uart
    uart_init(); 

    uart_puts("ready\n\r", 7);

    while(1) 
     

    return 0; 

在 GtkTerm 中,我发送以下字节序列:0x010x020x030x1d0x1e0x1f0x20 和中断服务例程 ISR 以以下序列响应。

但是,我应该收到 0x20 的 received=00100000 怎么了?

【问题讨论】:

可能由于使用了较慢的时钟速率/内部 RC 振荡器而导致波特率关闭?您应该“测试”更多的值并查看是否存在模式。根据您提供的信息,很难缩小范围。 谢谢。实际上是低频率(1MHz)导致数据损坏。我切换到 8MHz 和 19200 的波特率。 啊,太好了,我一针见血了:) 你应该把这个问题标记为完成。然后将其从未决问题列表中删除。 【参考方案1】:

来自我的评论:

可能由于使用了较慢的时钟速率/内部 RC 振荡器而导致波特率关闭?波特率越慢,每个位的“中间”偏移就越大。这可能导致跳过位或控制器看到位两次。

【讨论】:

以上是关于AVR UART 接收到错误的字节的主要内容,如果未能解决你的问题,请参考以下文章

为啥 UART w/DMA 只接收发送数据的最后一个字节?

QEMU 的 UART 驱动程序接收“删除”字节而不是“退格”

uart接收和发送数据

AVR单片机教程——串口接收

如何为 UART 传输设置消息的开始字节

STM32 硬件UART接收超时检测设置