我试图将数组从 uart rx 保存到变量并将其发送到 tx,我不知道代码中的问题在哪里,也不知道数组是否保存在变量中,但我在终端中没有收到任何数据,可能是我缺少一些东西
.DSEG
.ORG 0X0100
STRNG: .BYTE 128 ;Strings recommended to be even
.CSEG
STRNG2: .DB "Printing aithing from probably the buffer",0X00 ;Strings recommended to be even
RJMP MAIN
MAIN: SBI DDRD,PD1
LDI R16,0X00
LDI R17,0XCF
STS UBRR0L,R17 ;UBRRXL - Usart Baud Rate 0 Register Low| Low byte of Baud Rate
STS UBRR0H,R16 ;UBRRXH - Usart Baud Rate 0 Register High| High 4bits of Baud Rate
LDI R18,0X22
STS UCSR0A,R18 ;UCSRXA - Usart Control and Status Register X A| flags, status and config: (flag after receive)(flag after transmit)(flag buffer data register empty[1 defaul])(flag frame error)(flag buffer overrun)(flag parity error)(U2XX state)(multiprocessor communication state) | set flags acording documentation (all in 0 except UDRE0)
LDI R19,0X06
STS UCSR0C,R19 ;UCSRXC - Usart Control and Status Register X C| flags, status and config: (Usart modes)(parity mode)(stop bits mode)(character size)(clock polarity[for USART])
LDI R20,0X18
STS UCSR0B,R20 ;UCSRXB - Usart Control and Status Register X B| config: (after receive interrupt)(after transmit interrupt)(buffer data register empty interrupt)(rx enable)(tx enable)(character size)(receive data bit 8[for 9bit])(transmit data bit 8[for 9bit])
LOOP: RJMP RX
RCALL WAITT
RJMP LOOP
RX: LDS R21,UCSR0A
SBRS R21,UDRE0
RJMP RX
LDI XL,LOW(STRNG) ;Z POINTER
LDI XH,HIGH(STRNG)
LDS R22,UDR0
CPI R22,0X0D
BREQ TX
LDI XL,LOW(STRNG) ;Z POINTER
LDI XH,HIGH(STRNG)
ST X+,R22
RJMP RX
TX: LDI XL,LOW(STRNG) ;Z POINTER
LDI XH,HIGH(STRNG)
LD R23,X+
CPI R23,0X00
BREQ END
SEND: LDS R21,UCSR0A
SBRS R21,UDRE0
RJMP SEND
STS UDR0,R23
RJMP TX
END: RET
WAITT: LDI R24, 82
LDI R25, 43
L1: DEC r25
BRNE L1
DEC r24
BRNE L1
RET
我不明白问题出在哪里
程序中的第一个问题是 AVR8 内核开始从地址 0 处的复位向量执行代码,但那里有字符串。 CPU 尝试执行其内容。 通常中断向量表位于地址0。如果您不打算使用中断,您可以将代码放在那里,但它必须从地址 0 开始。
第二个问题是您的代码通过测试
UDRE0
标志来等待来自 UART 的字符:
RX: LDS R21,UCSR0A
SBRS R21,UDRE0
UDREn:USART 数据寄存器空:UDREn 标志指示发送缓冲区 (UDRn) 是否已准备好接收新数据
您应该测试 RXC0 标志来检测字符接收:
RXCn:USART 接收完成:当接收缓冲区中有未读数据时该标志位被置位,当接收缓冲区为空时该标志位被清零
RX: LDS R21,UCSR0A
SBRS R21,RXC0
第三个问题是,您在每次迭代时初始化当前字符指针(X 寄存器),而且两次:在测试行尾之前和存储到缓冲区之前。
第四个问题是,在 STORE 函数中,您查找 NUL 终止符作为字符串的结尾,但从不存储它。
整个程序可能如下所示。我不知道 WAIT 函数的用途,所以将其删除。
.DEVICE "ATmega328P"
.DSEG
.ORG 0X0100
STRNG: .BYTE 128 ;Strings recommended to be even
.CSEG
MAIN: SBI DDRD,PD1
LDI R16,0x00
LDI R17,0xCF
STS UBRR0L,R17
STS UBRR0H,R16
LDI R18,0x22
STS UCSR0A,R18
LDI R19,0x06
STS UCSR0C,R19
LDI R20,0x18
STS UCSR0B,R20
LOOP: LDI XL,LOW(STRNG) ; Set string pointer to the beginning of buffer
LDI XH,HIGH(STRNG)
RX: LDS R21,UCSR0A
SBRS R21,RXC0 ; USART Receive Complete
RJMP RX
LDS R22,UDR0
CPI R22,0x0D ; End of line?
BRNE STORE ; No - store received character into buffer
LDI R22,0x00 ; Store NUL terminator
ST X+,R22
LDI XL,LOW(STRNG) ; Set string pointer to the beginning of buffer
LDI XH,HIGH(STRNG)
RJMP TX ; Print buffer content
STORE: ST X+,R22
RJMP RX
TX: LD R23,X+
CPI R23,0x00
BREQ LOOP ; Read next line
SEND: LDS R21,UCSR0A
SBRS R21,UDRE0
RJMP SEND
STS UDR0,R23
RJMP TX
我没有在真实硬件上测试它,但它确实可以在 QEMU 中工作。
优化提示:可以使用CR字符(0x0D)作为字符串终止符。在这种情况下,您不应存储 NUL 字符,而应在 SEND 中检查 CR:
...
RX: LDS R21,UCSR0A
SBRS R21,RXC0 ; USART Receive Complete
RJMP RX
LDS R22,UDR0 ; Store character into buffer
ST X+,R22
CPI R22,0x0D ; End of line?
BRNE RX ; No - receive next character
LDI XL,LOW(STRNG) ; Set string pointer to the beginning of buffer
LDI XH,HIGH(STRNG)
TX: LD R23,X+
CPI R23,0x0D ; End of line?
BREQ LOOP ; Read next line
SEND: LDS R21,UCSR0A
SBRS R21,UDRE0
RJMP SEND
STS UDR0,R23
RJMP TX