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
  lcd_out(LCD_SOFT_SET);
58
  _delay_ms(1);
59
  
60
  lcd_out(LCD_SET_DISPLAY |
61
  LCD_DISPLAY_OFF);  
62
  _delay_ms(1);
63
  
64
  lcd_clear();
65
  
66
  lcd_out(LCD_SET_ENTRY |
67
  LCD_ENTRY_INCREASE);
68
  _delay_ms(1);
69
  /********************INIT DONE********************************************/
70
    
71
   // 4-bit Modus aktivieren
72
   lcd_out( LCD_SET_FUNCTION |
73
   LCD_FUNCTION_4BIT );
74
   _delay_ms( LCD_SET_4BITMODE_MS );
75
 
76
     // 4-bit Modus / 2 Zeilen / 5x7
77
     lcd_command( LCD_SET_FUNCTION |
78
     LCD_FUNCTION_4BIT |
79
     LCD_FUNCTION_2LINE |
80
     LCD_FUNCTION_5X7 );
81
   
82
    // Display ein / Cursor aus / Blinken aus
83
    lcd_command( LCD_SET_DISPLAY |
84
    LCD_DISPLAY_ON |
85
    LCD_CURSOR_ON |
86
    LCD_BLINKING_ON);
87
    
88
    // Cursor inkrement / kein Scrollen
89
    lcd_command( LCD_SET_ENTRY |
90
    LCD_ENTRY_INCREASE |
91
    LCD_ENTRY_NOSHIFT );
92
    lcd_clear();
93
}
94
  
95
////////////////////////////////////////////////////////////////////////////////
96
// Sendet ein Datenbyte an das LCD
97
void lcd_data( uint8_t data )
98
{
99
    LCD_PORT |= (1<<LCD_RS);    // RS auf 1 setzen
100
 
101
    lcd_out( data );            // zuerst die oberen, 
102
    lcd_out( data<<4 );         // dann die unteren 4 Bit senden
103
 
104
    _delay_us( LCD_WRITEDATA_US );
105
}
106
 
107
////////////////////////////////////////////////////////////////////////////////
108
// Sendet einen Befehl an das LCD
109
void lcd_command( uint8_t data )
110
{
111
    LCD_PORT &= ~(1<<LCD_RS);    // RS auf 0 setzen
112
 
113
    lcd_out( data );             // zuerst die oberen, 
114
    lcd_out( data<<4 );           // dann die unteren 4 Bit senden
115
 
116
    _delay_us( LCD_COMMAND_US );
117
}
118
 
119
////////////////////////////////////////////////////////////////////////////////
120
// Sendet den Befehl zur Löschung des Displays
121
void lcd_clear( void )
122
{
123
    lcd_command( LCD_CLEAR_DISPLAY );
124
    _delay_ms( LCD_CLEAR_DISPLAY_MS );
125
}
126
 
127
////////////////////////////////////////////////////////////////////////////////
128
// Sendet den Befehl: Cursor Home
129
void lcd_home( void )
130
{
131
    lcd_command( LCD_CURSOR_HOME );
132
    _delay_ms( LCD_CURSOR_HOME_MS );
133
}
134
 
135
////////////////////////////////////////////////////////////////////////////////
136
// Setzt den Cursor in Spalte x (0..15) Zeile y (1..4) 
137
 
138
void lcd_setcursor( uint8_t x, uint8_t y )
139
{
140
    uint8_t data;
141
 
142
    switch (y)
143
    {
144
        case 1:    // 1. Zeile
145
            data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
146
            break;
147
 
148
        case 2:    // 2. Zeile
149
            data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
150
            break;
151
 
152
        case 3:    // 3. Zeile
153
            data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x;
154
            break;
155
 
156
        case 4:    // 4. Zeile
157
            data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x;
158
            break;
159
 
160
        default:
161
            return;                                   // für den Fall einer falschen Zeile
162
    }
163
 
164
    lcd_command( data );
165
}
166
 
167
////////////////////////////////////////////////////////////////////////////////
168
// Schreibt einen String auf das LCD
169
 
170
void lcd_string( const char *data )
171
{
172
    while( *data != '\0' )
173
        lcd_data( *data++ );
174
}
175
 
176
////////////////////////////////////////////////////////////////////////////////
177
// Schreibt ein Zeichen in den Character Generator RAM
178
 
179
void lcd_generatechar( uint8_t code, const uint8_t *data )
180
{
181
    // Startposition des Zeichens einstellen
182
    lcd_command( LCD_SET_CGADR | (code<<3) );
183
 
184
    // Bitmuster übertragen
185
    for ( uint8_t i=0; i<8; i++ )
186
    {
187
        lcd_data( data[i] );
188
    }
189
}