von
Dave (Gast)
01.08.2007 22:24
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)
01.08.2007 23:13
Beitrag "Wie mache ich eine Textausgabe 8Bit auf Display?"
Ist ausführlich erklärt und am Ende des Threads gibts nen Code zum
Testen.
Schon mal am Kontrastpoti rumgespielt?
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)
10.08.2007 11:15
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)
10.08.2007 13:04
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 3 x
111 lcd_command ( 0x30 ); // DB4, DB5 = 1
112 } while ( -- n );
113 lcd_command ( fs1 ); // 4 Bit Modus / 2
114 Zeilen / 5 x7 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)
10.08.2007 13:12
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
@ 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)
10.08.2007 14:33
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)
10.08.2007 15:05
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 }
Ä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)
10.08.2007 17:10
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)
13.08.2007 10:24
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)
13.08.2007 13:39
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.