C 在ATMEGA168A下理解UART

C 在ATMEGA168A下理解UART,c,avr,uart,atmega,C,Avr,Uart,Atmega,我试图创建一个C程序,它通过UART接收字符,通过打开我的实验板上的8个LED,“打印”相应的二进制文件,并将字符发送回发射器 以下是我正在使用的代码: //CPU clock #define F_CPU 1000000UL //Baud #define BAUD 9600 //Baud rate #define BAUDRATE ((F_CPU)/(BAUD*16UL)-1) #include <avr/io.h> #include <util/delay.h> #i

我试图创建一个C程序,它通过UART接收字符,通过打开我的实验板上的8个LED,“打印”相应的二进制文件,并将字符发送回发射器

以下是我正在使用的代码:

//CPU clock
#define F_CPU 1000000UL
//Baud
#define BAUD 9600
//Baud rate
#define BAUDRATE ((F_CPU)/(BAUD*16UL)-1)

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

//Communication Parameters: 
//8 bits of data
//1 bit stop
//No parity
void uart_init(void){

    //Bit 7 - RXCIEn: RX complete interrupt enable
    //Bit 6 - TXCIEn: TX complete interrupt enable
    //Bit 5 - UDRIE: USART data register empty interrupt enable
    //Bit 4 - RXENn: Receiver enable
    //Bit 3 - TXENn: Transmitter enable
    UCSR0B = 0b10011000;

    //Bit 7 - RXCn: USART receive complete.
    //Bit 6 - TXCn: USART transmit complete
    //Bit 5 - UDREn: USART data register empty
    UCSR0A = 0b00000000;


    //Bit 11:0 – UBRR11:0: USART baud rate register
    //Whereas H are the higher bits and L the lower bits
    //It comes from the setbaud.h
    UBRR0H = UBRRH_VALUE;
    UBRR0L = UBRRL_VALUE;

    //Bit 7:6 - UMSELn1:0: USART mode select
        //00    Asynchronous USART
        //01    Synchronous USART
        //11    Master SPI
    //Bit 5:3 - Reserved bits in MSPI mode
    //Bit 2 - UDORDn: Data order
    //Bit 1 - UCPHAn: Clock phase
    //Bit 0 - UCPOLn: Clock polarity
    UCSR0C = 0b10000110;
}

// function to send data
void uart_transmit (uint8_t data)
{
    while (!( UCSR0A & (1<<UDRE0)));            // wait while register is free
    UDR0 = data;                             // load data in the register
}

int main (void)
{
    //Starts UART
    uart_init();
    //All led GPIOs as output
    DDRB = 0xFF;
    DDRC = 0x01;
    //Enabling interrupts
    sei();

    while(1)
    {
        ;
    }

    return 0;
}

ISR(USART_RX_vect)
{
    //Variable to hold the incoming char
    uint8_t received_bit = UDR0;
    PORTC ^= 0x01;
    PORTB = 0x00;
    PORTB = received_bit;
    uart_transmit(received_bit);
}
//CPU时钟
#定义F_CPU 1000000UL
//波特
#定义波特率9600
//波特率
#定义波特率((F_CPU)/(波特率*16UL)-1)
#包括

关于ATMEGA168a下的UART,我的问题如下:

  • 设置F_CPU时,我是应该使用ATMEGA168a使用的1MHZ还是必须使用我的发射机(Intel i7)?这可能是问题所在吗
  • UDR0何时“更新”?每当我按下回车键通过终端将字符发送到芯片时
  • 是什么导致了这个问题

在函数
uart_init()
中,您将位
7:6
设置为
10
,根据ATMega 168A手册,这是一种保留状态。要获得所需的异步UART功能,请将其设置为
00

UCSR0C = 0b00000110;
您的示例不起作用的另一个原因是波特率设置,我在下面的评论中解释了这一点

您已经包含了
头文件,其中包含宏以简化UART设置。查找文档。这些宏接收您在
F_CPU
BAUDRATE
中提供的输入,并计算UART配置寄存器的设置(
UBRRH_值
UBRRL_值

您几乎正确地使用了它,但是为了利用ATmega的UART波特率倍增功能,请在设置UBRR0H/L值后添加以下代码:

#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif

因为这正是setbaud.h所做的。

在函数
uart_init()
中,您将位
7:6
设置为
10
,根据ATMega 168A手册,这是一种保留状态。要获得所需的异步UART功能,请将其设置为
00

UCSR0C = 0b00000110;
您的示例不起作用的另一个原因是波特率设置,我在下面的评论中解释了这一点

您已经包含了
头文件,其中包含宏以简化UART设置。查找文档。这些宏接收您在
F_CPU
BAUDRATE
中提供的输入,并计算UART配置寄存器的设置(
UBRRH_值
UBRRL_值

您几乎正确地使用了它,但是为了利用ATmega的UART波特率倍增功能,请在设置UBRR0H/L值后添加以下代码:

#if USE_2X
UCSR0A |= (1 << U2X0);
#else
UCSR0A &= ~(1 << U2X0);
#endif

因为这正是setbaud.h所做的。

刚刚注意到另一件事:您使用的CPU时钟为1 MHz,波特率为9600 bd。根据第187页的表20-4,这会给您-7.0%的定时误差。这可能是问题所在,所以也许可以尝试另一种波特率?谢谢乔。如果我把波特率设为1200,效果很好。是否可以使用更高的波特率值?如果可能的话,最好的方法是使用频率高于1MHz的晶体振荡器。另一种方法是将U2X0位设置为1,这将使UART波特率加倍。我将相应地更新我的答案。通过使用U2X0位,您可以使用1 MHz晶体实现9600 bd。刚刚注意到另一件事:您使用的CPU时钟为1 MHz,波特率为9600 bd。根据第187页的表20-4,这会给您一个-7.0%的定时误差。这可能是问题所在,所以也许可以尝试另一种波特率?谢谢乔。如果我把波特率设为1200,效果很好。是否可以使用更高的波特率值?如果可能的话,最好的方法是使用频率高于1MHz的晶体振荡器。另一种方法是将U2X0位设置为1,这将使UART波特率加倍。我会相应地更新我的答案。你可以通过使用U2X0位用一个1MHz晶体实现9600BD。