mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Atmel Addonboard - LCD ansteuerung


Autor: Mathias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

ich hin gerade dabei mich in LCD - Routinen einzuarbeiten. Genauer bin 
ich ganz am Anfang...

Ich habe mir ein

- Atmel Evaluaion Board V2.01
- Atmel Addon Board V1.0
- AVR Dragon besorgt
- ATMega 16

Das "System funktioniert" ich kann auf den uC zugreifen und ihn 
programmieren.

Mein Ziel ist ADC - Werte am Display auszugeben. ADC Wandlung 
funktioniert bereits sehr genau.

Kann mir jemand ein kurzes Programm für die LCD - Ansteuerung zur 
Verfügung stellen mit dem ich meine ersten Schritte laufen kann...

Irgendwie komme ich mit dem Tutorial auf dieser Seite nicht zurecht. Der 
Kompiler gibt lauter Fehler aus.

Vielen Dank

Autor: Mathias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Habs vergessen.

Ich benutze das AVR-Studio.

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
1 lesenswert
nicht lesenswert
Mit einem atmega8 gelaufen...

Die Jumper auf dem Addon-Board sind alle offen zu lassen, stattdessen
Kabel stecken, wie im Kommentar beschrieben!

Hauptprogramm:
// Time-stamp: "29.06.09 11:04 pollin_evalboard_addon_LCD2x16.c klaus@wachtler.de"
//
// Testprogramm für LCD auf Pollin-Addon-Board zum
// Pollin-AVR-Evaluationboard oder frei verdrahtet im 4-bit-Modus
// lt. www.mikrocontroller.net.
//
// Auf dem Addon-Board ist ein LCD 2x16 mit HDC44780.
// Anschluß (Jumperleiste 1:1 gesteckt):
//
// Folgende Kabel auf Addon-Board stecken:
// - PA1 (ATMega8: PC0)   -> LCD DB4
// - PA2 (ATMega8: PC1)   -> LCD DB5
// - PA3 (ATMega8: PC2)   -> LCD DB6
// - PA4 (ATMega8: PC3)   -> LCD DB7
// - PA5 (ATMega8: PC4)   -> LCD RS
// - PA6 (ATMega8: PC5)   -> LCD E
// - GND                  -> R/W
//
// Bei freier Verdrahtung müssen folgende Verbindungen existieren:
//           LCD                                            AVR
//       VSS  1-----GND
//       VDD  2-----+5V
//       VEE  3--Abgriff Poti 10k zw. GND und +5V
//        RS  4---------------------------------------------LCD-RS PC4
//       R/W  5-----GND
//         E  6---------------------------------------------LCD-E  PC5
//       DB0  7-NC
//       DB1  8-NC
//       DB2  9-NC
//       DB3 10-NC
//       DB4 11---------------------------------------------LCD-DB4 PC0
//       DB5 12---------------------------------------------LCD-DB5 PC1
//       DB6 13---------------------------------------------LCD-DB6 PC2
//       DB7 14---------------------------------------------LCD-DB7 PC3
//     LED-A 15--R 220Ohm--+5V
//     LED-K 15-----GND
//
//
//   ATMega8:
//
//                   +---------+
//     (/Reset)  PC6-|  1   28 |-PC5 (ADC5/SCL)
//        (RxD)  PD0-|  2   27 |-PC4 (ADC4/SDA)
//        (TxD)  PD1-|  3   26 |-PC3 (ADC3)
//       (INT0)  PD2-|  4   25 |-PC2 (ADC2)
//       (INT1)  PD3-|  5   24 |-PC1 (ADC1
//     (XCK/T0)  PD4-|  6   23 |-PC0 (ADC0)
//               VCC-|  7   22 |-GND
//               GND-|  8   21 |-AREF
// (XTAL1/TOSC1) PB6-|  9   20 |-AVCC
// (XTAL2/TOSC2) PB7-| 10   19 |-PB5 (SCK)
//          (T1) PD5-| 11   18 |-PB4 (MISO)
//        (AIN0) PD6-| 12   17 |-PB3 (MOSI/OC2)
//        (AIN1) PD7-| 13   16 |-PB2 (SS/OC1B)
//        (ICB1) PB0-| 14   15 |-PB1 (OC1A)
//                   +---------+
//
//
// avrdude -c stk200 -p m8  -P /dev/parport0 -U hfuse:r:high.txt:b
// -> 0b11001001
//         + CKOPT=0
//
// avrdude -c stk200 -p m8  -P /dev/parport0 -U lfuse:r:low.txt:b
// -> 0b11111111 (CKSEL3..1 = 111)
//
// http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
//



//#include <stdlib.h>
//#include <stddef.h>
#include <stdio.h>
//#include <string.h>

#include <avr/io.h>
#include <stdint.h>
#include "lcd-routines.h"

#include <util/delay.h>

typedef enum { false, true } bool;

int main( int nargs, char **args )
{
  char puffer[21];

  lcd_init();
  lcd_clear();
  long int i = 0;

  uint8_t   wert = 0;
  DDRD =  0xFF;  // Port D als Ausgang

  while( true )
  {
    // geeignet für 2x16 (original Pollin):
    char   zeile = i%2 + 1;
    sprintf( puffer, "%c: i=%8ld",
             'A'+zeile-1,
             i++ );

    lcd_set_cursor( 0, zeile );
    lcd_string( puffer );
    PORTD = (wert++&0x03)<<5;
  }


  return 0;
}

lcd-routines.c (aus dem Tutorial abgekupfert):
// Time-stamp: "23.06.09 07:58 lcd-routines.c klaus@wachtler.de"
//
// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
// [1] http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
// [2] http://www.mikrocontroller.net/topic/88543#751982
//
// Die Pinbelegung ist über defines in lcd-routines.h einstellbar
//
// Änderungen:
// 23.06.2009 kw    - von außen nicht aufzurufende Funktionen static
//                    gemacht:
//                    lcd_data(), lcd_command(), lcd_enable()
//                  - gemeinsamen Code aus lcd_command() und lcd_data()
//                    in neue Funktion lcd_byte() ausgelagert
//                  - Shiften und Maskieren in lcd_byte() eliminiert
//                  - in lcd_set_cursor() Adressberechnung korrigiert
//                    für blaues LCD 

#include <avr/io.h>
#include "lcd-routines.h"
#include <util/delay.h>


// erzeugt den Enable-Puls
static void lcd_enable( void )
{
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers einfügen

   // http://www.mikrocontroller.net/topic/81974#685882
   LCD_EN1_PORT |= (1<<LCD_EN1);

    _delay_us(1);                   // kurze Pause
   // Bei Problemen ggf. Pause gemäß Datenblatt des LCD Controllers verlängern
   // http://www.mikrocontroller.net/topic/80900
   LCD_EN1_PORT &= ~(1<<LCD_EN1);
}


// sendet ein Daten- oder Kommandobyte (RS am LCD muß vorher
// entsprechend gesetzt sein)
static void lcd_byte( unsigned char data )
{
  // oberes Nibble auf den LCD-Pins 4..7 ausgeben:
  LCD_PORT_4 &= ~(1<<LCD_D4);
  LCD_PORT_5 &= ~(1<<LCD_D5);
  LCD_PORT_6 &= ~(1<<LCD_D6);
  LCD_PORT_7 &= ~(1<<LCD_D7);

  if( data & 0x10 ) LCD_PORT_4 |= (1<<LCD_D4);// setzen
  if( data & 0x20 ) LCD_PORT_5 |= (1<<LCD_D5);
  if( data & 0x40 ) LCD_PORT_6 |= (1<<LCD_D6);
  if( data & 0x80 ) LCD_PORT_7 |= (1<<LCD_D7);
  lcd_enable();

  // unteres Nibble auf den LCD-Pins 4..7 ausgeben:
  LCD_PORT_4 &= ~(1<<LCD_D4);
  LCD_PORT_5 &= ~(1<<LCD_D5);
  LCD_PORT_6 &= ~(1<<LCD_D6);
  LCD_PORT_7 &= ~(1<<LCD_D7);

  if( data & 0x01 ) LCD_PORT_4 |= (1<<LCD_D4);// setzen
  if( data & 0x02 ) LCD_PORT_5 |= (1<<LCD_D5);
  if( data & 0x04 ) LCD_PORT_6 |= (1<<LCD_D6);
  if( data & 0x08 ) LCD_PORT_7 |= (1<<LCD_D7);
  lcd_enable();

  // Dem LCD Zeit geben, das Kommando auszuführen
  _delay_us(42);
}


// sendet ein Datenbyte an das LCD
static void lcd_data( unsigned char data )
{
   LCD_RS_PORT |= (1<<LCD_RS);        // RS auf 1 setzen
   lcd_byte( data );
}


// sendet einen Befehl an das LCD
static void lcd_command( unsigned char command )
{
   LCD_RS_PORT &= ~(1<<LCD_RS);        // RS auf 0 setzen
   lcd_byte( command );
}


// Initialisierung:
// Muss ganz am Anfang des Programms aufgerufen werden.
void lcd_init( void )
{
   // Ports auf Ausgang schalten
   LCD_DDR_4 |=(1<<LCD_D4);
   LCD_DDR_5 |=(1<<LCD_D5);
   LCD_DDR_6 |=(1<<LCD_D6);
   LCD_DDR_7 |=(1<<LCD_D7);

   LCD_EN1_DDR |= (1<<LCD_EN1);

   LCD_RS_DDR  |= (1<<LCD_RS);

   // muss 3 mal hintereinander gesendet werden zur Initialisierung

   _delay_ms(15);

   LCD_PORT_4 |=  (1<<LCD_D4);
   LCD_PORT_5 |=  (1<<LCD_D5);
   LCD_PORT_6 &= ~(1<<LCD_D6);
   LCD_PORT_7 &= ~(1<<LCD_D7);

   LCD_RS_PORT &= ~(1<<LCD_RS);      // RS auf 0
   lcd_enable();

   _delay_ms(5);
   lcd_enable();

   _delay_ms(1);
   lcd_enable();
   _delay_ms(1);

   // 4 Bit Modus aktivieren
   LCD_PORT_4 &=  ~(1<<LCD_D4);
   LCD_PORT_5 |=   (1<<LCD_D5);
   LCD_PORT_6 &=  ~(1<<LCD_D6);
   LCD_PORT_7 &=  ~(1<<LCD_D7);

   lcd_enable();
   _delay_ms(1);

   // 4Bit / 2 Zeilen / 5x7
   lcd_command(0x28);

   // Display ein / Cursor aus / kein Blinken
   lcd_command(0x0C);

   // inkrement / kein Scrollen
   lcd_command(0x06);

   lcd_clear();
}


// Sendet den Befehl zur Löschung des Displays
void lcd_clear( void )
{
   lcd_command(CLEAR_DISPLAY);
   _delay_ms(5);
}


// Sendet den Befehl: Cursor Home
void lcd_home( void )
{
   lcd_command(CURSOR_HOME);
   _delay_ms(5);
}


// setzt den Cursor in Zeile y (1..4) Spalte x (0..15)
void lcd_set_cursor( uint8_t x, uint8_t y )
{
  uint8_t tmp;

  switch (y)
  {
    // Originalversion von [1]:
    //case 1: tmp=0x80+0x00+x;  break;    // 1. Zeile
    //case 2: tmp=0x80+0x40+x;  break;    // 2. Zeile
    //case 3: tmp=0x80+0x10+x;  break;    // 3. Zeile
    //case 4: tmp=0x80+0x50+x;  break;    // 4. Zeile

    // Klappt mit 4x20 blau ("Blue Line" von Electronic Assembly
    // EA W204B-NLW bzw. Reichelt LCD204BBL)
    case 1: tmp=0x80+0x00+x;  break;    // 1. Zeile
    case 2: tmp=0x80+0x40+x;  break;    // 2. Zeile
    case 3: tmp=0x80+0x14+x;  break;    // 3. Zeile
    case 4: tmp=0x80+0x54+x;  break;    // 4. Zeile
    default: return;
  }
  lcd_command(tmp);
}


// Schreibt einen String auf das LCD
void lcd_string( const char *data )
{
    while(*data)
    {
      lcd_data(*data);
      data++;
    }
}

lcd-routines.h:
// Time-stamp: "23.06.09 07:56 lcd-routines.h klaus@wachtler.de"
//
// Ansteuerung eines HD44780 kompatiblen LCD im 4-Bit-Interfacemodus
// [1] http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
// [2] http://www.mikrocontroller.net/topic/88543#751982


//void lcd_data( unsigned char data );
//void lcd_command( unsigned char command );
void lcd_string( const char *data );
//void lcd_enable( void );
void lcd_init( void );
void lcd_home( void );
void lcd_clear( void );
void lcd_set_cursor( uint8_t x, uint8_t y );

// Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!

// ist in Makefile gemacht!
#ifndef F_CPU
#error F_CPU nicht gesetzt
#endif


// LCD Befehle

#define CLEAR_DISPLAY 0x01
#define CURSOR_HOME   0x02



// Pinbelegung für das LCD, an verwendete Pins anpassen

#define LCD_PORT_4    PORTC
#define LCD_DDR_4     DDRC
#define LCD_D4        PC0

#define LCD_PORT_5    PORTC
#define LCD_DDR_5     DDRC
#define LCD_D5        PC1

#define LCD_PORT_6    PORTC
#define LCD_DDR_6     DDRC
#define LCD_D6        PC2

#define LCD_PORT_7    PORTC
#define LCD_DDR_7     DDRC
#define LCD_D7        PC3

#define LCD_RS_PORT   PORTC
#define LCD_RS_DDR    DDRC
#define LCD_RS        PC4

#define LCD_EN1_PORT  PORTC
#define LCD_EN1_DDR   DDRC
#define LCD_EN1       PC5

Autor: Klaus Wachtler (mfgkw)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier noch ein Bild dazu.

Die Ausgabe auf Port D ist übrigens überflüssig und macht nur
etwas gemütliche rote Beleuchtung am Schreibtisch.

Autor: Mathias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Vielen Dank!

Ich werde es gleich ausprobieren.

Autor: Mathias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Klaus,

wohin genau gehören die Dateien

- lcd-routines.h
- lcd-routines.c

die lcd-routines.h habe ich in das Verzeichniss vom Kompiler und die 
lcd-routines.c in das Projektverzeichniss gelegt. Leider bekomme 
Fehlermeldungen:

Build started 19.7.2009 at 17:16:26
avr-gcc -mmcu=atmega16 -Wl,-Map=LCD-Test.map LCD-Test.o     -o 
LCD-Test.elf
LCD-Test.o: In function `main':
D:\Daten 
Notebook\Uni\Diplomarbeit\AVR\LCD-Test\default/../LCD-Test.c:11: 
undefined reference to `lcd_init'
D:\Daten 
Notebook\Uni\Diplomarbeit\AVR\LCD-Test\default/../LCD-Test.c:13: 
undefined reference to `lcd_data'
D:\Daten 
Notebook\Uni\Diplomarbeit\AVR\LCD-Test\default/../LCD-Test.c:14: 
undefined reference to `lcd_data'
D:\Daten 
Notebook\Uni\Diplomarbeit\AVR\LCD-Test\default/../LCD-Test.c:15: 
undefined reference to `lcd_data'
D:\Daten 
Notebook\Uni\Diplomarbeit\AVR\LCD-Test\default/../LCD-Test.c:16: 
undefined reference to `lcd_data'
D:\Daten 
Notebook\Uni\Diplomarbeit\AVR\LCD-Test\default/../LCD-Test.c:18: 
undefined reference to `set_cursor'
D:\Daten 
Notebook\Uni\Diplomarbeit\AVR\LCD-Test\default/../LCD-Test.c:20: 
undefined reference to `lcd_string'
make: *** [LCD-Test.elf] Error 1
Build failed with 7 errors and 0 warnings...


Wie kann ich das in Ordnung bringen?

Autor: Klaus Wachtler (mfgkw)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich nehme nicht das AVR-Studio, sondern mache immer alles in der 
Kommandozeile; da habe ich diese Dateien in einem Verzeichnis.

Du wirst dem AVR-Studio noch sagen müssen, daß lcd-routines.c
mit zum Projekt gehört.

Das müsste im Source-Tree links gehen mit Rechtsklick auf
"Source Files", darin auswählen "Add existing source file(s)"
und dann die lcd-routines.c auswählen.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.