Hallo,
ich steuere im Moment ein Grafik-Display an. Dort sind keine
ASCII-Zeichen definiert, also habe ich mir sämtliche ASCII-Zeichen
selbst gebastelt. Das funktioniert auch wunderbar.
Das Problem: Der Speicher. Im Moment benötigen alle Zeichen ca. 12 KB.
Das ist viel zu viel für meinen 2313. Ich habe für jedes Zeichen eine
eigene "Prodzedur", also recht uneffizient.
Jedes einzelne ASCII-Zeichen besteht aus 6 Byte. 256 Zeichen x 6 Byte
macht also 1536 Byte.
Nun meine Idee: Ich möchte irgendwo einen speziellen Speicherbereich
haben (z.B. 0x0300) und ab da stehen einfach alle
ASCII-Zeichen-Definitionen nach einnander. Möchte ich also das
ASCII-Zeichen 3, so lese ich die Speicherstellen 0x0312-0x0317. Das
denke ich, müßte das Platzsparendste sein.
Natürlich könnte ich auch einen Mega nehmen, das wäre aber a) zu teuer
und b) Verschwendung.
Noch eine kleine Frage nebenbei: Wenn der AVR-Compiler sagt, mein
Programm habe 390 Worte, sind das dann 780 Byte Speicherplatz?!?
Vielen Dank!
Sebastian
Hi Christian,
danke für den Link! :-)
Leider hat mir das noch nicht wirklich weitergeholfen. Ich will nichts
mit dem EEPROM machen (eh zu klein).
Weiß denn niemand wie man eine Lookup-Tabelle in Assembler
programmiert?!?
Und könnte mein Trick mit der Speicheradresse (siehe oben!) nicht
funktionieren?!?
Ich brauche Eure Hilfe! Danke!!!
Sebastian
Hi,
da ohnehin um "Read only" Daten geht und Du für
einzelne Pixelansteuerung auch einigen Platz
brauchst, empfehle ich ein I2C EEPROM wie das 24C64 oder 24C128. So ein
Baustein ist relativ schnell
auszulesen (wenns nur ums Lesen geht) und die
Ansteuerpins belegen auch nur 2 Portleitungen.
mfg wolli_r ( www.tec-shop.de )
Hi wolli_r,
danke erstmal für die Antwort! :-)
Die Idee ist nicht schlecht und notfalls werd ich's auch so machen. Nur
wollte ich so wenig externe Komponenten wie möglich verwenden
(Platzproblem trotz SMD).
Der interne Speicher sollte ja auch reichen. Gibt es denn keinen Befehl,
der sagt "springe zu 0x468"?!?
Danke!
Sebastian
Ich glaube, da mußt Du in Assembler programmieren, um alles in 2kB zu
quetschen.
In C kann man auch Tabellen auslesen, aber da ist der Overhead zu groß.
Ich hab mal eine LED-Zeile (16*5*7) mit nem 2313 angesteuert, die 2kB
sind zum bersten voll.
Anbei die Routine zum Auslesen eines Zeichens in den Display-RAM.
Peter
Hallo, ich mache es immer so
Daten:
.db 255,128,88,77
.db 88, 56, , 44,41
.
.
.
dann gibt dir Lpm die Daten zurück für die adr. die im Z-Pointer steht.
ldi ZH,high(Daten*2)
ldi ZL,low(Daten*2)
Lpm
;; in r0 steht jetzt 255
wenn du den z+ nimmst und wieder lpm ausführst steht in r0 128 ....
MfG
Sebastian
.. nachtrag,
wenn du jetzt Einzelne grupen definieren willst brauchst du ja nur noch
relativ zu "Daten" de Offsets angeben und dann zum Z Pointer zu
addieren.
@verrücktes Pferd,
stimmt, nur die Tabelle allein bringt keinen großen Overhead.
Das sind die einzelnen Unterfunktionen, die soviel Platz benötigen.
Außer dem profanen Schreiben eines Zeichens an eine bestimmte Stelle hab
ich noch das Reinscrollen von rechts, links, oben, unten, für einzelen
Zeichen oder Pixel oder Texte.
Ich hab das z.B. als Uhr, wo die Ziffern einzeln von oben runterfallen,
etwas zutief und dann wieder zurückschnappen.
Dann noch eine Art Interpreter, d.h. die Texte und die Kommandos, wie
diese darzustellen sind, kommen über die UART von dem Haupt-MC.
Und damit habe ich in Assembler den Rest der 2kB völlig zugestopft.
Der RAM ist dabei nur Bildspeicher und Eingabepuffer, alle anderen
Variablen sind ausschließlich in den 32 Registern.
Teilweise sind die Register einzelnen Funktionen exclusiv zugeordnet um
selbst an PUSH und POP soviel wie möglich zu sparen.
Ein 20-Pinner mit 8KB wie die von Philips wäre wirklich dringend nötig.
Peter
Hallo,
wenn du die Tabels für die zeichen schon im AVR hast , sollte es doch
kein problem sein wenn man die daten geschickt anordnet mit einer
kleinen rechenroutine ein pixelgenaues scrolling oder moving zu
realiesieren du musst halt mit variablen offsets in den bitmasken der
zeichen arbeiten. genauso für das erzeugen der zeichen,.. wenn man zb.
bar graphen erzeugt kann man die ausrechen und zr laufzeit erstellen da
brauch man nur etwas rechenleistung und geht unter umständen sogar etwas
schneller, is aber mit mehr denksport verbunden.
Aber 2kb sind doch etwas arg wenig für deine aufgaben, und ein größerer
avr is ja auch nicht unbedingt teuer.
MfG
Sebastian
//www.mcu-design.de//
Hallo,
danke erstmal für alle Antworten!!! :-))
@Peter: Das sieht genau nach dem aus, was ich mir vorstelle! Kannst Du
eventuell das ganze Programm posten?
@Sebastia(n): Perfekt! Ich möchte auf alle Fälle sowieso in Assembler
bleiben. Notfalls nehm' ich auch einen 4433, an dem soll's auch nicht
liegen. Ich möchte nur keine 14KB vollknallen, denn die
Display-Ansteuerung macht nur einen kleinen Teil des kompletten
Programms aus.
Ich werd' das ganze nun mal ausprobieren und melde mich dann wieder.
Auf alle Fälle schonmal vielen Dank!!! :-)
Viele Grüße,
Sebastian
Hi Sebastian,
nochmal eine kurze Frage zu Deinem Beispiel.
Also:
ldi ZH,high(Daten*2)
ldi ZL,low(Daten*2)
Lpm
gibt mir 255.
Was genau heißt Z+?
ldi ZH,high(Daten*2)+1
ldi ZL,low(Daten*2)+1
Lpm
?!?!?!?!?!?!?
Und wie spreche ich die 2 Zeile (also .db 88, 56, , 44,41) an?!?
Und warum eigentlich "Daten*2". Das heißt ja glaube ich nicht wirklich
"mal 2" oder?!?
Vielen Dank schonmal! :-)
Sebastian
Hallo,
das "n" hatte ich irgendwie immer in meinem namen übersehen g.
Z+ heisst
adiw ZL,1 ;16-Bit Zeiger erhoehen
oder inc 16bit pointer +1
>>Und wie spreche ich die 2 Zeile (also .db 88, 56, , 44,41) an?!?
das.. ist im Flash immer fortlaufend also Wenn du 10 byte unter daten
hast kannst du auf das letzte byte mit Daten +9 zugreifen.
bsp:
Daten:
.db 1,2,3,4
.db 5,6,7,8
Daten2:
.db 11,12,13,14
.db 15,16,17,18
um auf 6 zugreifen zu können musst du die adr Daten+5 nehmen.
wenn du auf 18 zugreifen willst musst du halten Daten2+7 nehmen.
an die daten also zaheln kommst du mit LPM , das die adr. aus dem
Z-Pointer im vom Flash in r0 lädt.
so jetz mal zu dem hier:
>ldi ZH,high(Daten*2)>ldi ZL,low(Daten*2)
da das ja alles wor basiert ist muss man ja irgendwie die einzelnen
bytes adressieren.
wenn vom Z Pointer das LSB 0 ist wird das low byte geladen bei 1 das
high byte ( der speicher ist ja wortorientiert)
also Z * 2 = 1 mal schieben nach links <=> LSB wird null
!! das ist aber nur bei LPM so !!
beim high byte: ldi ZL,(Daten*2+1);
.. steht aber alles im datenblatt oder ?
so sollte der code aussehen wenn man ein daten segment laden will:
LoadStartPointer:
ldi ZH,high(Daten*2)
ldi ZL,low(Daten*2)
Loop:
LPM
adiw ZL,1
<abbruchbedingung> // lade so lange Z in r0 bis break erreicht ist
rjmp Loop
ich hoffe ich habe jetzt nichts falsches gesagt, aber bei mir hats immer
funktioniert.
MfG
Sebastian
www.mcu-design.de
Hallo Namensvetter,
danke für die Erklärung! :-)
Also nun läuft das ganze in Ansätzen schon bei mir.
Aber kann es sein, daß der Wert "0" nicht gespeichert werden kann?!? Der
klappt bei mir nämlich nicht. Und im Datenblatt finde ich die
Lookup-Tabellen nicht.
Danke!
Sebastian
Hallo nochmal!
Also: Es hat sich geklärt. Es lag einfach daran, daß eine über die
serielle Schnittstelle gesendete "0" (als ASCII-Wert) nicht angezeigt
wird.
Vielen Dank nochmals!!!
Sebastian