ATmega32A与PC的UART通信编程疑问:波特率寄存器配置代码解析
关于AVR USART初始化中UBRR寄存器赋值的疑问解答
嘿,作为AVR编程新手,啃数据手册时一头雾水太正常了!我来给你把这两行代码的作用讲得明明白白~
首先得搞清楚核心背景:AVR的USART通信波特率是由UBRR寄存器(USART波特率寄存器)决定的,这个寄存器本质是16位的,但AVR是8位内核,没法直接操作16位寄存器,所以厂商把它拆成了两个8位寄存器:UBRRH(高8位)和UBRRL(低8位)。你代码里的BAUD_PRESCALLER是根据单片机时钟频率和目标波特率计算出来的16位分频值,公式一般是:
#define BAUD_PRESCALLER ((F_CPU / (16 * BAUD_RATE)) - 1)
现在逐行解释你疑惑的代码:
UBRRH = (uint8_t)(BAUD_PRESCALLER>>8);
这行是把16位的BAUD_PRESCALLER向右偏移8位,相当于提取出它的高8位数据,然后通过(uint8_t)强制转换成8位类型,赋值给高字节寄存器UBRRH。举个例子,如果计算出的BAUD_PRESCALLER是0x1234(十进制4660),右移8位后就得到0x12,这就是要写入UBRRH的值。UBRRL = (uint8_t)(BAUD_PRESCALLER);
这行更直接:把16位的BAUD_PRESCALLER强制转换成8位类型时,会自动截断掉高8位,只保留低8位数据。还是用刚才的例子,0x1234转成uint8_t后就变成0x34,正好是要写入低字节寄存器UBRRL的值。
额外提个小细节:大部分AVR单片机要求先写UBRRH再写UBRRL,因为当你写入UBRRL的瞬间,整个16位的波特率计数器会被加载,所以你代码里的顺序是完全正确的~
内容的提问来源于stack exchange,提问作者Simon Maghiar




