Also,
ich hab jetzt noch n Fehler gefunden (bei der busy-funktion). Und zwar hab ich da den Eingang nicht mehr auf Ausgang zurückgesetzt.
Dann hab ich noch gesehen, dass ich öfters das busy-flag abfragen muss.
und noch einen weiteren initialisierungsteil einbauen muss.
Code sieht jetzt so aus:
Code:
#include <avr/io.h>
#define LCD_PORT PORTD
#define LCD_DATA0_PORT LCD_PORT
#define LCD_DATA1_PORT PORTB
#define LCD_DATA2_PORT LCD_PORT
#define LCD_DATA3_PORT LCD_PORT
#define LCD_RS_PORT LCD_PORT
#define LCD_RW_PORT LCD_PORT
#define LCD_E_PORT LCD_PORT
#define LCD_RS 4
#define LCD_RW 5
#define LCD_E 6
#define DB0 7
#define DB1 0
#define DB2 2
#define DB3 3
#define Ende all_low(); //WELCHES NUN all_low MEINS all_high PETER FLEURY'S
void toggle_e(void)
{
LCD_E_PORT |= (1 << LCD_E);
asm volatile ("rjmp 1f\n 1:"); //warte 500ns 0,543 us
LCD_E_PORT &=~(1 << LCD_E);
}
void all_high(void)
{
LCD_DATA0_PORT |= _BV(DB0);
LCD_DATA1_PORT |= _BV(DB1);
LCD_DATA2_PORT |= _BV(DB2);
LCD_DATA3_PORT |= _BV(DB3);
}
void all_low(void)
{
LCD_DATA3_PORT &= ~_BV(DB3);
LCD_DATA2_PORT &= ~_BV(DB2);
LCD_DATA1_PORT &= ~_BV(DB1);
LCD_DATA0_PORT &= ~_BV(DB0);
}
void delay(unsigned long count)
{
long i;
for(i=0;count>i;i++)
{
asm volatile ("rjmp 1f\n 1:"); //warte 500ns 0,543 us
asm volatile ("rjmp 1f\n 1:"); //warte 500ns 0,543 us // also 1 us
}
}
void busy(void)
{
LCD_RW_PORT |= _BV(LCD_RW);
LCD_RS_PORT &= ~_BV(LCD_RS);
DDRD = 0xF7; //PD3 als Eingang definieren 0b11110111
LCD_E_PORT |= _BV(LCD_E); // LCD_E auf high
while(PIND & (1<<DB3)) {} // solange warten, bis DB3 (busyFlag) auf 0
LCD_E_PORT &= ~_BV(LCD_E); // LCD_E auf low
DDRD = 0xFF; //und alles auf Ausgang natürlich
}
int
main(void)
{
/* write data (RS=1, RW=0) */
/* write instruction (RS=0, RW=0) */
DDRD = 0xFF;
DDRB = 0xFF;
delay(20000); //warte 20 ms (20000us)
LCD_DATA1_PORT |= (1<<DB1);
LCD_DATA0_PORT |= (1<<DB0);
toggle_e();
delay(5000); //mehr als 4,1 ms warten (4992)
toggle_e();
delay(200); // es muss mehr als 100 us gewartet werden
toggle_e();
delay(200); // es muss mehr als 100 us gewartet werden
LCD_DATA0_PORT &= ~_BV(DB0); //LCD_DATA0_PORT &= ~_BV(DB0);
//PORTD = 0x20>>4; //entspricht 0b00100000
toggle_e();
delay(100); //mehr als 100us warten
busy();
LCD_RS_PORT &= ~_BV(LCD_RS);
LCD_RW_PORT &= ~_BV(LCD_RW); //Daten als Befehl zu deuten sind. Dies erfolgt durch RS=0 und RW=0
//Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst.
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT |= _BV(DB1); //1 -> high nibble 0b0010 (36) von 40
LCD_DATA0_PORT &= ~_BV(DB0); //0
// macht insgesamt 4 + 36 = 40 -> 0x28
toggle_e();
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT |= _BV(DB2); //1
LCD_DATA1_PORT &= ~_BV(DB1); //0 -> high nibble 0bxxxx0100 (4) von 40
LCD_DATA0_PORT &= ~_BV(DB0); //0
toggle_e();
//In diesem Fall ist data = 0x28, wie es bereits oben erwähnt wurde.
//Dann werden alle Datenpins wieder auf logisch '0' gesetzt.
Ende
// Als nächstes soll das Display ausgeschaltet werden. Dies erfolgt durch das Senden von 0x08 (vgl. Datenblatt).
// Das Senden erfolgt analog zu der obigen Erklärung (dort war es 0x28 für den 4-Bit-Modus).
// Danach muss das Display gelöscht werden. Hierzu muss 0x01 gesendet werden (vgl. Datenblatt).
// Zu guter letzt muss noch der Start-Modus (entry mode) definiert werden.
// Hier soll das Display einfach aktiviert und der Cursor deaktiviert werden. Dies erfolgt durch Senden von 0x0C.
//Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst. (s.u.)
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
busy();
LCD_RS_PORT &= ~_BV(LCD_RS);
LCD_RW_PORT &= ~_BV(LCD_RW); //Daten als Befehl zu deuten sind. Dies erfolgt durch RS=0 und RW=0
delay(100);
//0x08 <- Als nächstes soll das Display ausgeschaltet werden.
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0 -> high nibble 0b0000 (0) von 8
LCD_DATA0_PORT &= ~_BV(DB0); //0
// macht insgesamt 0 + 8 = 8 -> 0x08
toggle_e();
LCD_DATA3_PORT |= _BV(DB3); //1
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0 -> high nibble 0bxxxx1000 (8) von 8
LCD_DATA0_PORT &= ~_BV(DB0); //0
toggle_e();
Ende
/////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////
busy();
LCD_RS_PORT &= ~_BV(LCD_RS);
LCD_RW_PORT &= ~_BV(LCD_RW); //Daten als Befehl zu deuten sind. Dies erfolgt durch RS=0 und RW=0
delay(100);
//Danach muss das Display gelöscht werden. Hierzu muss 0x01 gesendet werden
//Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst.
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0 -> high nibble 0b0000 (0) von 1
LCD_DATA0_PORT &= ~_BV(DB0); //0
// macht insgesamt 0 + 1 = 1 -> 0x01
toggle_e();
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0 -> high nibble 0bxxxx0001 (1) von 1
LCD_DATA0_PORT |= _BV(DB0); //1
toggle_e();
Ende
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
busy();
LCD_RS_PORT &= ~_BV(LCD_RS);
LCD_RW_PORT &= ~_BV(LCD_RW); //Daten als Befehl zu deuten sind. Dies erfolgt durch RS=0 und RW=0
delay(100);
//Hier soll das Display set entry mode DB1 und DB2
//Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst.
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0 -> high nibble 0b0000 (0) von 12
LCD_DATA0_PORT &= ~_BV(DB0); //0
// macht insgesamt 0 + 12 = 12 -> 0x0c
toggle_e();
LCD_DATA3_PORT &= ~_BV(DB3);
//LCD_DATA3_PORT = _BV(DB3); //0
LCD_DATA2_PORT |= _BV(DB2); //1
LCD_DATA1_PORT |= _BV(DB1);
//LCD_DATA1_PORT &= ~_BV(DB1); //0 -> high nibble 0bxxxx1100 (12) von 12
LCD_DATA0_PORT &= ~_BV(DB0); //0
toggle_e();
Ende
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////
busy();
LCD_RS_PORT &= ~_BV(LCD_RS);
LCD_RW_PORT &= ~_BV(LCD_RW); //Daten als Befehl zu deuten sind. Dies erfolgt durch RS=0 und RW=0
delay(100);
//Hier soll das Display einfach aktiviert und der Cursor deaktiviert werden. Dies erfolgt durch Senden von 0x0C.
//Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst.
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0 -> high nibble 0b0000 (0) von 12
LCD_DATA0_PORT &= ~_BV(DB0); //0
// macht insgesamt 0 + 12 = 12 -> 0x0c
toggle_e();
LCD_DATA3_PORT |= _BV(DB3); //0
LCD_DATA2_PORT |= _BV(DB2); //1
LCD_DATA1_PORT &= ~_BV(DB1); //0 -> high nibble 0bxxxx1100 (12) von 12
LCD_DATA0_PORT &= ~_BV(DB0); //0
toggle_e();
Ende
delay(100);
///////////////////////////////////////////////////////////////
//////////////////////INITIALIESIERUNG ABGESCHLOSSEN///////////
///////////////////////////////////////////////////////////////
//CLRSCR
busy();
LCD_RS_PORT &= ~_BV(LCD_RS);
LCD_RW_PORT &= ~_BV(LCD_RW); //Daten als Befehl zu deuten sind. Dies erfolgt durch RS=0 und RW=0
delay(100);
//Danach muss das Display gelöscht werden. Hierzu muss 0x01 gesendet werden
//Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst.
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0 -> high nibble 0b0000 (0) von 1
LCD_DATA0_PORT &= ~_BV(DB0); //0
// macht insgesamt 0 + 1 = 1 -> 0x01
toggle_e();
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0 -> high nibble 0bxxxx0001 (1) von 1
LCD_DATA0_PORT |= _BV(DB0); //1
toggle_e();
Ende
////////////////////////////////////////////////////
//Das Schreiben von Daten auf dem Display funktioniert mit
//den bereits oben angeführten Befehlen. RS muss auf H-Pegel sein, R/W auf Low.
LCD_RS_PORT |= _BV(LCD_RS);
LCD_RW_PORT &= ~(1 << LCD_RW); // LCD_RW_PORT |= _BV(LCD_RW);
toggle_e();
//0010 0001=!
delay(100);
busy();
//Die beiden Nibble werden nun hintereinander an das LCD gesendet, das obere zuerst.
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT |= _BV(DB1); //1 -> high nibble
LCD_DATA0_PORT &= ~_BV(DB0); //0
toggle_e();
LCD_DATA3_PORT |= _BV(DB3); //1
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0 -> high nibble
LCD_DATA0_PORT &= ~_BV(DB0); //0
toggle_e();
}
was bei dem Display jetzt neuerdings passiert ist, dass nicht mehr nur 2 Balken schwarz sind, sondern, dass bei Zeile 2 und 4 die oberen drei Pixel Reihen auch schwarz sind.
Das ist aber nur sichtbar wenn man den Kontrast sehr sehr dunkel dreht.
Das gewünschte Zeichen wird aber nicht ausgegeben.
Gruß
Scrat1
Lesezeichen