robocat
14.03.2007, 20:11
hi ihr,
vielleicht interessierts jemanden, wie man mit einem mega8 ein bitmap auf einem alten nokia-3310-display anzeigt. diese schwarzweiss-displays haben 84*48 pixel und werden mit max. 3,3V betrieben.
die beschaltung habe ich von http://www.microsyl.com/nokialcd/nokialcd.html beinahe 1:1 übernommen, nur der data/command-pin hängt bei mir auf PB7. ausserdem muss man spannungsteiler vorsehen, wenn man (wie ich) den mega8 mit 5V betreibt:
http://katze.dead-men.de/3310circuit.png
mit dem code von der microsyl-seite lässt sich das display sehr einfach ansteuern, man muss nur im header ein define ändern
#define LCD_DC_PIN 0x80 // PB7
und noch eine main-funktion in der c-datei hinzufügen
int main(void)
{
unsigned char buffer[]="ein text";
LcdInit ();
//LcdContrast (64); //hier koennte man den kontrast regeln
LcdGotoXY (1,1);
LcdStr(1,buffer);
LcdUpdate ();
for(;;);
return 0;
}
man kann auch schön pixel setzen oder linien malen:
LcdLine(0,0,83,47,1);
LcdPixel(5,5,1);
LcdUpdate();
das display muss mit LcdInit() initialisiert werden, bevor es verwendet werden kann. alle zeichendaten werden (mit LcdPixel, LcdLine, LcdStr) zuerst in einen puffer im atmega geschrieben und erst durch LcdUpdate() auf das display übertragen.
ich wollte eigentlich mit sprintf etwas in einen puffer schreiben, aber sobald ich stdio.h include, hängt sich mein AVRstudio (bzw. winAVR?) komplett auf. wenn jemand weiß, woran das liegen könnte, bitte hilfe.
wenn man allerdings bitmaps abbilden will, empfiehlt es sich, nicht alle pixel einzeln zu setzen, sondern den RAM des displays direkt vollzuschreiben. dazu sind 2 dinge zu beachten:
1. der display-ram-zeiger muss gesetzt werden, bevor man reinschreiben kann
2. während in windows-bitmaps die bilddaten zeile für zeile gespeichert sind (bei schwarzweiss also ein byte 8 horizontale pixel sind) sind es im display-ram 8 vertikale pixel.
http://katze.dead-men.de/3310ram.png
3. ein schwarz-weiss-windows-bitmap enthält headerdaten vor den bilddaten, ausserdem ist die länge einer zeile (in byte) immer durch 4 teilbar. das führt dazu, dass statt 84 pixel (10,5byte) 96 pixel (12 byte) gespeichert werden. angezeigt werden die übrigen 12 pixel im zeichenprogramm nicht.
folgender code konvertiert ein schwarzweiss-bitmap (muss 84*48pixel gross sein) in das nokia format. erzeugt wird eine textdatei, die direkt in den AVR-code gecopypastet werden kann.
/*----------------------------------------------------------------
84*48 schwarz-weiss bitmap in nokia 3310 daten wandeln
compiler: bcc32
OS: XP
robocat, 14.03.07
----------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
int main()
{
FILE *pDatei;
unsigned int size,i,x,y;
unsigned char buf[64],*file1,*file2;
long pos1,pos2;
pDatei = fopen("J:\\test.bmp", "rb");
if(pDatei == NULL)
{
printf("Fehler beim Oeffnen der Quell-Datei!\n");
printf("Programm beendet.\n");
exit(1);
}
fseek(pDatei,0,SEEK_END);
pos2=ftell(pDatei);
fseek(pDatei,10,SEEK_SET);
fread(&pos1,4,1,pDatei);
fseek(pDatei,pos1,SEEK_SET);
size=pos2-pos1;
file1=malloc(size);
fread(file1,1,size,pDatei);
fclose(pDatei);
file2=malloc(504);
memset(file2,0,504);
for(x=0;x<84;x++)
{
for(y=0;y<48;y++)
{
if(!(*(file1+y*12+x/8)>>(7-(x%8)))&1==1)
{
*(file2+(5-y/8)*84+x)|=1<<(7-(y%8));
}
}
}
pDatei = fopen("J:\\test.txt", "w");
if(pDatei == NULL)
{
printf("Fehler beim Oeffnen der Ziel-Datei!\n");
printf("Programm beendet.\n");
free(file1);
free(file2);
exit(1);
}
sprintf(buf,"unsigned char picture[]={");
fwrite (buf,strlen(buf),1,pDatei);
for(i=0;i<504;i++)
{
if(i%8==0)fwrite("\n",1,1,pDatei);
sprintf(buf,"%u,",*(file2+i));
fwrite(buf,strlen(buf),1,pDatei);
}
fseek(pDatei,-1,SEEK_END);
fwrite ("};\n",3,1,pDatei);
fclose(pDatei);
free(file1);
free(file2);
return 0;
}
bei bedarf kann ich auch das executable zur verfügung stellen.
nun die bitmapdaten noch aufs lcd bringen:
unsigned char picture[]={
0,0,64,192,64,64,64,128,........ }; // beispiel, das ist der bytecode
int main(void)
{
word i; // typedef unsigned int word;
LcdInit();
LcdSend( 0x80, LCD_CMD );
LcdSend( 0x40, LCD_CMD );
for ( i = 0; i < 504; i++ )
{
LcdSend(picture[i], LCD_DATA );
}
for(;;);
return 0;
}
damit hat man das bitmap auf dem display:
http://katze.dead-men.de/3310bmp.png
bei fragen helfe ich gern.
gruesse von der katze
edit:
hier noch eine weitere einfache möglichkeit, eine katze darzustellen, sogar mit hintergrundbeleuchtung..
http://katze.dead-men.de/display.jpg
vielleicht interessierts jemanden, wie man mit einem mega8 ein bitmap auf einem alten nokia-3310-display anzeigt. diese schwarzweiss-displays haben 84*48 pixel und werden mit max. 3,3V betrieben.
die beschaltung habe ich von http://www.microsyl.com/nokialcd/nokialcd.html beinahe 1:1 übernommen, nur der data/command-pin hängt bei mir auf PB7. ausserdem muss man spannungsteiler vorsehen, wenn man (wie ich) den mega8 mit 5V betreibt:
http://katze.dead-men.de/3310circuit.png
mit dem code von der microsyl-seite lässt sich das display sehr einfach ansteuern, man muss nur im header ein define ändern
#define LCD_DC_PIN 0x80 // PB7
und noch eine main-funktion in der c-datei hinzufügen
int main(void)
{
unsigned char buffer[]="ein text";
LcdInit ();
//LcdContrast (64); //hier koennte man den kontrast regeln
LcdGotoXY (1,1);
LcdStr(1,buffer);
LcdUpdate ();
for(;;);
return 0;
}
man kann auch schön pixel setzen oder linien malen:
LcdLine(0,0,83,47,1);
LcdPixel(5,5,1);
LcdUpdate();
das display muss mit LcdInit() initialisiert werden, bevor es verwendet werden kann. alle zeichendaten werden (mit LcdPixel, LcdLine, LcdStr) zuerst in einen puffer im atmega geschrieben und erst durch LcdUpdate() auf das display übertragen.
ich wollte eigentlich mit sprintf etwas in einen puffer schreiben, aber sobald ich stdio.h include, hängt sich mein AVRstudio (bzw. winAVR?) komplett auf. wenn jemand weiß, woran das liegen könnte, bitte hilfe.
wenn man allerdings bitmaps abbilden will, empfiehlt es sich, nicht alle pixel einzeln zu setzen, sondern den RAM des displays direkt vollzuschreiben. dazu sind 2 dinge zu beachten:
1. der display-ram-zeiger muss gesetzt werden, bevor man reinschreiben kann
2. während in windows-bitmaps die bilddaten zeile für zeile gespeichert sind (bei schwarzweiss also ein byte 8 horizontale pixel sind) sind es im display-ram 8 vertikale pixel.
http://katze.dead-men.de/3310ram.png
3. ein schwarz-weiss-windows-bitmap enthält headerdaten vor den bilddaten, ausserdem ist die länge einer zeile (in byte) immer durch 4 teilbar. das führt dazu, dass statt 84 pixel (10,5byte) 96 pixel (12 byte) gespeichert werden. angezeigt werden die übrigen 12 pixel im zeichenprogramm nicht.
folgender code konvertiert ein schwarzweiss-bitmap (muss 84*48pixel gross sein) in das nokia format. erzeugt wird eine textdatei, die direkt in den AVR-code gecopypastet werden kann.
/*----------------------------------------------------------------
84*48 schwarz-weiss bitmap in nokia 3310 daten wandeln
compiler: bcc32
OS: XP
robocat, 14.03.07
----------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
int main()
{
FILE *pDatei;
unsigned int size,i,x,y;
unsigned char buf[64],*file1,*file2;
long pos1,pos2;
pDatei = fopen("J:\\test.bmp", "rb");
if(pDatei == NULL)
{
printf("Fehler beim Oeffnen der Quell-Datei!\n");
printf("Programm beendet.\n");
exit(1);
}
fseek(pDatei,0,SEEK_END);
pos2=ftell(pDatei);
fseek(pDatei,10,SEEK_SET);
fread(&pos1,4,1,pDatei);
fseek(pDatei,pos1,SEEK_SET);
size=pos2-pos1;
file1=malloc(size);
fread(file1,1,size,pDatei);
fclose(pDatei);
file2=malloc(504);
memset(file2,0,504);
for(x=0;x<84;x++)
{
for(y=0;y<48;y++)
{
if(!(*(file1+y*12+x/8)>>(7-(x%8)))&1==1)
{
*(file2+(5-y/8)*84+x)|=1<<(7-(y%8));
}
}
}
pDatei = fopen("J:\\test.txt", "w");
if(pDatei == NULL)
{
printf("Fehler beim Oeffnen der Ziel-Datei!\n");
printf("Programm beendet.\n");
free(file1);
free(file2);
exit(1);
}
sprintf(buf,"unsigned char picture[]={");
fwrite (buf,strlen(buf),1,pDatei);
for(i=0;i<504;i++)
{
if(i%8==0)fwrite("\n",1,1,pDatei);
sprintf(buf,"%u,",*(file2+i));
fwrite(buf,strlen(buf),1,pDatei);
}
fseek(pDatei,-1,SEEK_END);
fwrite ("};\n",3,1,pDatei);
fclose(pDatei);
free(file1);
free(file2);
return 0;
}
bei bedarf kann ich auch das executable zur verfügung stellen.
nun die bitmapdaten noch aufs lcd bringen:
unsigned char picture[]={
0,0,64,192,64,64,64,128,........ }; // beispiel, das ist der bytecode
int main(void)
{
word i; // typedef unsigned int word;
LcdInit();
LcdSend( 0x80, LCD_CMD );
LcdSend( 0x40, LCD_CMD );
for ( i = 0; i < 504; i++ )
{
LcdSend(picture[i], LCD_DATA );
}
for(;;);
return 0;
}
damit hat man das bitmap auf dem display:
http://katze.dead-men.de/3310bmp.png
bei fragen helfe ich gern.
gruesse von der katze
edit:
hier noch eine weitere einfache möglichkeit, eine katze darzustellen, sogar mit hintergrundbeleuchtung..
http://katze.dead-men.de/display.jpg