AVR USART能否设置不同波特率?接收9600发送300需求咨询
AVR USART实现不同波特率收发的方法
当然可以!AVR的USART模块完全支持在收发过程中切换不同的波特率,完美匹配你“用9600波特率接收PC数据、切换到300波特率向其他设备发送”的需求,具体实现有两种思路,我给你拆解下:
方法一:单USART动态切换波特率
这是最常用的方案(适合只有一个USART端口的AVR型号),核心逻辑是:波特率由UBRR寄存器(部分型号分为UBRRH和UBRRL)和波特率倍增位U2X决定,我们只需要在收发操作间隙修改这些寄存器的值,就能切换波特率。
关键步骤:
- 初始化接收波特率:先把USART设置为9600波特率,开启接收功能,等待PC数据。
- 接收完成后切换波特率:确认当前接收操作完成(清空接收缓冲区),修改
UBRR和U2X的值,切换到300波特率。 - 发送完成后切回原波特率:发送数据到其他设备后,再切换回9600波特率,等待下一次PC数据。
代码示例(以16MHz晶振为例)
#include <avr/io.h> // 初始化USART为9600波特率(用于接收PC数据) void init_usart_9600() { // 计算UBRR值:(16000000/(16*9600)) - 1 ≈ 103 UBRRH = (uint8_t)(103 >> 8); UBRRL = (uint8_t)103; UCSRA &= ~(1 << U2X); // 关闭波特率倍增 UCSRB |= (1 << RXEN) | (1 << TXEN); // 开启接收、发送功能 UCSRC |= (1 << URSEL) | (1 << UCSZ1) | (1 << UCSZ0); // 8位数据位、1停止位、无校验 } // 切换到300波特率(用于向其他设备发送) void switch_to_300_baud() { // 确保当前收发操作完成,避免数据丢失 while (!(UCSRA & (1 << UDRE))); // 等待发送缓冲区为空 while (UCSRA & (1 << RXC)) { UDR; } // 清空接收缓冲区残留数据 // 计算300波特率的UBRR值:(16000000/(16*300)) -1 ≈ 3332 UBRRH = (uint8_t)(3332 >> 8); UBRRL = (uint8_t)3332; UCSRA &= ~(1 << U2X); } // 切换回9600波特率(继续接收PC数据) void switch_back_to_9600() { while (!(UCSRA & (1 << UDRE))); // 等待发送完成 UBRRH = (uint8_t)(103 >> 8); UBRRL = (uint8_t)103; UCSRA &= ~(1 << U2X); } // 主逻辑示例 int main(void) { init_usart_9600(); while(1) { // 等待接收PC数据 while (!(UCSRA & (1 << RXC))); uint8_t received_data = UDR; // 切换到300波特率发送 switch_to_300_baud(); UDR = received_data; // 发送接收的数据 while (!(UCSRA & (1 << UDRE))); // 等待发送完成 // 切回9600波特率,准备下一次接收 switch_back_to_9600(); } }
方法二:双USART端口分别设置(如果硬件支持)
如果你的AVR型号有两个USART端口(比如ATmega2560有2个,ATmega328P仅1个),可以直接给两个USART分别设置不同波特率:
- USART0设置为9600波特率,专门接收PC数据
- USART1设置为300波特率,专门向其他设备发送数据
这种方案不需要切换波特率,逻辑更简单,适合有多余USART端口的场景。
注意事项
- 切换波特率时一定要等待当前的收发操作完成,否则会导致数据损坏或丢失
- 波特率计算要结合你的AVR晶振频率,不同晶振对应的
UBRR值不同,可以用AVR官方的波特率计算器辅助计算
内容的提问来源于stack exchange,提问作者Ganesh S
相关产品推荐
相关产品推荐

