所以我一直在尝试让 UART 在 ATMEGA8535 上工作,但遇到了一些问题。设置如下:当 ATMEGA 在自定义 pcb 上时,我需要 UART 工作。这不起作用,所以回到一个裸露的面包板,ATMEGA 只连接到 GND 和 5V。 TX 引脚连接到示波器以监控其输出。这是芯片上的代码:
#define F_CPU 1000000UL //CPU frequency
#include <xc.h>
#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#define BAUD 19200 // baud
#define BRC ((F_CPU/16/BAUD) - 1)
int main(void) {
/* Set baud rate */
UBRRH = (BRC >> 8);
UBRRL = BRC;
/* Enable receiver and transmitter */
UCSRB = (1<<RXEN)|(1<<TXEN);
/* Set frame format: 8data*/
UCSRC = (1<<UCSZ1)|(1<<UCSZ0);
while(1){
UDR = 'b';
_delay_ms(2000);
}
}
虽然示波器显示发送了正确的信号,但速度很慢:整个信号需要超过 200 毫秒。相比之下,对于设置为相同波特率的 Arduino,它需要不到 1 毫秒的时间。我检查了芯片是否有故障,但五个不同的 ATMEGA8535 给出了相同的输出。查看数据表时,我没有看到任何可能导致时钟生成出现如此大错误的情况。关于这个问题的起源和解决方案有什么想法吗?
您没有正确设置 UCSRC 注册。对于这种 MCU 类型,该寄存器的地址与 UBRRH 相同。如果要写入 UCSRC 寄存器,则必须将第八位设置为 1。因此,您的代码保存的不是 UCSRC,而是 UBRRH。这意味着 UBRRH 值被覆盖。
看看DS
Bit 7 – URSEL:寄存器选择 该位在访问 UCSRC 或 UBRRH 寄存器之间进行选择。它被读作 阅读 UCSRC 时的一个。写UCSRC时URSEL必须是一个。
UCSRC 的正确写法是:
/* Set frame format: 8data*/
UCSRC = (1<<UCSZ1)|(1<<UCSZ0)|(1<<URSEL);
第 163 页讨论 UCSRC怎么写