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
}