Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - chunsen

Pages: [1]
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:
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++;
    }
}

Pages: [1]