1
OLEDs / Problem initialising NHD-0420DZW
« on: March 19, 2014, 02:10:54 PM »
Hi guys,
I am having problems when initialising the OLED.
I am always getting a weird behaviour. Most of the times having some@ signs showing up.
Can you help me please?
main.c:
lcd-routines.h:
lcd-routines.c:
I am having problems when initialising the OLED.
I am always getting a weird behaviour. Most of the times having some@ signs showing up.
Can you help me please?
main.c:
Code: [Select]
#define F_CPU 3686400UL //uc läuft mit 3,6864 MHZ Quarz
#include <avr/io.h>
#include <avr/pgmspace.h>
#include <avr/interrupt.h>
#include "lcd-routines.h"
#include <util/delay.h>
int main(void)
{
_delay_ms(5);
lcd_init(); //LCD Initialisieren
_delay_ms(5);
lcd_string("hello world");
_delay_ms(5000);
}
lcd-routines.h:
Code: [Select]
#ifndef LCD_ROUTINES_H
#define LCD_ROUTINES_H
#include <avr/pgmspace.h>
/* LCD DB4-DB7 <--> PORTA Bit PA2-PA5
* Datenleitung am uc: PA2:DB4, PA3:DB5, PA4:DB6, PA4:DB7
*/
#define LCD_PORT PORTA
#define LCD_DDR DDRA
#define LCD_DB PA2
// LCD RS <--> PORTA Bit PA0 (RS: 0=Data, 1=Command)
#define LCD_RS PA0
// LCD EN <--> PORTA Bit PA1 (EN: 1-Impuls für Daten)
#define LCD_EN PA1
////////////////////////////////////////////////////////////////////////////////
// LCD Ausführungszeiten (MS=Millisekunden, US=Mikrosekunden)
#define LCD_BOOTUP_MS 2
#define LCD_ENABLE_US 100
#define LCD_WRITEDATA_US 1
#define LCD_COMMAND_US 1
#define LCD_BUSY_MS 1
#define LCD_CLEAR_DISPLAY_MS 2
#define LCD_CURSOR_HOME_MS 2
////////////////////////////////////////////////////////////////////////////////
// Zeilendefinitionen des LCDs
#define LCD_DDADR_LINE1 0x00
#define LCD_DDADR_LINE2 0x40
#define LCD_DDADR_LINE3 0x14
#define LCD_DDADR_LINE4 0x54
////////////////////////////////////////////////////////////////////////////////
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
void lcd_init( void );
////////////////////////////////////////////////////////////////////////////////
// LCD löschen
void lcd_clear( void );
////////////////////////////////////////////////////////////////////////////////
// Cursor in die 1. Zeile, 0-te Spalte
void lcd_home( void );
////////////////////////////////////////////////////////////////////////////////
// Cursor an eine beliebige Position
void lcd_setcursor( uint8_t spalte, uint8_t zeile );
////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines einzelnen Zeichens an der aktuellen Cursorposition
void lcd_data( uint8_t data );
////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines Strings an der aktuellen Cursorposition
// String liegt im RAM
void lcd_string( const char *data );
////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines Strings an der aktuellen Cursorposition
// String liegt im Flash
void lcd_string_P( PGM_P data );
////////////////////////////////////////////////////////////////////////////////
// Definition eines benutzerdefinierten Sonderzeichens.
// data muss auf ein Array[8] mit den Zeilencodes des zu definierenden Zeichens
// zeigen, Daten liegen im RAM
void lcd_generatechar( uint8_t code, const uint8_t *data );
////////////////////////////////////////////////////////////////////////////////
// Definition eines benutzerdefinierten Sonderzeichens.
// data muss auf ein Array[8] mit den Zeilencodes des zu definierenden Zeichens
// zeigen, Daten liegen im FLASH
void lcd_generatechar_P( uint8_t code, PGM_P data );
////////////////////////////////////////////////////////////////////////////////
// Ausgabe eines Kommandos an das LCD.
void lcd_command( uint8_t data );
////////////////////////////////////////////////////////////////////////////////
// LCD Befehle und Argumente.
// Zur Verwendung in lcd_command
// Clear Display -------------- 0b00000001
#define LCD_CLEAR_DISPLAY 0x01
// Cursor Home ---------------- 0b0000001x
#define LCD_CURSOR_HOME 0x02
// Set Entry Mode ------------- 0b000001xx
#define LCD_SET_ENTRY 0x04
#define LCD_ENTRY_DECREASE 0x00
#define LCD_ENTRY_INCREASE 0x02
#define LCD_ENTRY_NOSHIFT 0x00
#define LCD_ENTRY_SHIFT 0x01
// Set Display ---------------- 0b00001xxx
#define LCD_SET_DISPLAY 0x08
#define LCD_DISPLAY_OFF 0x00
#define LCD_DISPLAY_ON 0x04
#define LCD_CURSOR_OFF 0x00
#define LCD_CURSOR_ON 0x02
#define LCD_BLINKING_OFF 0x00
#define LCD_BLINKING_ON 0x01
// Set Shift ------------------ 0b0001xxxx
#define LCD_SET_SHIFT 0x10
#define LCD_CURSOR_MOVE 0x00
#define LCD_DISPLAY_SHIFT 0x08
#define LCD_SHIFT_LEFT 0x00
#define LCD_SHIFT_RIGHT 0x01
// Set Function --------------- 0b001xxxxx
#define LCD_SET_FUNCTION 0x20
#define LCD_FUNCTION_4BIT 0x00
#define LCD_FUNCTION_8BIT 0x10
#define LCD_FT_Engl_Jap 0x08
#define LCD_FT_WEurop1 0x09
#define LCD_FT_Engl_Russ 0x0A
#define LCD_FT_WEurop2 0x0B
#define LCD_SOFT_RESET 0x30
// Set CG RAM Address --------- 0b01xxxxxx (Character Generator RAM)
#define LCD_SET_CGADR 0x40
#define LCD_GC_CHAR0 0
#define LCD_GC_CHAR1 1
#define LCD_GC_CHAR2 2
#define LCD_GC_CHAR3 3
#define LCD_GC_CHAR4 4
#define LCD_GC_CHAR5 5
#define LCD_GC_CHAR6 6
#define LCD_GC_CHAR7 7
// Set DD RAM Address --------- 0b1xxxxxxx (Display Data RAM)
#define LCD_SET_DDADR 0x80
#endif
lcd-routines.c:
Code: [Select]
#include <avr/io.h>
#include "lcd-routines.h"
#include <util/delay.h>
/////////////////////////////////////////////////////////////////////////////////
// Erzeugt einen Enable-Puls
static void lcd_enable( void ) {
LCD_PORT |= (1<<LCD_EN); // Enable auf 1 setzen
_delay_us( LCD_ENABLE_US ); // kurze Pause
LCD_PORT &= ~(1<<LCD_EN); // Enable auf 0 setzen
}
////////////////////////////////////////////////////////////////////////////////
// Sendet eine 4-bit Ausgabeoperation an das LCD
static void lcd_out( uint8_t data ) {
data &= 0xF0; // obere 4 Bit maskieren
LCD_PORT &= ~(0xF0>>(4-LCD_DB)); // Maske löschen
LCD_PORT |= (data>>(4-LCD_DB)); // Bits setzen
_delay_us(100);
lcd_enable();
}
////////////////////////////////////////////////////////////////////////////////
// Initialisierung: muss ganz am Anfang des Programms aufgerufen werden.
void lcd_init( void ) {
_delay_ms(LCD_BOOTUP_MS);
lcd_out(LCD_SET_FUNCTION);
_delay_us(LCD_COMMAND_US);
lcd_command(LCD_SET_FUNCTION|LCD_FUNCTION_4BIT|LCD_FT_Engl_Jap);
_delay_ms(LCD_BUSY_MS);
lcd_command(LCD_SET_DISPLAY|LCD_DISPLAY_OFF|LCD_CURSOR_OFF|LCD_BLINKING_OFF);
_delay_ms(LCD_BUSY_MS);
lcd_command(LCD_CLEAR_DISPLAY);
_delay_ms(LCD_BUSY_MS);
lcd_command(LCD_SET_ENTRY|LCD_ENTRY_INCREASE|LCD_ENTRY_NOSHIFT);
_delay_ms(LCD_BUSY_MS);
lcd_command(LCD_CURSOR_HOME);
_delay_ms(LCD_BUSY_MS);
lcd_command(LCD_SET_DISPLAY|LCD_DISPLAY_ON|LCD_CURSOR_OFF|LCD_BLINKING_OFF);
_delay_ms(LCD_BUSY_MS);
}
////////////////////////////////////////////////////////////////////////////////
// Sendet ein Datenbyte an das LCD
void lcd_data( uint8_t data ) {
LCD_PORT |= (1<<LCD_RS); // RS auf 1 setzen
lcd_out( data ); // zuerst die oberen,
lcd_out( data<<4 ); // dann die unteren 4 Bit senden
_delay_us( LCD_WRITEDATA_US );
}
////////////////////////////////////////////////////////////////////////////////
// Sendet einen Befehl an das LCD
void lcd_command( uint8_t data ) {
LCD_PORT &= ~(1<<LCD_RS); // RS auf 0 setzen
lcd_out( data ); // zuerst die oberen,
lcd_out( data<<4); // dann die unteren 4 Bit senden
_delay_us(LCD_COMMAND_US );
}
////////////////////////////////////////////////////////////////////////////////
// Sendet den Befehl zur Löschung des Displays
void lcd_clear( void ) {
lcd_command( LCD_CLEAR_DISPLAY );
_delay_ms( LCD_CLEAR_DISPLAY_MS );
}
////////////////////////////////////////////////////////////////////////////////
// Sendet den Befehl: Cursor Home
void lcd_home( void ) {
lcd_command( LCD_CURSOR_HOME );
_delay_ms( LCD_CURSOR_HOME_MS );
}
////////////////////////////////////////////////////////////////////////////////
// Setzt den Cursor in Zeile y (0..3) Spalte x (0..15)
void lcd_setcursor( uint8_t x, uint8_t y ) {
uint8_t data;
switch (y) {
case 0: // 1. Zeile
data = LCD_SET_DDADR + LCD_DDADR_LINE1 + x;
break;
case 1: // 2. Zeile
data = LCD_SET_DDADR + LCD_DDADR_LINE2 + x;
break;
case 2: // 3. Zeile
data = LCD_SET_DDADR + LCD_DDADR_LINE3 + x;
break;
case 3: // 4. Zeile
data = LCD_SET_DDADR + LCD_DDADR_LINE4 + x;
break;
default:
return; // für den Fall einer falschen Zeile
}
lcd_command( data );
}
////////////////////////////////////////////////////////////////////////////////
// Schreibt einen String auf das LCD
void lcd_string( const char *data ) {
while( *data != '\0' )
lcd_data( *data++ );
}
////////////////////////////////////////////////////////////////////////////////
// Schreibt einen String auf das LCD
// String liegt direkt im Flash Speicher
void lcd_string_P( PGM_P data ) {
uint8_t tmp;
tmp=pgm_read_byte(data);
while( tmp != '\0' ) {
lcd_data( tmp );
data++;
tmp = pgm_read_byte(data);
}
}
////////////////////////////////////////////////////////////////////////////////
// Schreibt ein Zeichen in den Character Generator RAM
// Daten liegen direkt im RAM
void lcd_generatechar( uint8_t code, const uint8_t *data ) {
uint8_t i;
// Startposition des Zeichens einstellen
lcd_command( LCD_SET_CGADR | (code<<3) );
// Bitmuster übertragen
for ( i=0; i<8; i++ ) {
lcd_data( *data);
data++;
}
}
////////////////////////////////////////////////////////////////////////////////
// Schreibt ein Zeichen in den Character Generator RAM
// Daten liegen direkt im Flash-Speicher
void lcd_generatechar_P( uint8_t code, PGM_P data ) {
uint8_t i;
// Startposition des Zeichens einstellen
lcd_command( LCD_SET_CGADR | (code<<3) );
// Bitmuster übertragen
for ( i=0; i<8; i++ ) {
lcd_data( pgm_read_byte(data) );
data++;
}
}