Es geht um dieses Programm: http://www.mikrocontroller.net/forum/read-4-336756.html ich hab ein paar Fragen zu dem Program/Display - bin totaller Newbie. 1.Bei Textausgabe: memcpy_P(&temp, &font[charx*5+x], 1); LCD_Write(1,temp); warum nicht einfach LCD_Write(1, font[charx*5+x]); 2. Bartholomäus schrieb: SIGNAL(SIG_OVERFLOW2) und packt hier die Tastaturabfrage 'rein. Ich hab nirgends gefunden was "SIG_OVERFLOW2" bedeutet. Ist evtl. nicht so schlimm, ich schau halt wie ich das auf meinem AVR Butterfly dann machen muss - aber wo kann ich über signal/interrupts lesen. Und was ist der Unterschied? 3. Gibt es key-bouncing noch, also wenn ich Taste drück', dass dann eine Flut von 1-0-1-0-1-1-1-1-1 kommt, bis der Taster wirklich unten ist? Und: reicht da ein "SIGNAL" Abstand dazu aus (Keys[i].delay) um das zu kompensieren? 4.Das Display steuert er in x-richtung per Pixel an, in y-Richtung der "zeile" also 1/8 mit je 8px Höhe. Seh' ich das Richtig? 5.Wenn ich einen Pixel setzen will, kann ich das Display modifizieren, und dann einen Befehl schichen "jetzt den Speicher darstellen", oder wird die Änderung sofort übernommen - sprich: brauche ich meinen eigenen Display-Speicher zum "wursteln" und schick den dann komplett geändert zum Display? 6. Wenn ich das byte (0x01) an das Display schicke, ist das dann der obere, oder der untere Pixel der Zeile den ich setze? 7.Wie schnell wäre ein kompletter 1024byte transfer zum Display? Ich bau' dann mal eine linien und per-pixel-grafik engine für das Display. Poste ich dann hier, dass es alle haben können.
Ich hab' den alten Thread schonnoch abonniert gehabt, bin nur am Wochenende selten online. 1. Die Textausgabe: Normalerweise liegen Strings (also Texte) in einem Programm sowohl im ROM als auch im RAM des Controllers. Da aber da RAM relativ knapp ist, kann man mittels dem Makro (?) PROGMEM im ROM ablegen. Dann kann man allerdings nicht mehr mit den normalen C-Funktionen arbeiten, sondern muss die ROM Funktion von der AVR-LIBC nehmen, deswegen das memcopy_P (für PROGMEM). Der Befehl liest einfach jeweils ein Zeichen vom Text in den RAM. 2. SIG_OVERFLOW2 ist der Interruptvektor, der ausgelöst wird, wenn der Timer2 von 255 auf 0 umschlägt, der beim Start mit TCCR2=(1<<CS22)|(1<<CS21); TIMSK|=(1<<TOIE2); aktiviert wird. Genaueres dazu steht im Datenblatt und in der Doku der AVR-LIBC 3. Bouncen tut bei meinem Code nichts mehr, dafür sind die ...Key(s) Funktionen gut. Das ganze ist ein bisschen aufwendiger, unterstütz dafür aber sowohl "gedrückte" Tasten als auch Events wenn eine Taste losgelassen wird. Die Verzögerung hat bei mir gereicht, aber das ganze zu verlängern ist kein Aufwand. 4. Ja, genau, das Display hat keine kleinere Adresseinheit. 5. Zweiteres, die Änderungen werden sofort übernommen. Allerdings ist das Display so träge, dass man es nicht sieht, wo etwas am Bildinhalt geändert wird. 6. Wenn ich mich recht erinnere der Oberste. 7. Schwer zu schätzen und ich bin grade ein bisschen zu faul zum Takte zählen, aber es dürfte schnell genug sein um es ein paarmal pro Sekunde zu machen. Aber: > Ich bau' dann mal eine linien und per-pixel-grafik engine für das > Display. Poste ich dann hier, dass es alle haben können. Ich wage zu bezweifeln, dass das schnell genug sein wird. Wie gesagt, du wirst nicht genug RAM haben um einen Backbuffer für das Display zu verwalten und das heißt, dass einen Pixel zu setzen auf Folgendes hinausläuft: Speicherposition beim Display setzen Dummyread ausführen ein Byte lesen das Byte umbiegen Speicherposition beim Display setzen neues Byte schreiben Ich will's dir nicht ausreden, aber ich halte es für wenig praktikabel. Mit externem RAM oder einem erheblich größeren Controller wäre die Sache natürlich eine andere. Beste Grüße, Bartl
Oh! Der ATmega169 hat nur 1024 bytes RAM! Ich muss mich erst an diese Größen gewöhnen ;)
nur so zur Info - wie könnte ich einen Block (1x8 pixel) auslesen?
Ich glaub' ich hab's herausgefunden:
1 | inline void LCD_Write(char isData,char data) |
2 | { |
3 | PORTB=data; |
4 | if (isData) |
5 | PORTC|=(1<<LCD_A0); |
6 | else |
7 | PORTC&=~(1<<LCD_A0); |
8 | |
9 | // set bit 'LCD_E' -> write |
10 | PORTC|=(1<<LCD_E); |
11 | // asm volatile("nop"::); |
12 | // unset bit 'LCD_E' -> stop write |
13 | PORTC&=~(1<<LCD_E); |
14 | }; |
15 | |
16 | inline char LCD_Read() |
17 | { |
18 | PORTC|=(1<<LCD_A0); |
19 | PORTC|=(1<<LCD_RW); // perform read |
20 | PORTC&=~(1<<LCD_RW);// stop read |
21 | return PORTB; |
22 | } |
Wofür machst Du manchmal diesen asm volatile("nop"::); (das wartet genau einen Taktzyklus, nicht?)
"nop" ist eine 1-Takt Pause sozusagen, wie du schon sagst. Das verwendet man schonmal, weil es bestimmte Anforderungen an das Enable Signal gibt. zB gibts so Angaben, dass Enable eine bestimmte (zum Beispiel 200ns) stabilen High oder Low Level haben muss. Man setzt/löscht dann den Port, macht ein paar Nops und kann weitermachen.
Allerdings mache ich den in diesem Fall ja garnicht, nur beim Reset. Ich hatte den nur testweise drin, aber bei 8 Mhz gehts auch ohne, deswegen sind // davor. Beste Grüße, Bartl
hätte ich bei 16Mhz ein Problem? Muss ich probieren, oder?
Oder ausrechnen. Im Datenblatt vom Display steht drin wie lang die Enable-Pulse sein müssen und in der .lss Datei von deinem Projekt kannst du sehen wieviele Assemblerbefehle der Puls braucht. Im Instruction Set Manual steht drin, wieviele Takte die brauchen. Wenn Takte*1s/Taktfrequenz >= minimal benötigte Zeit, dann klappts. Aber ich würd's auch ausprobieren. Beste Grüße, Bartl
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.