如何将 ATMEGA64a-au USART 速度设置为 115200?
How to set ATMEGA64a-au USART speed to 115200?
如标题所示,我有 ATMEGA64a-au 和 12mhz crystal,我通过这些代码将波特率设置为 9600:
#define F_CPU 12000000UL
#define FOSC 12000000 // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
..
void USART0_Init( unsigned int ubrr )
{
UBRR0H = (unsigned char) (ubrr >> 8);
UBRR0L = (unsigned char) ubrr;
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
// Set frame format: 8data, 1stop bit
UCSR0C = (1 << USBS0) | (3 << UCSZ00);
}
void USART1_Init( unsigned int ubrr )
{
UBRR1H = (unsigned char) (ubrr >> 8);
UBRR1L = (unsigned char) ubrr;
UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1);
// Set frame format: 8data, 1stop bit
UCSR1C = (1 << USBS1) | (3 << UCSZ10);
}
..
USART0_Init(MYUBRR);
USART1_Init(MYUBRR);
当我使用该波特率时很好,但我最近遇到了一个 115200bd 设备,我也需要将其更改为那个,但是当我更改此行时:
#define BAUD 115200
AVR 微控制器停止通信,我不知道如何修复它。是不是该设备太快了,还是我遗漏了什么?
#define MYUBRR FOSC/16/BAUD-1
首先这个公式有一个问题:它总是向下舍入。您需要将其四舍五入到接近整数,例如(FOSC / 16 + BAUD / 2) / BAUD-1
顺便问一下,为什么是 FOSC
而不是 F_CPU
?
反正你可以计算公式FOSC/16/BAUD-1
时的误差:
MYUBRR = 12000000/16/115200-1 = 5(5.51 向下舍入)
实际 UART 速度将为:
F_CPU / 16 / (MYUBRR + 1) = 12000000 / 16 / (5 + 1) = 125000
比要求高出 8.5%。接收器-发送器波特率差异超过 4.5% 的通信是不可能的。
但您可以设置双速运行模式 (参考数据表第25.3.2节)
可以通过设置 UCSRA
中的位 U2X
来完成。
在这种情况下,UART 时钟将是 CPU 时钟的 1/8,从而允许更高的 UBRR 设置:
// divide by 8, not 16
#define MYUBRR ((FOSC / 8 + BAUD / 2) / BAUD - 1)
...
void USART0_Init( unsigned int ubrr )
{
// you can just assign the value to UBRR, compiler will handle all the thighs
UBRR0 = ubrr;
UCSR0A = (1 << U2X0); // enable 2x mode
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
// Set frame format: 8data, 1stop bit
UCSR0C = (1 << USBS0) | (3 << UCSZ00);
}
在这种情况下 MYUBRR
值将是:
(12000000 / 8 + 115200 / 2) / 115200 - 1 = 12
实际 UART 速度为
12000000 / 8 / (12 + 1) = 115384,6
误差小于 0.2%
如标题所示,我有 ATMEGA64a-au 和 12mhz crystal,我通过这些代码将波特率设置为 9600:
#define F_CPU 12000000UL
#define FOSC 12000000 // Clock Speed
#define BAUD 9600
#define MYUBRR FOSC/16/BAUD-1
..
void USART0_Init( unsigned int ubrr )
{
UBRR0H = (unsigned char) (ubrr >> 8);
UBRR0L = (unsigned char) ubrr;
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
// Set frame format: 8data, 1stop bit
UCSR0C = (1 << USBS0) | (3 << UCSZ00);
}
void USART1_Init( unsigned int ubrr )
{
UBRR1H = (unsigned char) (ubrr >> 8);
UBRR1L = (unsigned char) ubrr;
UCSR1B = (1 << RXEN1) | (1 << TXEN1) | (1 << RXCIE1);
// Set frame format: 8data, 1stop bit
UCSR1C = (1 << USBS1) | (3 << UCSZ10);
}
..
USART0_Init(MYUBRR);
USART1_Init(MYUBRR);
当我使用该波特率时很好,但我最近遇到了一个 115200bd 设备,我也需要将其更改为那个,但是当我更改此行时:
#define BAUD 115200
AVR 微控制器停止通信,我不知道如何修复它。是不是该设备太快了,还是我遗漏了什么?
#define MYUBRR FOSC/16/BAUD-1
首先这个公式有一个问题:它总是向下舍入。您需要将其四舍五入到接近整数,例如(FOSC / 16 + BAUD / 2) / BAUD-1
顺便问一下,为什么是 FOSC
而不是 F_CPU
?
反正你可以计算公式FOSC/16/BAUD-1
时的误差:
MYUBRR = 12000000/16/115200-1 = 5(5.51 向下舍入)
实际 UART 速度将为:
F_CPU / 16 / (MYUBRR + 1) = 12000000 / 16 / (5 + 1) = 125000
比要求高出 8.5%。接收器-发送器波特率差异超过 4.5% 的通信是不可能的。
但您可以设置双速运行模式 (参考数据表第25.3.2节)
可以通过设置 UCSRA
中的位 U2X
来完成。
在这种情况下,UART 时钟将是 CPU 时钟的 1/8,从而允许更高的 UBRR 设置:
// divide by 8, not 16
#define MYUBRR ((FOSC / 8 + BAUD / 2) / BAUD - 1)
...
void USART0_Init( unsigned int ubrr )
{
// you can just assign the value to UBRR, compiler will handle all the thighs
UBRR0 = ubrr;
UCSR0A = (1 << U2X0); // enable 2x mode
UCSR0B = (1 << RXEN0) | (1 << TXEN0) | (1 << RXCIE0);
// Set frame format: 8data, 1stop bit
UCSR0C = (1 << USBS0) | (3 << UCSZ00);
}
在这种情况下 MYUBRR
值将是:
(12000000 / 8 + 115200 / 2) / 115200 - 1 = 12
实际 UART 速度为
12000000 / 8 / (12 + 1) = 115384,6
误差小于 0.2%