Läsa från SRAM på AVR? Ut på display?

PIC, AVR, Arduino, Raspberry Pi, Basic Stamp, PLC mm.
Glattnos
Inlägg: 3106
Blev medlem: 29 oktober 2009, 20:01:18

Läsa från SRAM på AVR? Ut på display?

Inlägg av Glattnos »

Jag kan inte komma på hur jag ska göra om jag vill skriva ut en textsträng, som ligger i SRAM, på en (standard)display.

Jag kan skriva ut en sträng som är sparad i Program-minnet(Anna är SNYGG!). Hela programmet är inte med(så det kanske inte funkar som det är nu)men det viktiga(för frågeställningen) är med.

Kod: Markera allt

.NOLIST
.INCLUDE	"m168def.inc"
.LIST
;-----------------------------------------------------------------------------------------------
.DEF	LPMdata			= r0		;Register för data som läses med "lpm"
.DEF	temp			= r16		;Temporärt register
.EQU	EOL				= 0				;End Off Line
;-----------------------------------------------------------------------------------------------
.MACRO PRINT_TEXT
	ldi	ZL, LOW(@0*2)
	ldi	ZH, HIGH(@0*2)
	rcall Print_data
.ENDMACRO
;-----------------------------------------------------------------------------------------------
.DSEG
.ORG 0x100
	Val:		.BYTE 70
;-----------------------------------------------------------------------------------------------
.ORG PMSTART
	Text1: .DB" Anna ", 0b11100001, "r SNYGG!", EOL		; 16 bytes
;-----------------------------------------------------------------------------------------------
Main:
	rcall	Print_init
	PRINT_TEXT Text1
	rcall	Delay

	rjmp	Main					;Börja om på Main
;-----------------------------------------------------------------------------------------------
Print_Data:
	ldi		temp, WRITE_DATA		;Sätt 3-ledningsbussen för sändning
	out		LCD_set, temp			;
Print_Next:
	lpm								;Hämta tecken från PM (r0 <- @Z)
	mov		temp, LPMdata
	out		LCD_data,temp
	cpi		temp, EOL				;Om detta tecken är lika med EOL...
	breq	Print_Done				;...hoppa till "Print_Done...
	rcall	SEND					;...annars, sänd LCD_data till Displayen
	adiw	ZL, 1					;Addera registerpar med direktdata (flyttar Z-pekare)
	rjmp	Print_Next				;Skicka nästa tecken
Print_Done:
	ret								;EOL(End Off Line), Returnera
Om jag vill skriva ut de 70 byte som är lagrat i variabeln "Val" i SRAM. Hur gör jag då?
Jag kan ju inte bara skriva "PRINT_TEXT Val" för då laddas väl Z med adressen till "Val" i SRAM och sedan läser LPM den adressen, fast i Flash-minnet.

Sen en liten fråga till: Varför måste man ladda Z med adressen Text1 och sedan ta det gånger två"(@0*2)"? Är är själva "Text1" en byte också eller hur ligger det till?
Användarvisningsbild
jesse
Inlägg: 9240
Blev medlem: 10 september 2007, 12:03:55
Ort: Alingsås

Re: Läsa från SRAM på AVR? Ut på display?

Inlägg av jesse »

Adressen som du skickar till macrot är en flashminne-adress. i AVR så ligger det 16 bitar i varje adress. För att få adressen till en 8-bitars byte i flashminnet behöver adressen multipliceras med två för att hamna rätt. Detta för att när du ska läsa nästa tecken (ADIW ZL,1) så tar du 8 bitar åt gången. Det lagras alltså två tecken på samma adress i flashminnet. Den lägsta biten i Z-registret avgör vilket av de två du ska läsa.

Du har ju skrivit en rutin ( Print_data ) som skriver ut från flashminnet. Om du vill skriva ut från SRAM måste du skriva en annan, separat rutin som gör det ( Print_SRAM ) . Ett alternativ (om det skulle visa sig vara effektivare?) kan ju vara att du inne i Print_data läser av en flagga och väljer att läsa antingen från flash eller SRAM beroende på flaggan. Då måste du först sätta flaggan rätt innan du anropar rutinen. Och så får du inte multiplicera adressen med 2, för i SRAM så stämmer den adress du får från labeln "Val".
Glattnos
Inlägg: 3106
Blev medlem: 29 oktober 2009, 20:01:18

Re: Läsa från SRAM på AVR? Ut på display?

Inlägg av Glattnos »

Jesse: Tack för svaret! Nu fattar jag i alla fall lite mer. Jag lyckades nu tack vare dig. Koden blir då typ såhär:

Kod: Markera allt

.NOLIST
.INCLUDE   "m168def.inc"
.LIST
;-----------------------------------------------------------------------------------------------
.DEF   LPMdata         = r0      ;Register för data som läses med "lpm"
.DEF   temp         = r16      ;Temporärt register
.EQU   EOL            = 0            ;End Off Line
;-----------------------------------------------------------------------------------------------
.MACRO PRINT_SRAM
	ldi	ZL, LOW(@0)
	ldi	ZH, HIGH(@0)
	rcall Print_data_SRAM
.ENDMACRO
;-----------------------------------------------------------------------------------------------
.DSEG
.ORG 0x100
   Val:      .BYTE 70
;-----------------------------------------------------------------------------------------------
.ORG PMSTART
   Text1: .DB" Anna ", 0b11100001, "r SNYGG!", EOL      ; 16 bytes
;-----------------------------------------------------------------------------------------------
Main:
   rcall   Print_init
	PRINT_SRAM Val
   rcall   Delay

   rjmp   Main               ;Börja om på Main
;-----------------------------------------------------------------------------------------------
Print_data_SRAM:
	ldi		temp, WRITE_DATA		;Sätt 3-ledningsbussen för sändning
	out		LCD_set, temp			;
Print_Next_SRAM:
	ld		temp, Z+				;Ladda temp och flytta pekare
	out		LCD_data,temp
	cpi		temp, EOL				;Om detta tecken är lika med EOL...
	breq	Print_Done_SRAM			;...hoppa till "Print_Done...
	rcall	SEND					;...annars, sänd LCD_data till Displayen
	rjmp	Print_Next_SRAM				;Skicka nästa tecken
Print_Done_SRAM:
	ret								;EOL(End Off Line), Returnera
Skriv svar