保存数组或字符串并使用atmega328p通过uart汇编器avr发送

问题描述 投票:0回答:1

我试图将数组从 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

我不明白问题出在哪里

assembly avr uart atmega
1个回答
0
投票

程序中的第一个问题是 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
© www.soinside.com 2019 - 2024. All rights reserved.