Forum: Mikrocontroller und Digitale Elektronik Shop-Platine: Problem mit LED und LCD


von Markus Krötz (Gast)


Lesenswert?

Hallo,

ich habe die Platine (16MHz) aus dem Shop hier und möchte einen LCD
anschließen.

Dafür habe ich mich für den Port B entschieden. Soweit so gut, wenn ich
Spannung anlege, dann sehe ich auf dem LCD in der 1. und 3. Zeile einen
schwarzen Balken. Was mich aber verwundert, ist dass die LED auf der
Entwicklungsplatine nicht leuchtet!
Ich habe nachgemessen, Spannung liegt an PB01 an, aber trotzdem
leuchtet die LED nicht!

Ich dachte mir vielleicht ist mein Mikrocontroller kaputt, da ich ja
das LCD weder initialisieren, noch sonst was kann. Kann das sein?

Was allerdings (zumindest meiner Meinung nach) dagegenspricht, ist,
dass ich den Mikrocontroller ja programmieren kann, also Programme in
den Controller + Speicher schreiben sowie auch lesen kann - das scheint
einwandfrei zu funktionieren.

An was kann denn das Problem liegen? Ist es möglich, dass der
Controller kaputt ist? Oder soll ich das LCD, das derzeit an den
PortB's liegt, an einen anderen Port (D) anschließen?

Vielen Dank für Eure Hilfe

Markus

von Markus Krötz (Gast)


Lesenswert?

Was noch zu sagen wäre: Falsch angeschlossen ist das Ding ja nicht, ich
habe alle Ports so angeschlossen, wie im AVR-Tutorial beschrieben, nur
anstatt der D's eben die B-Ports genommen.

von Sebastian Wille (Gast)


Lesenswert?

Hi Markus,

ich kenne die Platine jetzt zwar nicht, aber zur LED: Vielleicht hängt
die ja schon fest an Vcc und geht somit nur an, wenn Du den Port-Pin
auf Low ziehst, anstatt auf High?

Sebastian

von Fritz Ganter (Gast)


Lesenswert?

Du kannst dir bei Olimex die Doku zu der Platine runterladen. Dann
siehst du, dass die LED nach + angeschlossen ist, daher nur leuchtet
wenn der Ausgang auf Low liegt.

Eigentlich ist es egal an welchen Port das LCD hängt, sofern du das in
der LCD-Bibliothek richtig änderst.
Du solltest dort auch die delay() Routine anpassen, da die
wahrscheinlich für 4MHz ausgelegt ist, und sonst das Timing nicht
passt.

von Markus Krötz (Gast)


Lesenswert?

Ich habe ein bisschen im Forum gesurft (bin leider gerade nicht daheim,
sonst hätte ich das mit dem delay schon ausprobiert) und bin darauf
gestoßen, dass es evtl. auch was mit der Hintergrundbeleuchtung zu tun
haben könnte (habe ein LCD mit 16 pins) - kann das sein, oder dürften
dann gar keine Balken in der 1. und 3. Zeile erscheinen?

Vielen Dank schon einmal für Eure Antworten.

Grüßle

Markus

von Markus Krötz (Gast)


Lesenswert?

Aber es scheint so, als schließt ihr einen defekten Mikrocontroller aus,
richtig? Das wäre schon mal ne gute Nachricht.

von Markus Krötz (Gast)


Lesenswert?

So langsam krieg ich echt nen Koller. Das mit dem Delay hat nicht so
wirklich funktioniert (muss ich da vielleicht irgendwelche FuseBits
noch setzen, oder was weiß ich)?

Ich würd jetzt gern einfach mal testen, ob mein Mikrocontroller
funktioniert und würd gerne die LED an PB01 testen (wie oben
beschrieben).

Könnte mir da vielleicht jemand helfen mit ein bisschen Code? Vielen
vielen Dank

Der enttäuschte Markus

von Fritz Ganter (Gast)


Lesenswert?

Kanns dir nur für gcc aufschreiben:

#include <avr/io.h>

void main(void)
{
DDRB=1;
PORTB=0;
oder korrekter:
PORTB&=~_BV(0);
}

Wie ich oben schon geschrieben habe, der Pin muss auf 0!!!!

von Fritz Ganter (Gast)


Lesenswert?

Sorry, loop sollte drüber:

void main(void)
{
DDRB=1;
PORTB=0; // LED aus (einfache Methode)

for (;;)
 {
  PORTB|=_BV(0);  // setzt pin auf high, also LED aus

  // da kannst dein delay rein
  PORTB&=~_BV(0); // pin auf low, also LED ein
 }
}

}

von Markus Krötz (Gast)


Lesenswert?

Ha, ich werd verrückt. Vielen Dank, Fritz, die LED leuchtet wirklich!!!
Juhu! Damit wäre einmal sichergestellt, dass der Mikrocontroller nicht
im Eimer ist!

Jetzt muss nur noch der LCD funktionieren. Nochmal meine Frage von
vorhin: Kann es vielleicht daran liegen, dass ich an der
Kontrastspannung herumspielen muss? Aber warum werden dann nur in der
1. und 3. Zeile schwarze Balken angezeigt und nicht in allen Zeilen?
Ist dann doch unwahrscheinlich, oder?

von Fritz Ganter (Gast)


Lesenswert?

Wenn der LCD-Controller Strom kriegt, dann sieht man die schwarzen
Balken. Oder wenn er per Software initialisiert wird, hab ich
vergessen.
Auf jeden Fall passt der Kontrast wenn du was siehst.
Mit lcd_clrscr oder wie es bei dir heisst, sollten die weggehen, vorher
musst aber noch sowas wie lcd_init machen.

von Markus Krötz (Gast)


Lesenswert?

Ja, genau und das ist das Problem. Mit folgendem Code tut sich rein gar
nichts (außer den schwarzen Balken) :-(((


.include "2313def.inc"


.def temp1 = r16
.def temp2 = r17
.def temp3 = r18


           ldi temp1, LOW(RAMEND)      ; LOW-Byte der obersten
;RAM-Adresse
           out SPL, temp1



           ldi temp1, 0xFF    ;Port D = Ausgang
           out DDRB, temp1

           rcall lcd_init     ;Display initialisieren
           rcall lcd_clear    ;Display löschen

           ldi temp1, 'T'     ;Zeichen anzeigen
           rcall lcd_data

           ldi temp1, 'e'     ;Zeichen anzeigen
           rcall lcd_data

           ldi temp1, 's'     ;Zeichen anzeigen
           rcall lcd_data

           ldi temp1, 't'     ;Zeichen anzeigen
           rcall lcd_data

loop:
           rjmp loop






;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;                 LCD-Routinen                ;;
;;                 ============                ;;
;;              (c)andreas-s@web.de            ;;
;;                                             ;;
;; 4bit-Interface                              ;;
;; DB4-DB7:       PB0-PB3                      ;;
;; RS:            PB4                          ;;
;; E:             PB5                          ;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;



 ;sendet ein Datenbyte an das LCD
lcd_data:
           mov temp2, temp1             ;"Sicherungskopie" für
                                        ;die Übertragung des 2.Nibbles
           swap temp1                   ;Vertauschen
           andi temp1, 0b00001111       ;oberes Nibble auf Null setzen
           sbr temp1, 1<<4              ;entspricht 0b00010000
           out PORTB, temp1             ;ausgeben
           rcall lcd_enable             ;Enable-Routine aufrufen
                                        ;2. Nibble, kein swap da es
schon
                                        ;an der richtigen stelle ist
           andi temp2, 0b00001111       ;obere Hälfte auf Null setzen
           sbr temp2, 1<<4              ;entspricht 0b00010000
           out PORTB, temp2             ;ausgeben
           rcall lcd_enable             ;Enable-Routine aufrufen
           rcall delay50us              ;Delay-Routine aufrufen
           rcall delay50us
           rcall delay50us
           ret                          ;zurück zum Hauptprogramm

 ;sendet einen Befehl an das LCD
lcd_command:                            ;wie lcd_data, nur ohne RS zu
setzen
           mov temp2, temp1
           swap temp1
           andi temp1, 0b00001111
           out PORTB, temp1
           rcall lcd_enable
           andi temp2, 0b00001111
           out PORTB, temp2
           rcall lcd_enable
           rcall delay50us
           rcall delay50us
           rcall delay50us
           ret

 ;erzeugt den Enable-Puls
lcd_enable:
           sbi PORTB, 5                 ;Enable high
           nop                          ;3 Taktzyklen warten
           nop
           nop
           nop
           nop
           nop
           cbi PORTB, 5                 ;Enable wieder low
           ret                          ;Und wieder zurück


 ;Pause nach jeder Übertragung
delay50us:                              ;50us Pause
           ldi  temp1, $42
delay50us_:dec  temp1
           brne delay50us_
           ret                          ;wieder zurück

 ;Längere Pause für manche Befehle
delay5ms:                               ;5ms Pause
           ldi  temp1, $21
WGLOOP0:   ldi  temp2, $C9
WGLOOP1:   dec  temp2
           brne WGLOOP1
           dec  temp1
           brne WGLOOP0
           ret                          ;wieder zurück

 ;Initialisierung: muss ganz am Anfang des Programms aufgerufen werden
lcd_init:
           ldi  temp3,50
powerupwait:
           rcall  delay5ms
           rcall        delay5ms
           rcall        delay5ms
           dec  temp3
           brne  powerupwait
           ldi temp1, 0b00000011        ;muss 3mal hintereinander
gesendet
           out PORTB, temp1             ;werden zur Initialisierung
           rcall lcd_enable             ;1
           rcall delay5ms
           rcall delay5ms
           rcall delay5ms
           rcall lcd_enable             ;2
           rcall delay5ms
           rcall delay5ms
           rcall delay5ms
           rcall lcd_enable             ;und 3!
           rcall delay5ms
           rcall delay5ms
           rcall delay5ms
           ldi temp1, 0b00000010        ;4bit-Modus einstellen
           out PORTB, temp1
           rcall lcd_enable
           rcall delay5ms
           rcall delay5ms
           rcall delay5ms
           ldi temp1, 0b00101000        ;noch was einstellen...
           rcall lcd_command
           ldi temp1, 0b00001100        ;...nochwas...
           rcall lcd_command
           ldi temp1, 0b00000100        ;endlich fertig
           rcall lcd_command
           ret

 ;Sendet den Befehl zur Löschung des Displays
lcd_clear:
           ldi temp1, 0b00000001   ;Display löschen
           rcall lcd_command
           rcall delay5ms
           rcall delay5ms
           rcall delay5ms
           ret

von Markus Krötz (Gast)


Lesenswert?

Beziehungsweise analog dazu mit der originalen, unveränderten Peter
Fleury Bibliothek:

/*********************************************************************** 
**
Title:    testing output to a HD44780 based LCD display.
Author:   Peter Fleury  <pfleury@gmx.ch>  http://jump.to/fleury
File:     $Id: test_lcd.c,v 1.3 2003/12/10 19:32:48 peter Exp $
Software: AVR-GCC 3.3
Hardware: HD44780 compatible LCD text display
          ATS90S8515/ATmega if memory-mapped LCD interface is used
          any AVR with 7 free I/O pins if 4-bit IO port mode is used
************************************************************************ 
**/
#include <stdlib.h>
#include <avr/io.h>
#include "lcd.h"


/*
** constant definitions
*/


/*
** function prototypes
*/


int main(void)
{
    char buffer[7];
    int  num=134;

    /* initialize display, cursor off */
    lcd_init(LCD_DISP_ON);

    for (;;) {                           /* loop forever */
        /*
         * Test 1:  write text to display
         */

        /* clear display and home cursor */
        lcd_clrscr();

        /* put string to display (line 1) with linefeed */
        lcd_puts("LCD Test Line 1\n");

        /* cursor is now on second line, write second line */
        lcd_puts("Line 2");

        /* move cursor to position 8 on line 2 */
        lcd_gotoxy(7,1);

        /* write single char to display */
        lcd_putc(':');

    }
}

von Fritz Ganter (Gast)


Lesenswert?

es gibt bei der Fleury bibliothek ein lcd.h da musst du einstellen ob du
 memory maped oder i/o machst. Ich hab die delay routine auch an die
8MHz angepasst.

von Markus Krötz (Gast)


Lesenswert?

Da ich mich jetzt voll auf Fleurys Bibliothek konzentrieren möchten,
werde ich nun den Pin PB5 mit R/W (das war ja bisher auf GND gesetzt -
wegen Tutorial) und den Pin PB6 mit Enable (war davor PB5) verbinden.
So wie es eben in Fleurys Anleitung steht
(http://homepage.sunrise.ch/mysunrise/pfleury/avr-lcd44780.html). Ich
melde mich dann gleich wieder.

von Markus Krötz (Gast)


Lesenswert?

Jippie, es funktioniert!!! Fritz vielen Dank für deine aufopferungsvolle
Hilfe - das hat mir mehr als geholfen. Wenn ich noch ein paar Fragen
habe, darf ich dich dann fragen :-P?

Tausend Dank an allen, die sich die Mühe gemacht haben, mir zu helfen.
Nun bin ich fast fertig mit meinem LCD (naja, gut, schon noch ein
Stück, aber mal schaun).

Danke

Markus

von Markus Krötz (Gast)


Lesenswert?

Ich versuche nun, in mein EEPROM mit folgender Funktion die Zahl 732
hineinzuschreiben:

#include <stdlib.h>
#include <avr/io.h>
#include <inttypes.h>
#include <eeprom.h>
#include "lcd.h"

#define EEPROM_SECTION  _attribute_ ((section (".eeprom")))
uint16_t  eeprom_var1  EEPROM_SECTION  = 1027;

int main(void)
{
    char buffer[20];
    uint16_t  state1=732;
    eeprom_write_byte(&eeprom_var1, state1);

    /* initialize display, cursor off */
    lcd_init(LCD_DISP_ON);
    lcd_clrscr();
    ...
}


Dann hatte ich versucht, die Zahl mittels

int main(void)
{
    char buffer[20];
    uint16_t  state1=732;

    /* initialize display, cursor off */
    lcd_init(LCD_DISP_ON);
    lcd_clrscr();
    state1 = eeprom_read_word(&eeprom_var1);
    for (;;) {
    ...
}

auszulesen, und mittels

    itoa( state1 , buffer, 20);
    /* put converted string to display */
    lcd_puts(buffer);

auf den LCD zu schreiben. Doch auf dem LCD sehe ich nur 839f anstatt
732.

Die Zahl state1 muss bis zu 36600 groß werden, darum habe ich mich für
einen uint16_t entschieden - ich hoffe, das war richtig.

Warum aber zeigt mein LCD nun das falsche an?

von Markus Krötz (Gast)


Lesenswert?

Ich meinte natürlich itoa (state1, buffer, 10).
Und habe dabei auch state1 nicht auf 732, sondern auf die Höchstzahl
36600 gebracht. Auf dem LCD habe ich dann nur -1 anstatt 36600
gesehen.

Wahrscheinlich kann ich mit eeprom_write_byte(&eeprom_var1, state1);
keine so großen Werte speichern, sondern nur Byte-Werte von 0-255,
oder? Wie löse ich dann das Problem?
Oder muss ich beim Wertebereich 0-36600 einfach einen anderen
Variablentyp nehmen? Aber welchen?

Vielen Dank

Markus

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.