嗨,我一直在尝试使用 Atmel studio 6.1 实现串行通信和一个ATMEGA32 MCU。我阅读了数据表和帖子:ATMEGA32 UART通信
我想我或多或少得到了它应该如何设置,但我无法做到。我将 URSEL 的值设置为 1 以便写入它,但是当我运行模拟时,它似乎没有写入它,当我向它写入 0 并写入 UBRRH 时,我可以看到 UCSRC 和 UBRRH 都是用相同的值写入的。
这是代码的副本...
jmp RESET
RESET:
ldi r16, $12
out UCSRA, r16
ldi r17, $00
ldi r16, $47
out UBRRL, r16
out UBRRH, r17
; Enable receiver and transmitter
ldi r16, (1<<RXEN) | (1<<TXEN)
out UCSRB, r16
; Set frame format: 8 data, 1 stop bit
ldi r16, (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)
out UCSRC, r16
ldi r16, $80
ldi r17, (0<<URSEL)
out UBRRH, r17
loop:
ldi r16, $41
jmp TX
TX:
sbis UCSRA, UDRE
rjmp TX
;move data to the buffer
out UDR, r16
jmp loop
感谢您的帮助!
我可以看到您的代码中存在一些不一致之处。您是否认真阅读了 Atmega32 数据表,尤其是有关 USART 模块 SFR 的部分?
ldi r16, $12
out UCSRA, r16
为什么要在UCSRA中设置FE位(位4)?这是只读位,数据表说:"总是写入 UCSRA 时将此位设置为零。UCSRA 的初始值是 0x20,只有位 0、1 和 6 是 R/W,所以写0x22给 UCSRA 设置 U2X 位(我认为这是你的意图)。
ldi r16, $80
ldi r17, (0<<URSEL)
out UBRRH, r17
我不完全理解上面的几行。你正在 r16 中写一些东西,但从不使用它(你在下一行为 r16 写另一个字符)。接下来,您将 0 写入 r17(0<<URSEL
给出 r17=0x00),并将其存储在 UBRRH 中。为什么?你写0x00给UBRRH上面的几行。只有当您想在UBRRH或UBRSC中存储某些内容时,您才需要更改URSEL。所以这3行毫无意义。
init USART 和在循环中发送字符的代码应如下所示:
INIT:
ldi r16, $22
out UCSRA, r16
ldi r17, $00
ldi r16, $47
out UBRRL, r16
out UBRRH, r17
ldi r16, (1<<RXEN) | (1<<TXEN)
out UCSRB, r16
ldi r16, (1<<URSEL)|(1<<UCSZ0)|(1<<UCSZ1)
out UCSRC, r16
LOOP:
ldi r16, $41
TX:
sbis UCSRA, UDRE
rjmp TX
out UDR, r16
rjmp LOOP
如果您正在使用模拟工具,请注意 - 它们有时会显示毫无意义的结果,如果您真的不了解处理器内部发生了什么,请不要相信。