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
}