hallo,
also nach wochen des codens hab ich nun das erschaffen:
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
void toggle_e(void)
{
LCD_E_PORT |= _BV(LCD_E);
asm volatile ("rjmp 1f\n 1:"); //warte 500ns 0,543 us
LCD_E_PORT &= ~_BV(1 << LCD_E);
}
void delay(unsigned int count)
{
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)
{
char dataH;
char dataL;
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
do{
__asm__ __volatile__( "rjmp 1f\n 1:" ); //delay (500ns)
dataH = PIND; //zuerst hohes Nibble lesen
LCD_E_PORT &= ~_BV(LCD_E);
__asm__ __volatile__( "rjmp 1f\n 1:" ); //delay
LCD_E_PORT |= _BV(LCD_E);
__asm__ __volatile__( "rjmp 1f\n 1:" ); //delay
dataL = PIND; //lese niederes Nibble
LCD_E_PORT &= ~_BV(LCD_E);
//Dieser Code liest neben dem Busy-Flag gleich noch den Adresszähler aus
}while(dataH & (1<<DB3));
//while(PIND & (1<<DB3)) {} // solange warten, bis DB3 (busyFlag) auf 0
//LCD_E_PORT &= ~_BV(LCD_E); // LCD_E auf low
}
int main()
{
DDRD = 0xFF;
DDRB = 0xFF;
delay(20000); //warte 20 ms (20000us)
LCD_DATA1_PORT |= _BV(DB1);
LCD_DATA0_PORT |= _BV(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.
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0
LCD_DATA0_PORT &= ~_BV(DB0); //0
// 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.)
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
//////////////////////////////////////////////////////
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();
//Dann werden alle Datenpins wieder auf logisch '0' gesetzt.
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0
LCD_DATA0_PORT &= ~_BV(DB0); //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();
//Dann werden alle Datenpins wieder auf logisch '0' gesetzt.
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0
LCD_DATA0_PORT &= ~_BV(DB0); //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();
//Dann werden alle Datenpins wieder auf logisch '0' gesetzt.
LCD_DATA3_PORT &= ~_BV(DB3); //0
LCD_DATA2_PORT &= ~_BV(DB2); //0
LCD_DATA1_PORT &= ~_BV(DB1); //0
LCD_DATA0_PORT &= ~_BV(DB0); //0
delay(100);
///////////////////////////////////////////////////////////////
//////////////////////INITIALIESIERUNG ABGESCHLOSSEN///////////
///////////////////////////////////////////////////////////////
//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 |= _BV(LCD_RW);
//0010 0001=!
delay(100);
//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();
}
nun funktioniert das display mit diesem Code nicht, es kommen nur 2 schwarze Balken. (generell geht das display schon).
Hat jemand ne idee was da nicht stimmt?.....
Gruß
Scrat1
Lesezeichen