LCD 1602A an Atmega128A will nicht funktionieren

Gast #4315466
Lesenswert?

Hallo,

ich habe mir folgendes Board zugelegt, um ein wenig mit Mikrocontrollern 
herumzubasteln.

https://www.olimex.com/Products/AVR/Development/AVR-MT128/

Leider bekomme ich weder mit dem auf der Olimex Seite bereitgestellten 
Beispielprogramm, noch mit den Routinen aus dem LCD-Tutorial das Display 
zum laufen (nur schwarzer Balken).

Ich habe die von mir verwendeten Dateien beigefügt, damit 
nachvollziehbar ist welche Anpassungen ich vorgenommen habe.

Ich wäre für jede Hilfe sehr dankbar.

Grüße, Oliver
Angehängte Dateien:
Gast #4315507
Lesenswert?

Eigentlich nur die Port/Pinbelegung in der lcd-routines.h angepasst und 
die entsprechende Taktrate angegeben.
Da das die einzigen Anpassungen sind, muss es ja irgendetwas mit der 
Taktfrequenz zu tun haben.
#4315514
Lesenswert?

Die Pins sehen richtig gewählt aus.

Gibt es noch Warnungen, dass F_CPU irgendwo nicht definiert wurde? 
Könnte bedeuten, dass die Delay-Funktion nicht auf die 16MHz angepasst 
wurde.

Auch das Toggeln des E-Pins ist bei 16MHz vielleicht zu schnell. Das LCD 
erkennt den Puls vielleicht nicht.

Es wäre noch auszuprobieren, was passiert, wenn du die Fuse CKDIV8 setzt 
(also statt 16MHz mit 2MHz werkeln lässt).
Gast #4315547
Lesenswert?

@TEO

Ja bei dem Olimex Board ist das laut beigefügtem Schema schon so 
verdrahtet.
D.h.
DB4 -> PC4
.
.
DB7 -> PC7
RS -> PC0
EN -> PC2

Habe deshalb die Pins entsprechend angepasst in der lcd-routines.h. Das 
sollte es also eigentlich nicht sein.
Gast #4315552
Lesenswert?

Ansonsten haben LCDs hin und wieder Timing-Probleme.
Dann das LCD langsamer ansteuern (Takt runter oder "Pausenzeiten" 
verlängern).

In jedem Fall an die Kontrastspannung denken (auch daran, diese richtig 
einzustellen).
#4315578
Lesenswert?

CKOPT könnte es sein. Damals hieß die noch CKDIV8. Es müsste ein Tooltip 
geben, wenn du mit der Maus drauffährst.

Alternativ unter SUT_CKSEL den RC-Oszillator mit 1 oder 2 MHz auswählen. 
Aber Achtung: nicht verklicken auf externen Takt oder sowas, sonst 
bekommst du wahrscheinlich keinen Zugriff mehr auf das Teil.
#4315581
Lesenswert?

Felix A. schrieb:
> CKOPT könnte es sein. Damals hieß die noch CKDIV8. Es müsste ein Tooltip
> geben, wenn du mit der Maus drauffährst.
>
> Alternativ unter SUT_CKSEL den RC-Oszillator mit 1 oder 2 MHz auswählen.

Lass doch den Quatsch.
Er hat in den Routinen 16Mhz eingetragen.
D.h. der Compiler bemisst alle delays auf einen schnellen Prozessor. 
Sollte der tatsächlich langsamer sein als angegeben, dann werden die 
delays höchstens länger, aber nicht kürzer.

Einfach den Takt runterstellen und dafür F_CPU entsprechend kleiner 
stellen bringt genau gar nichts.
#4315595
Lesenswert?

Felix A. schrieb:

> Hier im Bild markiert die Einstellung, um den Takt auf 1 MHz zu setzen.

Was soll das beringen?
15ms sind 15ms

Egal ob er das mit einem realen CPU Takt von 16Mhz und einem F_CPU von 
16Mhz erreicht oder ob er das mit realen 1Mhz und einem F_CPU von 1Mhz 
macht.

Das ändert nur Zahlenwerte, die der Compiler errechnet. Aber in dem 
einen wie im anderen Fall kommen reale 15ms raus.
#4315604
Lesenswert?

Karl H. schrieb:

> ja, ok. Das ist sinnvoll.
> Aber der Rest ist es nicht

Im übrigen würde er da keine Warnung kriegen.

Daher in lcd_routines.h so abändern
1
#ifndef LCD_ROUTINES_H_
2
#define LCD_ROUTINES_H_
3

4
////////////////////////////////////////////////////////////////////////////////
5
// Hier die verwendete Taktfrequenz in Hz eintragen, wichtig!
6

7
// #ifndef F_CPU    <---- Kommentar davor
8
#define F_CPU 16000000UL
9
// #endif           <---- Kommentar davor
10

11

12
....

(der ifndef sollte da überhaupt nicht sein)
#4315609
Lesenswert?

Oliver schrieb:
> Karl H. schrieb:
>> hast du das selbst compiliert oder hast du dir von dort das Hex-File
>> geholt und gebrannt
>
> Sowohl als auch. Wenn ich das c file selbst compiliere erhalte ich wirre
> Zeichen auf dem Display. Wenn ich die fertige .elf-Datei direkt brenne,
> läuft es tadellos.

Das ist doch schon mal was!
Oben sagtest du noch, das die Demo nicht läuft.

Wirre Zeichen ist schon mal besser als nichts.
Gast #4315620
Lesenswert?

Karl H. schrieb:
> Karl H. schrieb:
>
>>> Sowohl als auch. Wenn ich das c file selbst compiliere
>
> Womit compilierst du?
> Atmel Studio?
>
> Hast du den Mega128A am Anfang ausgewählt?
>
> Ansonsten poste mal deine Projektdatei. Da scheint etwas in den
> Einstellungen nicht zu stimmen.

Anbei meine Projektdatei...
Angehängte Dateien:
Gast #4315627
Lesenswert?

S. K. schrieb:
> Der TE am Anfang:
>> (nur schwarzer Balken).
>
> und 1:30h später:
>>Wenn ich das c file selbst compiliere erhalte ich wirre
>>Zeichen auf dem Display. Wenn ich die fertige .elf-Datei direkt brenne,
>>läuft es tadellos.
>
> Ja was denn nun, wann und wie genau?

Also, schwarzer Balken bezieht sich auf die lcd Routinen, aus dem 
Tutorial.

Wirre Zeichen bezieht sich auf das Beispielprogramm von der Olimex 
Website.
#4315632
Lesenswert?

Du könntest im gesamten Projekt in allen Dateien mal nach der Konstanten 
F_CPU suchen. Irgendwo muss diese stehen.

Wenn diese nicht zu finden ist, dann F_CPU in deiner lcd_routines.h 
definieren ohne das #ifdef. Gibt es beim Compilieren jetzt Warnungen, 
dass diese doppelt definiert wurde?
Über die fehlermeldung findet sich dann vielleicht der zweite eintrag.

Mit WinAVR wurde die Konstante meiner Erinnerung nach sogar in der IDE 
festgelegt, also nicht im Code. Passiert vielleicht auch im AVR Studio, 
das weiß ich aber nicht. Auf die Schnelle konnte ich das nicht finden.

Wenn diese definiert ist und nicht gefunden werden kann, könnte der 
Standardwert 1MHz drin stehen. In dem Fall müsstest du alle Zeiten 16mal 
so groß machen.

Und deshalb macht das Reduzieren der Taktfrequenz auch Sinn. Das F_CPU 
angepasst werden soll, habe ich nämlich NICHT geschrieben, werter Karl 
Heinz
#4315645
Lesenswert?

Ich kann deine Projekt-Datei in meinem Atmel_Studio nicht öffnen. Das 
muss aber nichts heissen. Auf dem Rechner, auf dem ich zur Zeit bin, ist 
eine ziemlich alte Version installiert und ich will da jetzt auch nicht 
updaten.

Ich hab ein neues Projekt gemacht und dein Dateien eingefügt.
Das HEX-File, welches jetzt hier beiliegt, läuft das so wie es soll?
Angehängte Dateien:
#4315649
Lesenswert?

Felix A. schrieb:

> Mit WinAVR wurde die Konstante meiner Erinnerung nach sogar in der IDE
> festgelegt, also nicht im Code. Passiert vielleicht auch im AVR Studio,
> das weiß ich aber nicht. Auf die Schnelle konnte ich das nicht finden.

Es wurde da wie dort nicht defaultmässig eingefügt.
Im alten AVR Studio gab es eine Combo-Box zur Auswahl, wenn man da aber 
bei der Projekt-Generierung nichts unternahm, stand kein Wert drinnen. 
Im neuen Atmel Studio wird kein Preprozessor-Symbol vorbelegt.

>
> Wenn diese definiert ist

Wenn er es nicht gemacht hat, dann ist es nicht vorbelegt.
#4315660
Lesenswert?

Felix A. schrieb:
> Das stimmt so nicht, siehe delay.h
>
1
> #ifndef F_CPU
2
> /* prevent compiler error by supplying a default */
3
> # warning "F_CPU not defined for <util/delay.h>"
4
> # define F_CPU 1000000UL
5
> #endif
6
>

Schön.
Nur das die #include Reihenfolge lautet
1
#include <avr/io.h>
2
#include "lcd-routines.h"
3
#include <util/delay.h>

das F_CPU aus delay.h kommt nie zum Zug
#4315662
Lesenswert?

Es sei denn, es wäre vorher schon definiert. Und das lässt sich gut 
testen, indem F_CPU in der lcd-routines.h definiert und dann compiliert 
wird. Erscheint eine Warnung der Redefinition, kann man hier sicher 
sein.

Es ist leider nunmal so, dass Code, den man nicht komplett geschrieben 
hat, machmal etwas "unpraktisch" ist.

Irgendein Weg muss der TE zum Findes Fehlers nunmal auf sich nehmen. 
Genügend Vorschläge gibt es, diese ausprobieren dauert nicht lange.
#4315669
Lesenswert?

Felix A. schrieb:
> Es sei denn, es wäre vorher schon definiert.

Das kann wiederrum nur sein, wenn es in Atmel-Studio bei den vorbelegten 
Präprozessor-Defines angegeben ist.
Da das Atmel Studio keine derartige Vorbelegung macht, müsste er es 
eingefügt haben.

Aber seis drumm. Soll er halt mal den Prozessor auf 1Mhz umstellen, 
damit du beruhigt bist. Erwarten tu ich mir davon nichts.

> Es ist leider nunmal so, dass Code, den man nicht komplett geschrieben
> hat, machmal etwas "unpraktisch" ist.

Er hat den kompletten Code gepostet. Keine Spur von F_CPU ausser im 
lcd_routines.h
#4315712
Lesenswert?

Oliver schrieb:
> Karl H. schrieb:
>> Ich hab ein neues Projekt gemacht und dein Dateien eingefügt.
>> Das HEX-File, welches jetzt hier beiliegt, läuft das so wie es soll?
>
> Dumme Frage: Wie genau finde ich das heraus? D.h. wie bekomme ich dein
> hex-file in meinen Controller?

?
Du hast doch auch das Olimex-Hex File gebrannt.

Gibt es in deinen Brennprogramm keine Möglichkeit, wo du das zu 
brennende Hex-File auswählen kannst?
(Ich arbeite normal nicht mit dem Atmel Studio, drumm ist das hier alles 
nicht eingerichtet)
#4315717
Lesenswert?

Tools -> Device Programming -> Memories

Pfad zur HEX-Datei wählen und "Program" klicken.

Mir kam gerade ein Gedanke, nachdem ich in EIN Displaydatenblatt 
geschaut habe:
1
static void lcd_enable( void )
2
{
3
  LCD_PORT |= (1<<LCD_EN);     // Enable auf 1 setzen
4
  _delay_us( LCD_ENABLE_US );  // kurze Pause
5
  LCD_PORT &= ~(1<<LCD_EN);    // Enable auf 0 setzen
6
}

Da immer zweimal 4 Bits geschrieben werden, könnte die Zweit zwischen 
fallender Flanke und nächster steigender Flanke zu kurz sein.
Ich würde ein delay vor dem "LCD_PORT |= (1<<..." einfügen, probeweise.

Bei diesem Displaydatenblatt steht 800ns lowtime und 800ns Hightime für 
den Takt, der hier per E-Signal gemacht wird.
Gast #4315720
Lesenswert?

Karl H. schrieb:
> Du hast doch auch das Olimex-Hex File gebrannt.
>
> Gibt es in deinen Brennprogramm keine Möglichkeit, wo du das zu
> brennende Hex-File auswählen kannst?
> (Ich arbeite normal nicht mit dem Atmel Studio, drumm ist das hier alles
> nicht eingerichtet)

Olimex hat zudem noch eine elf-Datei mitgeliefert, welche ich mit Atmel 
Studio brennen konnte. Hex Files kann ich da aber nicht auswählen.

Aber das weiß doch hier bestimmt jemand, ob man mit Atmel Studio 
hex-Files direkt brennen kann?
#4315747
Lesenswert?

1
void lcd_init( void )
2
{
3
  // verwendete Pins auf Ausgang schalten
4
  uint8_t pins = (0x0F << LCD_DB) |           // 4 Datenleitungen
5
  (1<<LCD_RS) |                // R/S Leitung
6
  (1<<LCD_EN);                 // Enable Leitung
7
  LCD_DDR |= pins;
8
  
9
  // initial alle Ausgänge auf Null
10
  LCD_PORT &= ~pins;

Letzte Zeile.

Diese Thema lässt mich irgendwie nicht los :-(
#4315749
Lesenswert?

Oliver schrieb:
> Karl H. schrieb:
>> Was ist mit dem Hex-File welches ich gepostet habe?
>> Hast du das mal probiert?
>
> Ergebnis: Schwarzer Balken...

hmm.
normalerweise würde ich jetzt schön langsam in die Richtung tendieren, 
die Verkabelung noch mal zu kontrollieren. Da du aber sagst, das 
original Hex-File funktioniert ....

Kopfkratz.

Ändere mal dein LCD.c so um
1
#
2
...
3

4
int main(void)
5
{
6
  DDRA = ( 1 << PA6 );
7
  _delay_ms( 500 );
8
  PORTA |= ( 1 << PA5 );
9
  _delay_ms( 500 );
10
  PORTA &= ~( 1 << PA5 );
11

12
  // Initialisierung des LCD
13
  // Nach der Initialisierung müssen auf dem LCD vorhandene schwarze Balken
14
  // verschwunden sein
15
  lcd_init();  
16

17
...

das ist jetzt mehr so ein Verzweiflungsschlag. Auf dem Board ist ein 
Relais samt LED verbaut. Nach dem Einschalten solltest du einmalif die 
LED aufblinken sehen und das Relais schalten hören. Aber das darf nur 
ein einziges mal nach dem Programmieren passieren.

Es wird dein Problem nicht lösen. Aber es gibt erst mal Rückmeldung, ob 
das programmieren geklappt hat oder nicht.
#4315755
Lesenswert?

Felix A. schrieb:
>
1
> void lcd_init( void )
2
> {
3
>   // verwendete Pins auf Ausgang schalten
4
>   uint8_t pins = (0x0F << LCD_DB) |           // 4 Datenleitungen
5
>   (1<<LCD_RS) |                // R/S Leitung
6
>   (1<<LCD_EN);                 // Enable Leitung
7
>   LCD_DDR |= pins;
8
> 
9
>   // initial alle Ausgänge auf Null
10
>   LCD_PORT &= ~pins;
11
>
>
> Letzte Zeile.
>
> Diese Thema lässt mich irgendwie nicht los :-(

Autsch.
Das haben wir alle übersehen.
AUf dem LCD ist die R/W nicht auf GND verkabelt, sondern geht an den 
Prozessor.

Das könnte es wirklich sein!
Gast #4315767
Lesenswert?

Felix A. schrieb:
> Da immer zweimal 4 Bits geschrieben werden, könnte die Zweit zwischen
> fallender Flanke und nächster steigender Flanke zu kurz sein.
> Ich würde ein delay vor dem "LCD_PORT |= (1<<..." einfügen, probeweise.

Habe verschiedene Delays 10us bis 50ms eingefügt. Leider kein Erfolg.

Vielleicht ist der Fehler bei dem von Olimex bereitgestellten Code 
einfacher zu identifizieren. Hier erhalte ich ja immerhin schon wirre 
Zeichen auf dem Display.
#4315784
Lesenswert?

Oliver schrieb:

> Vielleicht ist der Fehler bei dem von Olimex bereitgestellten Code
> einfacher zu identifizieren. Hier erhalte ich ja immerhin schon wirre
> Zeichen auf dem Display.

Der entscheidende Unterschied dürfte wirklich sein, dass der Olimex Code 
am PortC alle 7 LCD Leitungen auf Ausgang und 0 setzt.

Dass der nur wirre Zeichen bringt, das kann jetzt an vielem liegen. 
Unter andermm daran
1
void Delay(unsigned int a)
2
{
3
  while (a) 
4
  {
5
    a--;
6
  }
7
}

das ist ziemlicher Müll. Damit hat man kein reproduzierbares Timing.

-> so, wie Felix das sagt: Erweitere um den R/W Pin. Aber schreib dir 
einen Kommentar dazu, dass der Pin nicht benutzt wird!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren