assembly 保存数组或字符串并通过atmega328 p的uart汇编程序avr发送

uemypmqf  于 2023-10-19  发布在  其他
关注(0)|答案(1)|浏览(104)

Im试图保存一个数组从uart数据库到一个变量,并将其发送到tx,我不知道哪里是在代码中的问题,如果数组保存在变量,但im没有收到任何数据在终端,可能im错过了什么

.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

我不明白问题出在哪里

h5qlskok

h5qlskok1#

程序中的第一个问题是AVR8核心开始从地址0的重置向量执行代码,但那里有字符串。CPU尝试执行其内容。中断向量表通常位于地址0处。如果你不打算使用中断,你可以把你的代码放在那里,但它必须从地址0开始。
第二个问题是,您的代码通过测试UDRE 0标志来等待字符串:

RX:         LDS     R21,UCSR0A
            SBRS    R21,UDRE0

UDREn:USART数据寄存器为空:UDREn标志指示发送缓冲器(UDRn)是否准备好接收新数据
您应该测试RXC 0标志以检测字符接收:
RXCn:USART接收完成:当接收缓冲器中有未读数据时,设置该标志位,当接收缓冲器为空时,清除该标志位

RX:         LDS     R21,UCSR0A
            SBRS    R21,RXC0

第三个问题是你在每次迭代时初始化当前字符指针(X寄存器),而且是两次:在测试行尾之前和在存储到缓冲器之前。
第四个问题是,在STORE函数中,您将NUL终止符作为字符串的结尾,但从不存储它。
整个程序可以像下面这样。我不知道等待功能的目的,所以删除了它。

.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

相关问题