#define PinD7 7 #define PinD6 6 #define PinD5 5 #define PinD4 4 #define PinE 3 // Enable #define PinRW 2 // Read/Write #define PinRS 10 // Command/Data #define OpClear 0b00000001 #define OpHome 0b00000010 #define OpDispOn 0b00001100 #define OpDispOff 0b00001000 #define OpCursorOn 0b00001111 #define OpCursorOff 0b00001100 int val = 0; byte nibble = (0x00 & 0xF0) >> 4; byte xPos = 7; byte yPos = 1; void portClear() { digitalWrite(PinD7, LOW); digitalWrite(PinD6, LOW); digitalWrite(PinD5, LOW); digitalWrite(PinD4, LOW); } void portSet() { digitalWrite(PinD7, HIGH); digitalWrite(PinD6, HIGH); digitalWrite(PinD5, HIGH); digitalWrite(PinD4, HIGH); } void busyWait() { val = 1; while (val) { portSet(); pinMode(PinD7, INPUT); digitalWrite(PinRS, LOW); // 0=command, 1=character digitalWrite(PinRW, HIGH); // Lese-Modus digitalWrite(PinE, HIGH); // Enable _delay_us(1); val = digitalRead(PinD7); // Read Busy-Bit digitalWrite(PinE, LOW); _delay_us(1); pinMode(PinD7, OUTPUT); } portClear(); digitalWrite(PinRW, LOW); // Schreib-Modus } void transferNibbleToPins(byte nibble) { digitalWrite(PinE, HIGH); digitalWrite(PinD7, (nibble & 0b1000) > 0 ? HIGH : LOW); digitalWrite(PinD6, (nibble & 0b0100) > 0 ? HIGH : LOW); digitalWrite(PinD5, (nibble & 0b0010) > 0 ? HIGH : LOW); digitalWrite(PinD4, (nibble & 0b0001) > 0 ? HIGH : LOW); _delay_us(1); digitalWrite(PinE, LOW); _delay_us(1); } void lcdByte(char data) // sendet ein Byte zum LCD { // höherwertiges Halbbyte senden nibble = (data & 0xF0) >> 4; transferNibbleToPins(nibble); // niederwertiges Halbbyte senden nibble = data & 0x0F; transferNibbleToPins(nibble); } void lcdWriteCmd(char data) { // Kommando als Byte-Wert senden busyWait(); digitalWrite(PinRW, LOW); // Schreib-Modus digitalWrite(PinRS, LOW); // 0=command, 1=character lcdByte(data); } void lcdWriteChar(char data) { // Zeichen als Byte-Wert senden busyWait(); digitalWrite(PinRW, LOW); // Schreib-Modus digitalWrite(PinRS, HIGH); // 0=command, 1=character lcdByte(data); } void lcdInit() { // LCD initialisieren // lcd ein bisschen Zeit zum Hochfahren geben delay(50); digitalWrite(PinRW, LOW); // Schreib-Modus digitalWrite(PinRS, LOW); // 0=command, 1=character nibble = (0b00110000 & 0xF0) >> 4; transferNibbleToPins(nibble); // 8-Bit-Mode einschalten; delay(2); portClear(); nibble = (0b00110000 & 0xF0) >> 4; transferNibbleToPins(nibble); // nochmal ... _delay_us(30); portClear(); nibble = (0b00110000 & 0xF0) >> 4; transferNibbleToPins(nibble); // nochmal ... _delay_us(30); portClear(); busyWait(); nibble = (0b00100000 & 0xF0) >> 4; transferNibbleToPins(nibble); // Umschalten auf 4-Bit-Mode _delay_us(30); portClear(); lcdWriteCmd(0b00101001); // 4-Bit-Mode einschalten; extended instruction table 1 setzen // ^^^---------- function set // ^--------- DL = 0 = 4-Bit-Mode // ^-------- N = 1 = one-line display mode (0=two-line disp mde), 1 auch für 3-line-displays // ^------- DH = 0 = single height (1=double height) // ^^----- IS = 01 = extended instructions table No. IS lcdWriteCmd(0b00011101); // ^^^^--------- bias set // ^-------- BS = 1 = bias 1/4 (0=bias 1/5) // ^^------ fest // ^----- FX = 1 = three line application lcdWriteCmd(0b01010011); // ^^^^--------- Power/ICON control/Contrast set // ^-------- I_ON = 0 = ICON display off (1=on) // ^------- B_ON = 0 = booster circuit off (1=on) // ^^----- Contrast = 11 (C5,C4,C3,C2,C1,C0 can only be set when internal follower is used (OPF1=0,OPF2=0)) lcdWriteCmd(0b01101111); // ^^^^--------- Follower control // ^-------- F_ON = 1 = follower circuit on/off (Fon must be set to “Low” if (OPF1, OPF2) is not (0,0)) ???? // ^^^----- Rab2,Rab1,Rab0 = ???. V0 generator amplified ratio. Rab2,Rab1,Rab0 can only be set when internal follower is used (OPF1=0,OPF2=0). They can adjust the amplified ratio of V0 generator lcdWriteCmd(0b01111111); // ^^^^--------- Contrast set(low byte) // ^^^^----- I_ON = 0 = ICON display off (1=on) // C5,C4,C3,C2,C1,C0 can only be set when internal follower is used (OPF1=0,OPF2=0) lcdWriteCmd(0b00101000); // es folgen nur noch Standard-Befehle: normal instruction table 0 setzen, damit Konfiguration nicht überschrieben werden kann druch ÜBertragungsfehler lcdWriteCmd(0b00000110); // ^^^^^^------- Entry Mode Set // ^------ I/D = 1 = Increment / decrement = inc= left to right (1), dec= right to left (0) // ^----- S = Shift, if 1 = Scrolling in direction I/D lcdWriteCmd(OpClear); // clear display lcdWriteCmd(OpDispOn); // display on } void lcdHome() { lcdWriteCmd(OpHome); } void lcdClear() { lcdWriteCmd(OpClear); lcdHome(); } void lcdDispOn() { lcdWriteCmd(OpDispOn); } void lcdDispOff() { lcdWriteCmd(OpDispOff); } void lcdCursorOn() { lcdWriteCmd(OpCursorOn); } void lcdCursorOff() { lcdWriteCmd(OpCursorOff); } void lcdPos(byte x, byte y) { // x= 0...15, y= 0..2 Cursor an Pos. setzen byte cmd = 0x80; cmd += y * 16 + x; lcdWriteCmd(cmd); } void lcdPrint(char* lines) { char bst; for (byte i = 0; i < 48; i++) { bst = lines[i]; if (bst == 0) return; lcdWriteChar(bst); } } void lcdPrint(byte x, byte y, char* lines) { lcdPos(x, y); lcdPrint(lines); } void lcdDefineChar(byte charNum, byte* def) { if (charNum > 7) return; // nur 8 Chars möglich lcdWriteCmd(0x40 + 8 * charNum); // Adresse für custom char // 8 Datenbytes für die Definition übertragen for (byte i = 0; i < 8; i++) { lcdWriteChar(def[i]); } lcdPos(0, 0); // Standard Position DDRAM Adresse } void setup() { pinMode(PinD7, OUTPUT); pinMode(PinD6, OUTPUT); pinMode(PinD5, OUTPUT); pinMode(PinD4, OUTPUT); pinMode(PinE, OUTPUT); pinMode(PinRW, OUTPUT); pinMode(PinRS, OUTPUT); digitalWrite(PinRW, LOW); digitalWrite(PinRS, LOW); digitalWrite(PinE, LOW); portClear(); lcdInit(); lcdPos(xPos, yPos); // Cursor testen lcdCursorOn(); delay(2000); lcdCursorOff(); //Alphabet ausgeben und dann blinken lassen lcdClear(); for (int i = 0; i < 48; i++) { lcdWriteChar(65 + i); //Alphabet } delay(2000); for (byte i = 0; i < 4; i++) { lcdDispOff(); delay(500); lcdDispOn(); delay(500); } } void loop() { }