Forum: Mikrocontroller und Digitale Elektronik Pollin TC1602E-01


von Hendrik (Gast)


Lesenswert?

Hallo!

Ich versuche gerade das Beispiel AVR-GCC-Tutorial/LCD-Ansteuerung 
nachzubauen. Leider bisher noch ohne Erfolg.

Zu meinem Aufbau:

- AtMega8 16PU steckt auf Pollin Atmel Evaluations-Board Version 2.0.1. 
.
- Das Pollin LCD TC1602E-01 ist über dem 40 Poligen stecker wie folgt 
angeschlossen:

Vdd->5V  Pin 40
Vss->GND Pin 39
RS->PD4  Pin 30
R/W->GND Pin 39
E->PD5   Pin 31
DB4->PD0 Pin 26
DB5->PD1 Pin 27
DB6->PD2 Pin 28
DB7->PD3 Pin 29

Ich habe im AVR-Studio ein neues Projekt erstellt mit drei Outputfiles:

AVRGCC6.c
1
#include <avr/io.h>
2
#include "lcd-routines.h"
3
 
4
int main(void)
5
{
6
  // Initialisierung des LCD
7
  // Nach der Initialisierung müssen auf dem LCD vorhandene schwarze Balken
8
  // verschwunden sein
9
  lcd_init();
10
  
11
 
12
  // Text in einzelnen Zeichen ausgeben
13
  lcd_data( 'T' );
14
  lcd_data( 'e' );
15
  lcd_data( 's' );
16
  lcd_data( 't' );
17
 
18
  // Die Ausgabemarke in die 2te Zeile setzen
19
  lcd_setcursor( 0, 2 );
20
 
21
  // erneut Text ausgeben, aber diesmal komfortabler als String
22
  lcd_string("Hello World!");
23
 
24
  while(1)
25
  {
26
  }
27
 
28
  return 0;
29
}
lcd-routines.h
1
// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
2
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
3
//
4
 
5
#ifndef LCD_ROUTINES_H
6
#define LCD_ROUTINES_H
7
 
8
////////////////////////////////////////////////////////////////////////////////
9
// Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!
10
 
11
#ifndef F_CPU
12
#define F_CPU 16000000
13
#endif
14
 
15
////////////////////////////////////////////////////////////////////////////////
16
// Pinbelegung für das LCD, an verwendete Pins anpassen
17
// Alle LCD Pins müssen an einem Port angeschlossen sein und die 4
18
// Datenleitungen müssen auf aufeinanderfolgenden Pins liegen
19
 
20
//  LCD DB4-DB7 <-->  PORTD Bit PD0-PD3
21
#define LCD_PORT      PORTD
22
#define LCD_DDR       DDRD
23
#define LCD_DB        PD0
24
 
25
//  LCD RS      <-->  PORTD Bit PD4     (RS: 1=Data, 0=Command)
26
#define LCD_RS        PD4
27
 
28
//  LCD EN      <-->  PORTD Bit PD5     (EN: 1-Impuls für Daten)
29
#define LCD_EN        PD5
30
 
31
////////////////////////////////////////////////////////////////////////////////
32
// LCD Ausführungszeiten (MS=Millisekunden, US=Mikrosekunden)
33
 
34
#define LCD_BOOTUP_MS           15
35
#define LCD_ENABLE_US           20
36
#define LCD_WRITEDATA_US        46
37
#define LCD_COMMAND_US          42
38
 
39
#define LCD_SOFT_RESET_MS1      5
40
#define LCD_SOFT_RESET_MS2      1
41
#define LCD_SOFT_RESET_MS3      1
42
#define LCD_SET_4BITMODE_MS     5
43
 
44
#define LCD_CLEAR_DISPLAY_MS    2
45
#define LCD_CURSOR_HOME_MS      2
46
 
47
////////////////////////////////////////////////////////////////////////////////
48
// Zeilendefinitionen des verwendeten LCD
49
// Die Einträge hier sollten für ein LCD mit einer Zeilenlänge von 16 Zeichen passen
50
// Bei anderen Zeilenlängen müssen diese Einträge angepasst werden
51
 
52
#define LCD_DDADR_LINE1         0x00
53
#define LCD_DDADR_LINE2         0x40
54
#define LCD_DDADR_LINE3         0x10
55
#define LCD_DDADR_LINE4         0x50
56
 
57
////////////////////////////////////////////////////////////////////////////////
58
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
59
void lcd_init( void );
60
 
61
////////////////////////////////////////////////////////////////////////////////
62
// LCD löschen
63
void lcd_clear( void );
64
 
65
////////////////////////////////////////////////////////////////////////////////
66
// Cursor in die 1. Zeile, 0-te Spalte
67
void lcd_home( void );
68
 
69
////////////////////////////////////////////////////////////////////////////////
70
// Cursor an eine beliebige Position 
71
void lcd_setcursor( uint8_t spalte, uint8_t zeile );
72
 
73
////////////////////////////////////////////////////////////////////////////////
74
// Ausgabe eines einzelnen Zeichens an der aktuellen Cursorposition 
75
void lcd_data( uint8_t data );
76
 
77
////////////////////////////////////////////////////////////////////////////////
78
// Ausgabe eines Strings an der aktuellen Cursorposition 
79
void lcd_string( const char *data );
80
 
81
////////////////////////////////////////////////////////////////////////////////
82
// Definition eines benutzerdefinierten Sonderzeichens.
83
// data muss auf ein Array[5] mit den Spaltencodes des zu definierenden Zeichens
84
// zeigen
85
void lcd_generatechar( uint8_t code, const uint8_t *data );
86
 
87
////////////////////////////////////////////////////////////////////////////////
88
// Ausgabe eines Kommandos an das LCD.
89
void lcd_command( uint8_t data );
90
 
91
 
92
////////////////////////////////////////////////////////////////////////////////
93
// LCD Befehle und Argumente.
94
// Zur Verwendung in lcd_command
95
 
96
// Clear Display -------------- 0b00000001
97
#define LCD_CLEAR_DISPLAY       0x01
98
 
99
// Cursor Home ---------------- 0b0000001x
100
#define LCD_CURSOR_HOME         0x02
101
 
102
// Set Entry Mode ------------- 0b000001xx
103
#define LCD_SET_ENTRY           0x04
104
 
105
#define LCD_ENTRY_DECREASE      0x00
106
#define LCD_ENTRY_INCREASE      0x02
107
#define LCD_ENTRY_NOSHIFT       0x00
108
#define LCD_ENTRY_SHIFT         0x01
109
 
110
// Set Display ---------------- 0b00001xxx
111
#define LCD_SET_DISPLAY         0x08
112
 
113
#define LCD_DISPLAY_OFF         0x00
114
#define LCD_DISPLAY_ON          0x04
115
#define LCD_CURSOR_OFF          0x00
116
#define LCD_CURSOR_ON           0x02
117
#define LCD_BLINKING_OFF        0x00
118
#define LCD_BLINKING_ON         0x01
119
 
120
// Set Shift ------------------ 0b0001xxxx
121
#define LCD_SET_SHIFT           0x10
122
 
123
#define LCD_CURSOR_MOVE         0x00
124
#define LCD_DISPLAY_SHIFT       0x08
125
#define LCD_SHIFT_LEFT          0x00
126
#define LCD_SHIFT_RIGHT         0x04
127
 
128
// Set Function --------------- 0b001xxxxx
129
#define LCD_SET_FUNCTION        0x20
130
 
131
#define LCD_FUNCTION_4BIT       0x00
132
#define LCD_FUNCTION_8BIT       0x10
133
#define LCD_FUNCTION_1LINE      0x00
134
#define LCD_FUNCTION_2LINE      0x08
135
#define LCD_FUNCTION_5X7        0x00
136
#define LCD_FUNCTION_5X10       0x04
137
 
138
#define LCD_SOFT_RESET          0x30
139
 
140
// Set CG RAM Address --------- 0b01xxxxxx  (Character Generator RAM)
141
#define LCD_SET_CGADR           0x40
142
 
143
#define LCD_GC_CHAR0            0
144
#define LCD_GC_CHAR1            1
145
#define LCD_GC_CHAR2            2
146
#define LCD_GC_CHAR3            3
147
#define LCD_GC_CHAR4            4
148
#define LCD_GC_CHAR5            5
149
#define LCD_GC_CHAR6            6
150
#define LCD_GC_CHAR7            7
151
 
152
// Set DD RAM Address --------- 0b1xxxxxxx  (Display Data RAM)
153
#define LCD_SET_DDADR           0x80
154
 
155
#endif
und lcd-routines.c
1
// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
2
// http://www.mikrocontroller.net/articles/HD44780
3
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung
4
//
5
// Die Pinbelegung ist über defines in lcd-routines.h einstellbar
6
 
7
#include <avr/io.h>
8
#include "lcd-routines.h"
9
#include <util/delay.h>
10
 
11
////////////////////////////////////////////////////////////////////////////////
12
// Erzeugt einen Enable-Puls
13
static void lcd_enable( void )
14
{
15
    LCD_PORT |= (1<<LCD_EN);     // Enable auf 1 setzen
16
    _delay_us( LCD_ENABLE_US );  // kurze Pause
17
    LCD_PORT &= ~(1<<LCD_EN);    // Enable auf 0 setzen
18
}
19
 
20
////////////////////////////////////////////////////////////////////////////////
21
// Sendet eine 4-bit Ausgabeoperation an das LCD
22
static void lcd_out( uint8_t data )
23
{
24
    data &= 0xF0;                       // obere 4 Bit maskieren
25
 
26
    LCD_PORT &= ~(0xF0>>(4-LCD_DB));    // Maske löschen
27
    LCD_PORT |= (data>>(4-LCD_DB));     // Bits setzen
28
    lcd_enable();
29
}
30
 
31
////////////////////////////////////////////////////////////////////////////////
32
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
33
void lcd_init( void )
34
{
35
    // verwendete Pins auf Ausgang schalten
36
    uint8_t pins = (0x0F << LCD_DB) |           // 4 Datenleitungen
37
                   (1<<LCD_RS) |                // R/S Leitung
38
                   (1<<LCD_EN);                 // Enable Leitung
39
    LCD_DDR |= pins;
40
 
41
    // initial alle Ausgänge auf Null
42
    LCD_PORT &= ~pins;
43
 
44
    // warten auf die Bereitschaft des LCD
45
    _delay_ms( LCD_BOOTUP_MS );
46
    
47
    // Soft-Reset muss 3mal hintereinander gesendet werden zur Initialisierung
48
    lcd_out( LCD_SOFT_RESET );
49
    _delay_ms( LCD_SOFT_RESET_MS1 );
50
 
51
    lcd_enable();
52
    _delay_ms( LCD_SOFT_RESET_MS2 );
53
 
54
    lcd_enable();
55
    _delay_ms( LCD_SOFT_RESET_MS3 );
56
 
57
    // 4-bit Modus aktivieren 
58
    lcd_out( LCD_SET_FUNCTION |
59
             LCD_FUNCTION_4BIT );
60
    _delay_ms( LCD_SET_4BITMODE_MS );
61
 
62
    // 4-bit Modus / 2 Zeilen / 5x7
63
    lcd_command( LCD_SET_FUNCTION |
64
                 LCD_FUNCTION_4BIT |
65
                 LCD_FUNCTION_2LINE |
66
                 LCD_FUNCTION_5X7 );
67
 
68
    // Display ein / Cursor aus / Blinken aus
69
    lcd_command( LCD_SET_DISPLAY |
70
                 LCD_DISPLAY_ON |
71
                 LCD_CURSOR_OFF |
72
                 LCD_BLINKING_OFF); 
73
 
74
    // Cursor inkrement / kein Scrollen
75
    lcd_command( LCD_SET_ENTRY |
76
                 LCD_ENTRY_INCREASE |
77
                 LCD_ENTRY_NOSHIFT );
78
 
79
    lcd_clear();
80
}
81
  
82
////////////////////////////////////////////////////////////////////////////////
83
// Sendet ein Datenbyte an das LCD
84
void lcd_data( uint8_t data )
85
{
86
    LCD_PORT |= (1<<LCD_RS);    // RS auf 1 setzen
87
 
88
    lcd_out( data );            // zuerst die oberen, 
89
    lcd_out( data<<4 );         // dann die unteren 4 Bit senden
90
 
91
    _delay_us( LCD_WRITEDATA_US );
92
}
93
 
94
////////////////////////////////////////////////////////////////////////////////
95
// Sendet einen Befehl an das LCD
96
void lcd_command( uint8_t data )
97
{
98
    LCD_PORT &= ~(1<<LCD_RS);    // RS auf 0 setzen
99
 
100
    lcd_out( data );             // zuerst die oberen, 
101
    lcd_out( data<<4 );           // dann die unteren 4 Bit senden
102
 
103
    _delay_us( LCD_COMMAND_US );
104
}
105
 
106
////////////////////////////////////////////////////////////////////////////////
107
// Sendet den Befehl zur Löschung des Displays
108
void lcd_clear( void )
109
{
110
    lcd_command( LCD_CLEAR_DISPLAY );
111
    _delay_ms( LCD_CLEAR_DISPLAY_MS );
112
}
113
 
114
////////////////////////////////////////////////////////////////////////////////
115
// Sendet den Befehl: Cursor Home
116
void lcd_home( void )
117
{
118
    lcd_command( LCD_CURSOR_HOME );
119
    _delay_ms( LCD_CURSOR_HOME_MS );
120
}
121
 
122
////////////////////////////////////////////////////////////////////////////////
123
// Setzt den Cursor in Spalte x (0..15) Zeile y (1..4) 
124
 
125
void lcd_setcursor( uint8_t x, uint8_t y )
126
{
127
    uint8_t data;
128
 
129
    switch (y)
130
    {
131
        case 1:    // 1. Zeile
132
            data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
133
            break;
134
 
135
        case 2:    // 2. Zeile
136
            data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
137
            break;
138
 
139
        case 3:    // 3. Zeile
140
            data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x;
141
            break;
142
 
143
        case 4:    // 4. Zeile
144
            data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x;
145
            break;
146
 
147
        default:
148
            return;                                   // für den Fall einer falschen Zeile
149
    }
150
 
151
    lcd_command( data );
152
}
153
 
154
////////////////////////////////////////////////////////////////////////////////
155
// Schreibt einen String auf das LCD
156
 
157
void lcd_string( const char *data )
158
{
159
    while( *data != '\0' )
160
        lcd_data( *data++ );
161
}
162
 
163
////////////////////////////////////////////////////////////////////////////////
164
// Schreibt ein Zeichen in den Character Generator RAM
165
 
166
void lcd_generatechar( uint8_t code, const uint8_t *data )
167
{
168
    // Startposition des Zeichens einstellen
169
    lcd_command( LCD_SET_CGADR | (code<<3) );
170
 
171
    // Bitmuster übertragen
172
    for ( uint8_t i=0; i<8; i++ )
173
    {
174
        lcd_data( data[i] );
175
    }
176
}

Diese übertrage ich mit My Avr ProgTool. Da das Board einen externen 
Quarz besitzt, habe ich die Fusebits mit My Avr ProgTool angepasst.

Im eingeschalteten Zustand ist auf dem Display nix zu sehen. Drücke ich 
den Resettaster erscheinen schwarze Balken auf dem Display die nach 
loslassen des Taster wieder verschwinden. Ist dies ein Hinweis das die 
lcd_init(); funktioniert? Warum wird das "Test" nicht ausgegeben?

Vielen Dank im Voraus!!!

von Mobilist (Gast)


Lesenswert?

Hendrik schrieb:
> Ich habe im AVR-Studio ein neues Projekt erstellt mit drei Outputfiles:

Funktioniert bei dir die Funktion für Dateianhänge nicht? Wer soll denn 
da durchscrollen?

von Hendrik (Gast)


Angehängte Dateien:

Lesenswert?

Hier ein Bild:

von Hendrik (Gast)


Angehängte Dateien:

Lesenswert?

Entschuldigt falsches Bild!

von Knut O. (Gast)


Lesenswert?

Kann man bei dir Marzipan günstiger bekommen?

von hinz (Gast)


Lesenswert?

Hendrik schrieb:
> Entschuldigt falsches Bild!

Das Display sieht aber recht kaputt aus, undicht geworden.

von Hendrik (Gast)


Lesenswert?

hinz schrieb:
> Hendrik schrieb:
>> Entschuldigt falsches Bild!
>
> Das Display sieht aber recht kaputt aus, undicht geworden.

Nein ist nagelneu. Sind Spiegeleffekte durch die noch nicht entfernte 
Schutzfolie.

von spess53 (Gast)


Lesenswert?

Hi

> Das Pollin LCD TC1602E-01 ist über dem 40 Poligen stecker wie folgt
>angeschlossen:

Ich vermisse die Kontrastspannung.

MfG Spess

von Hendrik (Gast)


Lesenswert?

spess53 schrieb:
> Hi
>
>> Das Pollin LCD TC1602E-01 ist über dem 40 Poligen stecker wie folgt
>>angeschlossen:
>
> Ich vermisse die Kontrastspannung.
>
> MfG Spess

ist jetzt dran -> keine Verbesserung

von spess53 (Gast)


Lesenswert?

Hi

>ist jetzt dran -> keine Verbesserung

Wie?

MfG Spess

von Hendrik (Gast)


Lesenswert?

spess53 schrieb:
> Hi
>
>>ist jetzt dran -> keine Verbesserung
>
> Wie?
>
> MfG Spess

Ein Poti zwischen VDD Pin 38 und VSS Pin 37 mit dem Mittelabgriff an VO.

Mit dem Kontrast scheint es aber keine Probleme zu geben da ich ja beim 
Reset schwarze Balken sehe. Oder ist das falsch gedacht?

von Hendrik (Gast)


Lesenswert?

Keiner ne Idee was ich noch mal prüfen könnte?

von Knut O. (Gast)


Lesenswert?

Kein Marzipan :-(
Was du machen könntest:
Lade dir von pollin die Software vom "Bausatz ATMEL Addon-Board V1.0" 
runter. Dadrin ist ein BASCOM Programm, welches auch ein LCD ansteuert. 
Das zugehörige PDF klärt dich über die notwendigen Pinbelegungen auf, 
die du auch über den 40pol. Pin-Header vom Evaluation Board erreichen 
kannst. Ein Kompilat für den mega8 (ADDON-TESTM8.HEX) ist auch im 
ZIP-File, falls du nicht über BASCOM verfügst. Habe ich bei mir 
getestet, es funktioniert. Damit kannst du rausfinden, ob es an deiner 
Software liegt, dass es nicht geht.

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.