Forum: Mikrocontroller und Digitale Elektronik bringe LCD-Display nicht zum laufen


von Dave (Gast)


Lesenswert?

Hallo


Ich habe mir kürzlich bei Conrad ein LCD-Display mit 16x2 Zeilen 
gekauft...

Nun bin ich am Programmieren. Ich habe sowohl fertigen Code aus 
verschiedenen Tutorials genommen und die Ports angepasst und ein 
programm mehr oder weniger selber geschrieben.
Doch das einzige was angezeigt wird, sind die 32 Zeichen, aber alle 
davon als schwarze Rechtecke. Also wie wenn man nur den Strom ansteckt.

Was könnte am Code Falsch sein? Ach ja, uC ist ein Atmega168 mit 
internem Takt von 8Mhz und prescaler von 8 --> 1Mhz

hier der Code:
1
#include <avr/io.h>
2
#include <util/delay.h>
3
4
#define F_CPU 1000000
5
6
#define PORT_LCD  PORTD
7
#define PIN_RS  4
8
#define PIN_EN  5
9
10
#define CLEAR_DISPLAY 0x01
11
#define CURSOR_HOME 0x02
12
13
void lcd_enable(void)
14
{
15
  PORT_LCD |= (1<<PIN_EN);
16
  asm("nop");
17
  asm("nop");
18
  asm("nop");
19
  PORT_LCD &= ~(1<<PIN_EN);
20
}
21
22
void lcd_data(unsigned char temp1)
23
{
24
   unsigned char temp2 = temp1;
25
 
26
   temp1 = temp1 >> 4;
27
   temp1 = temp1 & 0x0F;
28
   PORT_LCD &= 0xF0;
29
   PORT_LCD |= temp1 | (1<<PIN_RS); // inkl. LCD_RS = RS-Leitung setzen
30
   lcd_enable();
31
 
32
   temp2 = temp2 & 0x0F;
33
   PORT_LCD &= 0xF0;
34
   PORT_LCD |= temp2 | (1<<PIN_RS); // inkl. LCD_RS = RS-Leitung setzen
35
   lcd_enable();
36
   
37
   _delay_ms(50.0);
38
}
39
40
void lcd_command(unsigned char temp1)
41
{
42
  unsigned char temp2 = temp1;
43
  
44
  temp1 = temp1 >> 4; //oberes nibble holen
45
  temp1 = temp1 & 0x0F; //maskieren
46
  PORT_LCD = temp1; //setzen
47
  lcd_enable();
48
  
49
  temp2 = temp2 & 0x0F; //unteres nibble holen und maskieren
50
  PORT_LCD = temp2; //setzen
51
  lcd_enable();
52
  
53
  _delay_ms(5.0);
54
}
55
56
void lcd_init(void)
57
{
58
  _delay_ms(20);
59
  
60
  PORT_LCD = 0x03;
61
  lcd_enable();
62
  _delay_ms(5.0);
63
  
64
  PORT_LCD = 0x03;
65
  lcd_enable();
66
  _delay_us(160);
67
  
68
  PORT_LCD = 0x03;
69
  lcd_enable();
70
  _delay_us(160);
71
  
72
  PORT_LCD = 0x02;
73
  lcd_enable();
74
  _delay_ms(5.0);
75
  
76
  lcd_command(0x28);
77
  
78
  lcd_command(0x0C);
79
  
80
  lcd_command(0x04);
81
  
82
  lcd_command(CLEAR_DISPLAY);
83
  
84
  lcd_command(CURSOR_HOME);
85
}
86
87
int main(void)
88
{
89
  lcd_init();
90
  
91
  lcd_data("a");
92
  
93
  while(1)
94
  {
95
  }
96
  
97
  return 0;
98
}

Vielen Dank, falls mir jemand helfen kann/will, Gruss und schönen Abend
Dave

von Joe (Gast)


Lesenswert?

Beitrag "Wie mache ich eine Textausgabe 8Bit auf Display?"

Ist ausführlich erklärt und am Ende des Threads gibts nen Code zum 
Testen.

von Andreas K. (a-k)


Lesenswert?

Schon mal am Kontrastpoti rumgespielt?

von Dave S. (applican)


Lesenswert?

Guten Morgen ;-)

Ich habe nochmals den Code durchgeschaut und auch noch mit dem anderen 
Thread verglichen... Schlussendlich habe ich gemerkt, dass ein Poti doch 
nicht schlecht ist, anstatt einfach auf Ground zu legen (nur schwarze 
Rechtecke und kein Inhalt sichtbar).
Dann hatte ich noch das Problem, dass ich nicht mehr aus dem 
Schreibmodus raus kam, weil das RS-bit nicht wieder auf 0 gesetzt wurde.

aber jetzt geht alles... macht richtig spass, damit zu spiiiielen ;-)

gruss und Danke für die Hilfe!
Dave

von Cosi (Gast)


Lesenswert?

Hallo zusammen,

habe ebenfalls ein Prob. und wollte kein neues Thema eröffnen, daher 
poste ich es einfach hier...
Ich kriege es einfach net zum laufen...Finde keine Fehler...:(

Beim Display handelt es sich um folgenden:
http://docs-europe.electrocomponents.com/webdocs/06dd/0900766b806dda1a.pdf

Als µC benutze ich einen MEGA48 auf nem AVR-Board..
Für das Prog. habe ich eine Vorlage von Nollmeyer hier im Forum benutzt, 
dabei ein bisschen angepasst, wie Ports ect.
Wie zu sehen, benutze ich Port D.

Das Display gibt einfach keine Zeichen aus :( Außer, nach dem Start nur 
Rechtecke, also alle Pixel aktiv...

Am Kontrast habe ich schon herumgespielt, nix...
Die Display-Comments stimmen mit denen von meinem Display überein...So 
weit ich es korrekt kontrolliert habe. Naja, alle Display-Controller 
sind ja nahezu gleich...


::::::::::::::::::::::::::::::::::::::::::::::::::::Header

/* ---- LCD Driver Routine for 2x16 / 4x20 char. Display 
----------------------------------------------------- */
/* 
*/
/* (c) B. Nollmeyer, WINAVR sample Routine. Das Display wird im 4 BIT 
Modus betrieben.                         */
/* 
*/

#ifndef lcd_h
#define lcd_h

/* ---- Define BIT Variablen 
------------------------------------------------------------------------ 
---------  */
/* 
*/
#define HIGH 1                                                  /* 
digital High Pegel                          */
#define LOW  0                                                  /* 
digital Low Pegel                           */

/* ---- Define I/O's, AVR I/O's sind nicht BITadressierbar! 
-------------------------------------------------- */
/* 
*/
struct bits {
  uint8_t b0:1;
  uint8_t b1:1;
  uint8_t b2:1;
  uint8_t b3:1;
  uint8_t b4:1;
  uint8_t b5:1;
  uint8_t b6:1;
  uint8_t b7:1;
} __attribute__((_packed_));

#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin) /* I/O 
Defines vereinfachen                    */

/* ---- Define Display Signale 
------------------------------------------------------------------------ 
-------  */
/* 
*/
#define ENABLE SBIT (PORTD, 6)                                  // 
Display Enable
#define RS SBIT (PORTD, 4)                                      // 
Display RS BIT

/* ---- Define Display Kommandos 
------------------------------------------------------------------------ 
-----  */
/* 
*/
#define fs1 0x28 // 4 Bit Modus  2 Zeilen  5x7 Dots
#define fs2 0x2C // 4 Bit Modus  2 Zeilen  5x10 Dots
#define fs3 0x20 // 4 Bit Modus  1 Zeile  5x7 Dots
#define fs4 0x24 // 4 Bit Modus  1 Zeile  5x10 Dots

#define on_off_control_1    0x0C // Display An  Cursor Aus  Blink Aus
#define on_off_control_2    0x0E // Display An  Cursor An  Blink Aus
#define on_off_control_3    0x0F // Display An  Cursor An  Blink An
#define on_off_control_4    0x08 // Display Aus

#define entrymode_1         0x06 // Cursor nach rechts / kein Shift
#define entrymode_2         0x07 // Cursor nach rechts / Shift
#define entrymode_3         0x04 // Cursor nach links / kein Shift
#define entrymode_4         0x05 // Cursor nach links / Shift

#define cursor_line_1       0x00 // LCD Zeile 1 / Referenz LCD 
Datenblatt; 80
#define cursor_line_2       0x40 // LCD Zeile 2 / Referenz LCD 
Datenblatt; C0
#define cursor_line_3       0x90 // LCD Zeile 3 / Referenz LCD 
Datenblatt
#define cursor_line_4       0xD0 // LCD Zeile 4 / Referenz LCD 
Datenblatt

#define clear_display       0x01 // Clear Display
#define cursor_home         0x02 // Cursor Home

/* ---- Define Prototypes 
------------------------------------------------------------------------ 
------------  */
/* 
*/
extern void lcd_command (uint8_t dsp_control_out);              // 
Funktion für Display Steuersignale
extern void lcd_char (uint8_t send_char);                       // 
Funktion Zeichen ausgeben
extern void lcd_init (void);                                    // 
Funktion LCD Initialisieren
extern void lcd_puts (const char *lcd_string);                  // 
Funktion Display String ausgeben

#endif

:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::



/* ---- LCD Driver Routine for 2x16 / 4x20 char. Display 
-------------------------------------- */
/* 
*/
/* (c) B. Nollmeyer, WINAVR sample Routine! Das Display wird im 4 BIT 
Modus betrieben.                         */
/* ATMEL ATTINY 2313, die Routine benötigt 247 Byte inkl. Startup Code. 
WINAVR gcc 3.4.6                       */

/* ---- CPU CLOCK 
------------------------------------------------------------------------ 
-----  */
/* 
*/
#ifndef F_CPU
#define F_CPU 3686000UL // Frequenz in Hz
#endif

/* ---- Include Files 
------------------------------------------------------------------------ 
-  */
/* 
*/
#include <stdint.h>                                   /* ISO C99 Integer 
types        */
#include <avr/io.h>                                   /* ATTINY I/O's 
*/
#include <util/delay.h>                               /* delay Lib. 
*/
#include "lcd.h"                                      /* LCD Lib. 
*/

/* ---- MAIN 
------------------------------------------------------------------------ 
-----------  */

int main (void)  {
  DDRD = (1 << DDD6)                                   // Anschluß 
Display ENABLE
       | (1 << DDD0)                                   // Anschluß 
Display Datenbit DB4
       | (1 << DDD1)                                   // Anschluß 
Display Datenbit DB5
       | (1 << DDD2)                                   // Anschluß 
Display Datenbit DB6
       | (1 << DDD3)                                   // Anschluß 
Display Datenbit DB7
     | (1 << DDD4);                                 // Anschluß Display 
RS

  _delay_ms (15);                                      // wait 15 mSec. 
after Power ON
  lcd_init ();                                         // Display 
initialisieren
  lcd_puts ("WIN_AVR GCC");                            // Display Text

  for (;;);
}

/* ---- Display Ausgabe String 
------------------------------------------------------------------ */

void lcd_puts (const char *lcd_string)  {
  while (*lcd_string)  {
    lcd_char (*lcd_string++);                         // String auslesen 
und an LCD Ausgabe übergeben
  }
}

/* ---- Display Ausgabe Steuersignale 
----------------------------------------------------------- */

void lcd_command (uint8_t dsp_control_out)  {
  RS = LOW;                                           // Steuersignale 
an Display ausgeben (RS BIT=0)
  lcd_char (dsp_control_out);                         // Steuersignal 
ausgeben
  _delay_ms (4.1);                                    // Warteschleife 
4,1 mSec.
  RS = HIGH;                                          // RS BIT=1 => 
Daten
}

/* ---- Display Ausgabe Zeichen 
----------------------------------------------------------------- */

void lcd_char (uint8_t send_char)  {
  uint8_t n=2;                                         // Sende 2x 4 BIT 
(oberes Nibble zuerst)
  do  {
        PORTD = (PORTD & 0x0F) | (send_char & 0xF0);   // Port low 
nibble nicht verändern
        ENABLE = HIGH;                                 // ENABLE = HIGH
        ENABLE = LOW;                                  // ENABLE = LOW, 
Steuersignal Datenübernahme
        send_char <<= 4;                               // unteres Nibble 
nach oben schieben
  }while (--n);
  _delay_us (42);                                      // Warteschleife 
42 uSec.
}

/* ---- Display initialisieren 
------------------------------------------------------------------ */

void lcd_init (void)  {
  uint8_t n = 3;                                       // Init. Sequenz, 
Referenz LCD Datenblatt
  do  {                                                // 3x 33H (0x03), 
init cycle 3x
        lcd_command (0x30);                            // DB4, DB5 = 1
  }while (--n);
  lcd_command (fs1);                              // 4 Bit Modus / 2 
Zeilen / 5x7 Dots
  lcd_command (on_off_control_1);                      // Display An / 
Cursor Aus / Blink Aus
  lcd_command (clear_display);                         // Clear Display
  lcd_command (entrymode_1);                           // Cursor nach 
rechts / kein Shift
}

von Cosi (Gast)


Lesenswert?

so ist besser:

::::::::::::::::::::::::::::::::::::::::::::::::::::Header
1
/* ---- LCD Driver Routine for 2x16 / 4x20 char. Display
2
----------------------------------------------------- */
3
/*
4
*/
5
/* (c) B. Nollmeyer, WINAVR sample Routine. Das Display wird im 4 BIT
6
Modus betrieben.                         */
7
/*
8
*/
9
10
#ifndef lcd_h
11
#define lcd_h
12
13
/* ---- Define BIT Variablen
14
---------------------------------------------------------------------------------
15
*/
16
/*
17
*/
18
#define HIGH 1                                                  /*
19
digital High Pegel                          */
20
#define LOW  0                                                  /*
21
digital Low Pegel                           */
22
23
/* ---- Define I/O's, AVR I/O's sind nicht BITadressierbar!
24
-------------------------------------------------- */
25
/*
26
*/
27
struct bits {
28
  uint8_t b0:1;
29
  uint8_t b1:1;
30
  uint8_t b2:1;
31
  uint8_t b3:1;
32
  uint8_t b4:1;
33
  uint8_t b5:1;
34
  uint8_t b6:1;
35
  uint8_t b7:1;
36
} __attribute__((__packed__));
37
38
#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin) /* I/O
39
Defines vereinfachen                    */
40
41
/* ---- Define Display Signale
42
-------------------------------------------------------------------------------
43
*/
44
/*
45
*/
46
#define ENABLE SBIT (PORTD, 6)                                  //
47
Display Enable
48
#define RS SBIT (PORTD, 4)                                      //
49
Display RS BIT
50
51
/* ---- Define Display Kommandos
52
-----------------------------------------------------------------------------
53
*/
54
/*
55
*/
56
#define fs1 0x28 // 4 Bit Modus / 2 Zeilen / 5x7 Dots
57
#define fs2 0x2C // 4 Bit Modus / 2 Zeilen / 5x10 Dots
58
#define fs3 0x20 // 4 Bit Modus / 1 Zeile / 5x7 Dots
59
#define fs4 0x24 // 4 Bit Modus / 1 Zeile / 5x10 Dots
60
61
#define on_off_control_1    0x0C // Display An / Cursor Aus / Blink Aus
62
#define on_off_control_2    0x0E // Display An / Cursor An / Blink Aus
63
#define on_off_control_3    0x0F // Display An / Cursor An / Blink An
64
#define on_off_control_4    0x08 // Display Aus
65
66
#define entrymode_1         0x06 // Cursor nach rechts / kein Shift
67
#define entrymode_2         0x07 // Cursor nach rechts / Shift
68
#define entrymode_3         0x04 // Cursor nach links / kein Shift
69
#define entrymode_4         0x05 // Cursor nach links / Shift
70
71
#define cursor_line_1       0x00 // LCD Zeile 1 / Referenz LCD
72
Datenblatt; 80
73
#define cursor_line_2       0x40 // LCD Zeile 2 / Referenz LCD
74
Datenblatt; C0
75
#define cursor_line_3       0x90 // LCD Zeile 3 / Referenz LCD
76
Datenblatt
77
#define cursor_line_4       0xD0 // LCD Zeile 4 / Referenz LCD
78
Datenblatt
79
80
#define clear_display       0x01 // Clear Display
81
#define cursor_home         0x02 // Cursor Home
82
83
/* ---- Define Prototypes
84
------------------------------------------------------------------------------------
85
*/
86
/*
87
*/
88
extern void lcd_command (uint8_t dsp_control_out);              //
89
Funktion für Display Steuersignale
90
extern void lcd_char (uint8_t send_char);                       //
91
Funktion Zeichen ausgeben
92
extern void lcd_init (void);                                    //
93
Funktion LCD Initialisieren
94
extern void lcd_puts (const char *lcd_string);                  //
95
Funktion Display String ausgeben
96
97
#endif
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
1
/* ---- LCD Driver Routine for 2x16 / 4x20 char. Display
2
-------------------------------------- */
3
/*
4
*/
5
/* (c) B. Nollmeyer, WINAVR sample Routine! Das Display wird im 4 BIT
6
Modus betrieben.                         */
7
/* ATMEL ATTINY 2313, die Routine benötigt 247 Byte inkl. Startup Code.
8
WINAVR gcc 3.4.6                       */
9
10
/* ---- CPU CLOCK
11
-----------------------------------------------------------------------------
12
*/
13
/*
14
*/
15
#ifndef F_CPU
16
#define F_CPU 3686000UL // Frequenz in Hz
17
#endif
18
19
/* ---- Include Files
20
-------------------------------------------------------------------------
21
*/
22
/*
23
*/
24
#include <stdint.h>                                   /* ISO C99 Integer
25
types        */
26
#include <avr/io.h>                                   /* ATTINY I/O's
27
*/
28
#include <util/delay.h>                               /* delay Lib.
29
*/
30
#include "lcd.h"                                      /* LCD Lib.
31
*/
32
33
/* ---- MAIN
34
-----------------------------------------------------------------------------------
35
*/
36
37
int main (void)  {
38
  DDRD = (1 << DDD6)                                   // Anschluß
39
Display ENABLE
40
       | (1 << DDD0)                                   // Anschluß
41
Display Datenbit DB4
42
       | (1 << DDD1)                                   // Anschluß
43
Display Datenbit DB5
44
       | (1 << DDD2)                                   // Anschluß
45
Display Datenbit DB6
46
       | (1 << DDD3)                                   // Anschluß
47
Display Datenbit DB7
48
     | (1 << DDD4);                                 // Anschluß Display
49
RS
50
51
  _delay_ms (15);                                      // wait 15 mSec.
52
after Power ON
53
  lcd_init ();                                         // Display
54
initialisieren
55
  lcd_puts ("WIN_AVR GCC");                            // Display Text
56
57
  for (;;);
58
}
59
60
/* ---- Display Ausgabe String
61
------------------------------------------------------------------ */
62
63
void lcd_puts (const char *lcd_string)  {
64
  while (*lcd_string)  {
65
    lcd_char (*lcd_string++);                         // String auslesen
66
und an LCD Ausgabe übergeben
67
  }
68
}
69
70
/* ---- Display Ausgabe Steuersignale
71
----------------------------------------------------------- */
72
73
void lcd_command (uint8_t dsp_control_out)  {
74
  RS = LOW;                                           // Steuersignale
75
an Display ausgeben (RS BIT=0)
76
  lcd_char (dsp_control_out);                         // Steuersignal
77
ausgeben
78
  _delay_ms (4.1);                                    // Warteschleife
79
4,1 mSec.
80
  RS = HIGH;                                          // RS BIT=1 =>
81
Daten
82
}
83
84
/* ---- Display Ausgabe Zeichen
85
----------------------------------------------------------------- */
86
87
void lcd_char (uint8_t send_char)  {
88
  uint8_t n=2;                                         // Sende 2x 4 BIT
89
(oberes Nibble zuerst)
90
  do  {
91
        PORTD = (PORTD & 0x0F) | (send_char & 0xF0);   // Port low
92
nibble nicht verändern
93
        ENABLE = HIGH;                                 // ENABLE = HIGH
94
        ENABLE = LOW;                                  // ENABLE = LOW,
95
Steuersignal Datenübernahme
96
        send_char <<= 4;                               // unteres Nibble
97
nach oben schieben
98
  }while (--n);
99
  _delay_us (42);                                      // Warteschleife
100
42 uSec.
101
}
102
103
/* ---- Display initialisieren
104
------------------------------------------------------------------ */
105
106
void lcd_init (void)  {
107
  uint8_t n = 3;                                       // Init. Sequenz,
108
Referenz LCD Datenblatt
109
  do  {                                                // 3x 33H (0x03),
110
init cycle 3x
111
        lcd_command (0x30);                            // DB4, DB5 = 1
112
  }while (--n);
113
  lcd_command (fs1);                              // 4 Bit Modus / 2
114
Zeilen / 5x7 Dots
115
  lcd_command (on_off_control_1);                      // Display An /
116
Cursor Aus / Blink Aus
117
  lcd_command (clear_display);                         // Clear Display
118
  lcd_command (entrymode_1);                           // Cursor nach
119
rechts / kein Shift
120
}

von Fisch (Gast)


Lesenswert?

Hallo!
Bin jetzt nur mal kurz drübergeflogen. Was mir aufgefallen ist:
Enable wird oben als sbit(PORTD, 6) definiert. Und weiter unten sagst du 
dann  ENABLE = HIGH. Das macht keinen Sinn. Ausserdem solltest du den 
Enable Impuls etwas länger auf HIGH lassen. Also noch ein kleines Delay 
einbauen.

Gruß Fisch

von Stefan B. (stefan) Benutzerseite


Lesenswert?

@ Cosi

ich sehe bei deinem Code nicht, wie bei der Ausgabe eines Zeichens 
(Daten) per lcd_char die RS Leitung auf HIGH geht. Die Zeile
1
PORTD = (PORTD & 0x0F) | (send_char & 0xF0);   // Port low

macht das unmöglich, da (PORTD & 0x0F) auch DDD4 löscht/auf LOW setzt! 
So gesehen schickst du nie Daten (Zeichen) ans LCD sondern immer ggf. 
illegale Kommandos.

Vergleiche mal, warum es beim Tutorialquellcode ZWEI Funktionen 
(lcd_data() und lcd_command()) gibt.

von Joe (Gast)


Lesenswert?

Beitrag "Wie mache ich eine Textausgabe 8Bit auf Display?"

Ist ausführlich erklärt und am Ende des Threads gibts nen Code zum
Testen und der funktioniert !!! Ich wiederhole mich...

Was hast du geändert ? Die Delays passen vermutlich nicht mehr, 
vergleiche mal den Quarztakt.

Der Rest ist ok. Der originale Code ist ebenso fehlerfrei !!!

von Cosi (Gast)


Lesenswert?

Hallo,
Joe, is er von dir :)
Du, habe nichts groß geändert, nur die Ports angepasst, weil ich den 
Port D nutze...Ebenso Taktfrequenz geändert...

Ich habe nun die Tipps von Fisch und Stefan mit berücksichtigt...Aber es 
geht noch immer nicht :(
1
/* ---- LCD Driver Routine for 2x16 / 4x20 char. Display ----------------------------------------------------- */
2
/*                                                                                                             */
3
/* (c) B. Nollmeyer, WINAVR sample Routine. Das Display wird im 4 BIT Modus betrieben.                         */
4
/*                                                                                                             */
5
6
#ifndef lcd_h
7
#define lcd_h
8
9
/* ---- Define BIT Variablen --------------------------------------------------------------------------------- */
10
/*                                                                                                             */
11
#define HIGH 1                                                  /* digital High Pegel                          */
12
#define LOW  0                                                  /* digital Low Pegel                           */
13
14
/* ---- Define I/O's, AVR I/O's sind nicht BITadressierbar! -------------------------------------------------- */
15
/*                                                                                                             */
16
struct bits {
17
  uint8_t b0:1;
18
  uint8_t b1:1;
19
  uint8_t b2:1;
20
  uint8_t b3:1;
21
  uint8_t b4:1;
22
  uint8_t b5:1;
23
  uint8_t b6:1;
24
  uint8_t b7:1;
25
} __attribute__((__packed__));
26
27
#define SBIT(port,pin) ((*(volatile struct bits*)&port).b##pin) /* I/O Defines vereinfachen                    */
28
29
/* ---- Define Display Signale ------------------------------------------------------------------------------- */
30
/*                                                                                                             */
31
#define ENABLE 6                                  // Display Enable
32
#define RS 4                                      // Display RS BIT
33
//#define RS SBIT (PORTD, 4)
34
35
/* ---- Define Display Kommandos ----------------------------------------------------------------------------- */
36
/*                                                                                                             */
37
#define fs1 0x28 // 4 Bit Modus / 2 Zeilen / 5x7 Dots
38
#define fs2 0x2C // 4 Bit Modus / 2 Zeilen / 5x10 Dots
39
#define fs3 0x20 // 4 Bit Modus / 1 Zeile / 5x7 Dots
40
#define fs4 0x24 // 4 Bit Modus / 1 Zeile / 5x10 Dots
41
42
#define on_off_control_1    0x0C // Display An / Cursor Aus / Blink Aus
43
#define on_off_control_2    0x0E // Display An / Cursor An / Blink Aus
44
#define on_off_control_3    0x0F // Display An / Cursor An / Blink An
45
#define on_off_control_4    0x08 // Display Aus
46
47
#define entrymode_1         0x06 // Cursor nach rechts / kein Shift
48
#define entrymode_2         0x07 // Cursor nach rechts / Shift
49
#define entrymode_3         0x04 // Cursor nach links / kein Shift
50
#define entrymode_4         0x05 // Cursor nach links / Shift
51
52
#define cursor_line_1       0x00 // LCD Zeile 1 / Referenz LCD Datenblatt; 80
53
#define cursor_line_2       0x40 // LCD Zeile 2 / Referenz LCD Datenblatt; C0
54
#define cursor_line_3       0x90 // LCD Zeile 3 / Referenz LCD Datenblatt
55
#define cursor_line_4       0xD0 // LCD Zeile 4 / Referenz LCD Datenblatt
56
57
#define clear_display       0x01 // Clear Display
58
#define cursor_home         0x02 // Cursor Home
59
60
/* ---- Define Prototypes ------------------------------------------------------------------------------------ */
61
/*                                                                                                             */
62
extern void lcd_command (uint8_t dsp_control_out);              // Funktion für Display Steuersignale
63
extern void lcd_char (uint8_t send_char);                       // Funktion Zeichen ausgeben
64
extern void lcd_init (void);                                    // Funktion LCD Initialisieren
65
extern void lcd_puts (const char *lcd_string);                  // Funktion Display String ausgeben
66
67
#endif



1
// ---- LCD Driver Routine for 2x16 / 4x20 char. Display
2
// (c) B. Nollmeyer, WINAVR sample Routine! Das Display wird im 4 BIT Modus betrieben.
3
// ATMEL ATTINY 2313, die Routine benötigt 247 Byte inkl. Startup Code. WINAVR gcc 3.4.6
4
5
/* ---- CPU CLOCK ----------------------------------------------------------------------------- */
6
7
#ifndef F_CPU
8
#define F_CPU 3686000UL // Frequenz in Hz
9
#endif
10
11
/* ---- Include Files ------------------------------------------------------------------------- */
12
13
#include <stdint.h>                                   /* ISO C99 Integer types        */
14
#include <avr/io.h>                                   /* ATTINY I/O's                 */
15
#include <util/delay.h>                               /* delay Lib.                   */
16
#include "lcd.h"                                      /* LCD Lib.                     */
17
18
/* ---- MAIN ----------------------------------------------------------------------------------- */
19
20
int main (void)  {
21
  DDRD = (1 << DDD6)                                   // Anschluß Display ENABLE 
22
       | (1 << DDD0)                                   // Anschluß Display Datenbit DB4 
23
       | (1 << DDD1)                                   // Anschluß Display Datenbit DB5
24
       | (1 << DDD2)                                   // Anschluß Display Datenbit DB6
25
       | (1 << DDD3)                                   // Anschluß Display Datenbit DB7
26
     | (1 << DDD4);                                 // Anschluß Display RS
27
 
28
   _delay_ms (15);                                      // wait 15 mSec. after Power ON
29
  lcd_init ();                                         // Display initialisieren
30
  lcd_puts ("Hallo");                            // Display Text
31
32
  for (;;);
33
}
34
35
/* ---- Display Ausgabe String ------------------------------------------------------------------ */
36
37
void lcd_puts (const char *lcd_string)  {
38
  while (*lcd_string)  {
39
    lcd_char (*lcd_string++);                         // String auslesen und an LCD Ausgabe übergeben
40
  }
41
}
42
43
/* ---- Display Ausgabe Steuersignale ----------------------------------------------------------- */
44
45
void lcd_command (uint8_t dsp_control_out)  {    
46
  PORTD |= (1<<RS);                                  // Steuersignale an Display ausgeben (RS BIT=0)
47
  lcd_char (dsp_control_out);                         // Steuersignal ausgeben
48
  _delay_ms (4.1);                                    // Warteschleife 4,1 mSec.
49
  PORTD &= ~(1<<RS);                                          // RS BIT=1 => Daten
50
}
51
52
/* ---- Display Ausgabe Zeichen ----------------------------------------------------------------- */
53
54
void lcd_char (uint8_t send_char)
55
{
56
  uint8_t n=2;                               
57
  do  {                        // Sende 2x 4 BIT (oberes Nibble zuerst)
58
        PORTD = (PORTD & 0x0F) | (send_char & 0xF0) | (1<<RS);// Port low nibble nicht verändern
59
        PORTD|= (1<< ENABLE);                                 // ENABLE = HIGH
60
    _delay_ms(0.5);    // Impulszeit von E=High,in Doku: min 220ns
61
        PORTD &= ~(1<< ENABLE);                                  // ENABLE = LOW, Steuersignal Datenübernahme
62
        send_char <<= 4;                               // unteres Nibble nach oben schieben
63
  }while (--n);
64
  _delay_us (42);                                      // Warteschleife 42 uSec.
65
}
66
67
/* ---- Display initialisieren ------------------------------------------------------------------ */
68
69
void lcd_init (void)  {
70
  uint8_t n = 3;                                       // Init. Sequenz, Referenz LCD Datenblatt
71
  do  {                                                // 3x 33H (0x03), init cycle 3x
72
        lcd_command (0x33);                            // DB4, DB5 = 1
73
  }while (--n);
74
  lcd_command (fs1);                              // 4 Bit Modus / 2 Zeilen / 5x7 Dots
75
  lcd_command (on_off_control_1);                      // Display An / Cursor Aus / Blink Aus
76
  lcd_command (clear_display);                         // Clear Display
77
  lcd_command (entrymode_1);                           // Cursor nach rechts / kein Shift
78
}

von Stefan B. (stefan) Benutzerseite


Lesenswert?

Ähm, das
1
PORTD = (PORTD & 0x0F) | (send_char & 0xF0) | (1<<RS);

macht nicht das Gewünschte. Futschgemacht ist futsch und später 
dazugefrickelt ist falsch.
1
PORTD = (PORTD & (0x0F | (1<<RS))) | (send_char & 0xF0);

ist besser. Aber jetzt beim Drüberschauen sehe ich, das das doch sowieso 
Murks ist.

Von PORTD sollen die Bits D0-D3 für die 4 Datenleitungen vom LCD benutzt 
werden, D4 für RS und D6 für ENABLE. Genau das macht diese Zeile NICHT:
1
PORTD = (PORTD & 0x0F) | (send_char & 0xF0) | (1<<RS);

Die löscht die D7-D4 und lässt D3-D0 so wie sie sind. Dazu wird das 
obere Nibble von sendchar geodert... Murks, irgendwann ist D3 bis D0 
komplett 1.

So soll es gehen (in Einzelanweisungen)
1
PORTD  = (PORTD & 0xF0);        // D3-D0 freimachen
2
PORTD |= (send_char & 0xF0)>>4; // oberes Nibble von send_char dazu.

bzw. in einer Zeile
1
PORTD  = (PORTD & 0xF0) | (send_char & 0xF0)>>4;

von Cosi (Gast)


Lesenswert?

Hallo Stefan,
ok, stimmt, danke dir...

Aber es geht noch immer net heul
Habe schon andere ganz einfache Programme laufen lassen, nie eine 
Reaktion.

Hab die Pinbelegung bereits zig-Mal überprüft, die muss stimmen...
Vielleicht stimmt mit dem LCD was net, hmmm :(

von Cosi (Gast)


Lesenswert?

Hallo,
habe mit den Code nochmal ganz genau angeschaut und debuggt. Keine 
Fehler gefunden...

Jedoch eine Frage:
In der Display-Doku (Seite 5) steht was von CG bzw. DD RAM Adresse 
setzen...Muss ich da auch was initialisieren?

Nach dem Senden der Zeichen (im Beispiel unten: "Aa") ist da das 
zurücksetzen vom RS-Bit notwenig?

Der aktuelle Code:
1
// ---- LCD Driver Routine for 2x16 / 4x20 char. Display                                                                                                             
2
// (c) B. Nollmeyer, WINAVR sample Routine. Das Display wird im 4 BIT Modus betrieben                       
3
4
#ifndef lcd_h
5
#define lcd_h
6
7
#define HIGH 1
8
#define LOW  0
9
10
#define ENABLE 6                                  // Display Enable
11
#define RS 4                                      // Display RS BIT
12
//#define RS SBIT (PORTD, 4)
13
14
/* ---- Define Display Kommandos ----------------------------------------------------------------------------- */
15
/*                                                                                                             */
16
#define fs1 0x28 // 4 Bit Modus / 2 Zeilen / 5x7 Dots
17
#define fs2 0x2C // 4 Bit Modus / 2 Zeilen / 5x10 Dots
18
#define fs3 0x20 // 4 Bit Modus / 1 Zeile / 5x7 Dots
19
#define fs4 0x24 // 4 Bit Modus / 1 Zeile / 5x10 Dots
20
21
#define on_off_control_1    0x0C // Display An / Cursor Aus / Blink Aus
22
#define on_off_control_2    0x0E // Display An / Cursor An / Blink Aus
23
#define on_off_control_3    0x0F // Display An / Cursor An / Blink An
24
#define on_off_control_4    0x08 // Display Aus
25
26
#define entrymode_1         0x06 // Cursor nach rechts / kein Shift
27
#define entrymode_2         0x07 // Cursor nach rechts / Shift
28
#define entrymode_3         0x04 // Cursor nach links / kein Shift
29
#define entrymode_4         0x05 // Cursor nach links / Shift
30
31
#define cursor_line_1       0x00 // LCD Zeile 1 / Referenz LCD Datenblatt; 80
32
#define cursor_line_2       0x40 // LCD Zeile 2 / Referenz LCD Datenblatt; C0
33
#define cursor_line_3       0x90 // LCD Zeile 3 / Referenz LCD Datenblatt
34
#define cursor_line_4       0xD0 // LCD Zeile 4 / Referenz LCD Datenblatt
35
36
#define clear_display       0x01 // Clear Display
37
#define cursor_home         0x02 // Cursor Home
38
39
/* ---- Define Prototypes ------------------------------------------------------------------------------------ */
40
/*                                                                                                             */
41
extern void lcd_command (uint8_t dsp_control_out);              // Funktion für Display Steuersignale
42
extern void lcd_char (uint8_t send_char);                       // Funktion Zeichen ausgeben
43
extern void lcd_init (void);                                    // Funktion LCD Initialisieren
44
extern void lcd_puts (const char *lcd_string);                  // Funktion Display String ausgeben
45
46
#endif




1
// ---- LCD Driver Routine for 2x16 / 4x20 char. Display
2
// (c) B. Nollmeyer, WINAVR sample Routine! Das Display wird im 4 BIT Modus betrieben.
3
// ATMEL ATTINY 2313, die Routine benötigt 247 Byte inkl. Startup Code. WINAVR gcc 3.4.6
4
5
#ifndef F_CPU
6
#define F_CPU 3686000UL // Frequenz in Hz
7
#endif
8
9
#include <stdint.h>
10
#include <avr/io.h>
11
#include <util/delay.h>
12
#include "lcd.h"
13
14
int main (void)
15
{
16
  DDRD = (1 << DDD6)                                   // Anschluß Display ENABLE 
17
       | (1 << DDD0)                                   // Anschluß Display Datenbit DB4 
18
       | (1 << DDD1)                                   // Anschluß Display Datenbit DB5
19
       | (1 << DDD2)                                   // Anschluß Display Datenbit DB6
20
       | (1 << DDD3)                                   // Anschluß Display Datenbit DB7
21
     | (1 << DDD4);                                 // Anschluß Display RS
22
 
23
   _delay_ms (15);                                      // wait 15 mSec. after Power ON
24
  lcd_init ();                                         // Display initialisieren
25
  lcd_puts ("Aa");                            // Display Text
26
27
  for (;;);
28
}
29
30
/* ---- Display Ausgabe String ------------------------------------------------------------------ */
31
32
void lcd_puts (const char *lcd_string)
33
{
34
  while (*lcd_string)
35
  {
36
    lcd_char (*lcd_string++);                         // String auslesen und an LCD Ausgabe übergeben
37
  }
38
}
39
40
/* ---- Display Ausgabe Steuersignale ----------------------------------------------------------- */
41
42
void lcd_command (uint8_t dsp_control_out)
43
{    
44
  PORTD &= ~(1<<RS);                                  // Steuersignale an Display ausgeben (RS BIT=0)
45
  lcd_char (dsp_control_out);                         // Steuersignal ausgeben
46
  _delay_ms (4.1);                                    // Warteschleife 4,1 mSec.
47
  PORTD |= (1<<RS);                                  // RS BIT=1 => Daten
48
}
49
50
/* ---- Display Ausgabe Zeichen ----------------------------------------------------------------- */
51
52
void lcd_char (uint8_t send_char)
53
{
54
  uint8_t n=2;                               
55
  do  {                        // Sende 2x 4 BIT (oberes Nibble zuerst)
56
        PORTD  = (PORTD & 0xF0);        // D3-D0 freimachen
57
    PORTD |= (send_char & 0xF0)>>4; // oberes Nibble von send_char dazu.// Port low nibble nicht verändern
58
        PORTD|= (1<< ENABLE);                                 // ENABLE = HIGH
59
    _delay_ms(0.5);    // Impulszeit von E=High,in Doku: min 220ns
60
        PORTD &= ~(1<< ENABLE);                                  // ENABLE = LOW, Steuersignal Datenübernahme
61
        send_char <<= 4;                               // unteres Nibble nach oben schieben
62
  }while (--n);
63
  _delay_us (42);                                      // Warteschleife 42 uSec.
64
}
65
66
/* ---- Display initialisieren ------------------------------------------------------------------ */
67
68
void lcd_init (void)
69
{
70
  uint8_t n = 3;                                       // Init. Sequenz, Referenz LCD Datenblatt
71
  do  {                                                // 3x 33H (0x03), init cycle 3x
72
        lcd_command (0x30);                            // DB4, DB5 = 1
73
  }while (--n);
74
  lcd_command (fs1);                              // 4 Bit Modus / 2 Zeilen / 5x7 Dots
75
  lcd_command (on_off_control_1);                      // Display An / Cursor Aus / Blink Aus
76
  lcd_command (clear_display);                         // Clear Display
77
  lcd_command (entrymode_1);                           // Cursor nach rechts / kein Shift
78
  lcd_command (cursor_home);
79
}

Grüße, Cosi

von Cosi (Gast)


Angehängte Dateien:

Lesenswert?

In der LCD-Doku steht etwas zu den Zeiten, zu denen die E und RS-Bits 
gesetzt werden sollen...Habe ich bereits ohne Erfolg ausprobiert.

Im Tutorial wurde aber einfach zuerst RS-Bit, danach das E-Bit 
gesetzt...Die Daten liegen dabei schon an.
Das habe ich momentan so implementiert...

Vielleicht könnt ihr es kurz bei euch laufen lassen?! Ich komm echt 
nicht dahinter an was es liegen könnte...

Hab den Code auf das wesentliche abgespeckt.

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
Noch kein Account? Hier anmelden.