Forum: Mikrocontroller und Digitale Elektronik Delay timing Problem


von Pierre G. (bqube)


Lesenswert?

Moin moin liebe Gemeinde,

Ich hab mich nun nach Jahren wieder an die kleinen Käfer gewagt und bin 
auf ein seltsames Problem gestoßen,  ich hatte damals ein LCD Projekt 
hier im Forum was auch super lief nun hab ich das ganze wieder aufgebaut 
und bekomm das 16x2 Display nur zum laufen wenn die CPU mit 8mhz 
definiert wird obwohl der interne Quarz mit 1mhz gewählt wurde.

Gibt es ein Problem mit der delay.h in der avr studio 7

MFG


#include <avr/io.h>
#ifndef F_CPU
#define F_CPU 1000000UL
#endif
#include <util/delay.h>
#define DatenPort PORTD
#define SteuerPort PORTB

void Setup(void)
{
  SteuerPort |= (1 << 0);
  _delay_us(5);
  SteuerPort &= ~(1 << 0);
}

void Text(void)
{
  SteuerPort |= (1 << 1);
  SteuerPort |= (1 << 0);
  _delay_us(5);
  SteuerPort &= ~((1 << 0) | (1 << 1));
}

int main(void)
{
    DDRB = 0xff;
  DDRD = 0xff;
    {
         _delay_ms(15);
     DatenPort = 0b00110000; //Interface auf 8-Bit setzen
     Setup();
     DatenPort = 0b00000000;

     _delay_ms(5);
     DatenPort = 0b00110000; //Interface auf 8-Bit setzen
     Setup();
     DatenPort = 0b00000000;

     _delay_us(120);
     DatenPort = 0b00110000; //Interface auf 8-Bit setzen
     Setup();
     DatenPort = 0b00000000;

     _delay_us(120);
     DatenPort = 0b00110000; //Interface auf 8-Bit setzen
     Setup();
     DatenPort = 0b00000000;

     _delay_us(120);
     DatenPort = 0b00111000; //2-zeilig, 5x8-Punkt-Matrix
     Setup();
     DatenPort = 0b00000000;

     _delay_us(120);
     DatenPort = 0b00001000; //Display aus
     Setup();
     DatenPort = 0b00000000;

     _delay_us(120);
     DatenPort = 0b00000001; //Display löschen
     Setup();
     DatenPort = 0b00000000;

     _delay_us(120);
     DatenPort = 0b00000110; //Kursor nach rechts wandernd, kein Display 
shift
     Setup();
     DatenPort = 0b00000000;

     _delay_us(120);
     DatenPort = 0b00001100; //Display ein
     Setup();
     DatenPort = 0b00000000;

     _delay_us(120);
     DatenPort = 'T';    // T Senden
     Text();
     DatenPort = 0x00;


  }

  while(1);
}

von Wolfgang (Gast)


Lesenswert?

Pierre G. schrieb:
> Ich hab mich nun nach Jahren wieder an die kleinen Käfer gewagt und bin
> auf ein seltsames Problem gestoßen,  ich hatte damals ein LCD Projekt
> hier im Forum was auch super lief nun hab ich das ganze wieder aufgebaut
> und bekomm das 16x2 Display nur zum laufen wenn die CPU mit 8mhz
> definiert wird obwohl der interne Quarz mit 1mhz gewählt wurde.

Alsonoch mal ganz der reihe nach:
welchen quarz hast du eingebaut welche frequenz musst du eintragen damit 
es läuft um welchen prozessor handelt es sich was hast du als taktquelle 
gewählt und wie hast du die CKDIV8 fuse eingestellt?

von Pierre G. (bqube)


Lesenswert?

Verwendet wird ein Atmega16 an dem ein 16x2 LCD angeschlossen ist und 
das ganze über ein 5V Netzteil versorgt wird.

Das LCD ist an PORTB Eingang 7-0 für die Daten und an PORTD Eingang  2-0 
für RW RS und E angeschlossen.

Der Mikrocontroller ist in dem Fusebits auf Grundeinstellung 1Mhz 
interner Quarz eingestellt

Wenn ich den Code Compiliere mit #define F_CPU 1000000UL zeigt das 
Display nichts an aber sobald ich den Wert auf 8000000UL anhebe zeigt 
das Display das gewollte Zeichen an.

MFG

von booze (Gast)


Lesenswert?

Vielleicht hattest du damals unwissend ein Problem, daß jetzt rauskommt.

von Johann Klammer (Gast)


Lesenswert?

avr gcc hatte da das problem dass die NOPs verschwinden.
Ich vermute dass es das ist. (Ich verwende den gcc nicht mehr fuer uC.
Ist zu beschissen geworden.)
Versuch an die disassembly zu kommen. ich glaube nm or objdump kann das.
Dann kannst' die NOPs zaehlen.

von Georg M. (g_m)


Lesenswert?

Pierre G. schrieb:
> Verwendet wird ein Atmega16
>
> Der Mikrocontroller ist in dem Fusebits auf Grundeinstellung 1Mhz
> interner Quarz eingestellt

Was ist "interner Quarz"?
Zeige bitte den Screenshot.

von Hannes (Gast)


Lesenswert?

Hast du in den Fuses CLK/8 ausgewählt? Vermutlich schon, ist bei den 
meisten AVR Standard.

von Pierre G. (bqube)


Lesenswert?

Wenn ich heut abend zu Hause bin mach ich mal ein screen shoot der 
eingestellten Fuses

von Hannes (Gast)


Lesenswert?

Kannst den Fuse CKDIV8 auch einfach ausschalten (bzw. einschalten, je 
nach Programm) Brauchst nicht vorher nen screenshot zu senden. Dein uC 
läuft halt gerade mit 1Mhz / 8.

von Axel S. (a-za-z0-9)


Lesenswert?

Pierre G. schrieb:
> Verwendet wird ein Atmega16 an dem ein 16x2 LCD angeschlossen ist und
> das ganze über ein 5V Netzteil versorgt wird.
>
> Der Mikrocontroller ist in dem Fusebits auf Grundeinstellung 1Mhz
> interner Quarz eingestellt

Es gibt keinen "internen Quarz". Du meinst wohl, er ist auf den internen 
RC-Oszillator gestellt und die CKDIV8 Fuse ist aktiviert, so daß er real 
mit 1MHz Takt läuft.

> Wenn ich den Code Compiliere mit #define F_CPU 1000000UL zeigt das
> Display nichts an aber sobald ich den Wert auf 8000000UL anhebe zeigt
> das Display das gewollte Zeichen an.

Das würde bedeuten, daß entweder

- dein ATMega16 doch schneller als mit 1MHz läuft -oder-
- das Timing für das LCD immer schon grenzwertig war -oder-
- du sonst etwas falsch machst

Compilierst du mit Optimierung? Ohne funktionieren die _delay* 
Funktionen nicht.

Ferner fällt mir auf, daß du in
1
void Setup(void)
2
{
3
  SteuerPort |= (1 << 0);
4
  _delay_us(5);
5
  SteuerPort &= ~(1 << 0);
6
}

zwar die Länge der H-Zeit der Impulse an E großzügig auf 5µs setzt, 
nicht jedoch die Länge der L-Zeit.

Für den ersten Punkt oben mach doch einen einfachen Test, schließ eine 
LED an irgendeinen IO an und laß die mit 1Hz Blinken mit einer 
Endlosschleife a'la
1
while (1) {
2
  LED_on();
3
  _delay_ms(500);
4
  LED_off();
5
  _delay_ms(500);
6
}

das ganze natürlich mit F_CPU auf 1000000. Wenn deine LED dann mit 1Hz 
blinkt, dann läuft die CPU wirklich mit 1MHz. Falls es doch 8MHz sein 
sollten, siehst du es direkt.

von Janos (Gast)


Lesenswert?

Axel S. schrieb:
> Der Mikrocontroller ist in dem Fusebits auf Grundeinstellung 1Mhz
> interner Quarz eingestellt
>
> Es gibt keinen "internen Quarz". Du meinst wohl, er ist auf den internen
> RC-Oszillator gestellt und die CKDIV8 Fuse ist aktiviert, so daß er real
> mit 1MHz Takt läuft.
>
> Wenn ich den Code Compiliere mit #define F_CPU 1000000UL zeigt das
> Display nichts an aber sobald ich den Wert auf 8000000UL anhebe zeigt
> das Display das gewollte Zeichen an.
>
> Das würde bedeuten, daß entweder
>
> - dein ATMega16 doch schneller als mit 1MHz läuft -oder-

Deine interpretation ist etwas merkwürdig, warum sollte die CPU 
schneller laufen, wenn man im Code eine höhere angeben muss?

Er läuft mit 1Mhz und hat CKDIV8 an. Dadurch läuft er real nur mit 
125khz. Damit die Software nun richtig läuft, wird dem Programm 
vorgegaukelt, 8 mal länger warten zu müssen (8mhz statt 1Mhz also 8 mal 
länger für Timer und sonstiges zählen) dadurch kommt er dann mit 125khz 
wieder auf 1Mhz.

Oder anders, die Frequenz des internen Oszillators wird durch 8 geteilt 
mit dem Fuse CKDIV8, und dann wieder mit 8 multipliziert durch 8mhz 
anstatt 1Mhz Angabe. Am Ende kommt dann 1 als Multiplikator raus

von Wolfgang (Gast)


Lesenswert?

Janos schrieb:
> Er läuft mit 1Mhz und hat CKDIV8 an

Wo soll bei einem ATmega16 eine CKDIV8 fuse sitzen?
Weder das DS noch der Fuse Calculator kennt die.
http://www.engbedded.com/fusecalc

von Peter D. (peda)


Lesenswert?

Pierre G. schrieb:
> obwohl der interne Quarz mit 1mhz gewählt wurde

Sicher?
Zeig mal die Fusebytes.

von Axel S. (a-za-z0-9)


Lesenswert?

Janos schrieb:
> Axel S. schrieb:
>> Der Mikrocontroller ist in dem Fusebits auf Grundeinstellung 1Mhz
>> interner Quarz eingestellt
>>
>> Es gibt keinen "internen Quarz". Du meinst wohl, er ist auf den internen
>> RC-Oszillator gestellt und die CKDIV8 Fuse ist aktiviert, so daß er real
>> mit 1MHz Takt läuft.
>>
>> Wenn ich den Code Compiliere mit #define F_CPU 1000000UL zeigt das
>> Display nichts an aber sobald ich den Wert auf 8000000UL anhebe zeigt
>> das Display das gewollte Zeichen an.
>>
>> Das würde bedeuten, daß entweder
>>
>> - dein ATMega16 doch schneller als mit 1MHz läuft -oder-
>
> Deine interpretation ist etwas merkwürdig, warum sollte die CPU
> schneller laufen, wenn man im Code eine höhere angeben muss?

Das F_CPU Makro dient nicht zur Einstellung der Taktfrequenz. Mit 
diesem Makro teilst du <delay.h> mit, mit welcher Taktfrequenz dein 
Controller läuft, damit es ausrechnen kann, wieviele Durchläufe der 
Warteschleife gebraucht werden, um z.B. 5µs zu warten.

Wenn man hier einen zu großen Wert angibt, dauert die Warterei 
entsprechend länger. Bei einem zu kleinen dann kürzer.

> Er läuft mit 1Mhz und hat CKDIV8 an. Dadurch läuft er real nur mit
> 125khz.

Quatsch. Ich habe gerade erst mal selber in das Datenblatt schauen 
müssen (habe noch was mit dem ATMega16 gemacht). Der hat gar keine 
CKDIV8 Fuse. Allerdings kann der interne RC-Oszillator wahlweise mit 1, 
2, 4 oder 8MHz laufen. Default ist 1MHz.

von Pierre G. (bqube)


Angehängte Dateien:

Lesenswert?

Ich teste gleich mal die idee mit der blinkfrequenz von 1s und im anhang 
schicke ich einmal einen Screenshoot von den Fuses.

von Pierre G. (bqube)


Lesenswert?

Als nächstes hab ich ganz Simpel 1000ms an und 1000ms aus und siehe da 
genau das macht der Uc auch hatte den internen oszillator auf 8 Mhz 
erhört und das Programm darauf hin angepasst aber das Display regiert 
nicht hab auch das Display ausgetauscht selbes ergebnis.

Meine nächste idee wäre es Extern einen quarz anzulöten und dann nochmal 
das selbe versuchen.

von Peter D. (peda)


Lesenswert?

Zeig doch mal das .lss-File (als Dateianhang).

von Forist (Gast)


Lesenswert?

Pierre G. schrieb:
> Als nächstes hab ich ganz Simpel 1000ms an und 1000ms aus und siehe da
> genau das macht der Uc auch hatte den internen oszillator auf 8 Mhz
> erhört und das Programm darauf hin angepasst aber das Display regiert
> nicht hab auch das Display ausgetauscht selbes ergebnis

Von Satzzeichen hast du wohl noch nie etwas gehört oder ist das reine 
Faulheit?

von Axel S. (a-za-z0-9)


Lesenswert?

Pierre G. schrieb:
> Als nächstes hab ich ganz Simpel 1000ms an und 1000ms aus und siehe da
> genau das macht der Uc auch hatte den internen oszillator auf 8 Mhz
> erhört und das Programm darauf hin angepasst aber das Display regiert
> nicht hab auch das Display ausgetauscht selbes ergebnis.

An sich sieht dein Timing gut aus. Nur daß du halt die Setup- und 
Hold-Zeiten bezüglich des Impulses am E-Pin nicht einhältst. Probier mal
1
void Setup(void)
2
{
3
  _delay_us(1);
4
  SteuerPort |= (1 << 0);
5
  _delay_us(2);
6
  SteuerPort &= ~(1 << 0);
7
  _delay_us(1);
8
}

und genauso in der Text() Funktion.

von Pierre G. (bqube)


Angehängte Dateien:

Lesenswert?

Axel S. schrieb:
> Pierre G. schrieb:
>> Als nächstes hab ich ganz Simpel 1000ms an und 1000ms aus und siehe da
>> genau das macht der Uc auch hatte den internen oszillator auf 8 Mhz
>> erhört und das Programm darauf hin angepasst aber das Display regiert
>> nicht hab auch das Display ausgetauscht selbes ergebnis.
>
> An sich sieht dein Timing gut aus. Nur daß du halt die Setup- und
> Hold-Zeiten bezüglich des Impulses am E-Pin nicht einhältst. Probier mal
>
>
1
> void Setup(void)
2
> {
3
>   _delay_us(1);
4
>   SteuerPort |= (1 << 0);
5
>   _delay_us(2);
6
>   SteuerPort &= ~(1 << 0);
7
>   _delay_us(1);
8
> }
9
>
>
> und genauso in der Text() Funktion.

Ändert leider nichts an der Funktion, hab das Program nun so abgeändert 
und die .lss Datei angehängt.
1
#include <avr/io.h>
2
#ifndef F_CPU
3
#define F_CPU 1000000UL
4
#endif
5
#include <util/delay.h>
6
#define DatenPort PORTB
7
#define SteuerPort PORTD
8
9
void Setup(void)
10
{
11
  _delay_us(1);
12
  SteuerPort |= (1 << 0);
13
  _delay_us(2);
14
  SteuerPort &= ~(1 << 0);
15
  _delay_us(1);
16
}
17
18
void Text(void)
19
{
20
  _delay_us(1);
21
  SteuerPort |= (1 << 0);
22
  _delay_us(2);
23
  SteuerPort |= (1 << 2);
24
  _delay_us(2);
25
  SteuerPort &= ~(1 << 0);
26
  _delay_us(2);
27
  SteuerPort &= ~(1 << 2);
28
  _delay_us(1);
29
}
30
31
int main(void)
32
{
33
  DDRB = 0xFF;
34
  DDRD = 0xFF;
35
  PORTB = 0x00;
36
  {
37
    _delay_ms(15);
38
    DatenPort = 0b00110000; //Interface auf 8-Bit setzen
39
    Setup();
40
    DatenPort = 0x00;
41
42
    _delay_ms(5);
43
    DatenPort = 0b00110000; //Interface auf 8-Bit setzen
44
    Setup();
45
    DatenPort = 0x00;
46
47
    _delay_us(120);
48
    DatenPort = 0b00110000; //Interface auf 8-Bit setzen
49
    Setup();
50
    DatenPort = 0x00;
51
52
    _delay_us(120);
53
    DatenPort = 0b00110000; //Interface auf 8-Bit setzen
54
    Setup();
55
    DatenPort = 0x00;
56
57
    _delay_us(120);
58
    DatenPort = 0b00111000; //2-zeilig, 5x8-Punkt-Matrix
59
    Setup();
60
    DatenPort = 0x00;
61
62
    _delay_us(120);
63
    DatenPort = 0b00001000; //Display aus
64
    Setup();
65
    DatenPort = 0x00;
66
67
    _delay_us(120);
68
    DatenPort = 0b00000001; //Display löschen
69
    Setup();
70
    DatenPort = 0x00;
71
72
    _delay_us(120);
73
    DatenPort = 0b00000110; //Kursor nach rechts wandernd
74
    Setup();
75
    DatenPort = 0x00;
76
77
    _delay_us(120);
78
    DatenPort = 0b00001100; //Display ein
79
    Setup();
80
    DatenPort = 0x00;
81
82
    _delay_us(120);
83
    DatenPort = 'T';    // T Senden
84
    Text();
85
    DatenPort = 0x00;
86
  }
87
88
89
  
90
91
  while(1)
92
  {
93
  PORTD |= (1<<6);
94
  _delay_ms(500);
95
  PORTD &=~(1<<6);
96
  _delay_ms(500);
97
  }
98
}

von Wolfgang (Gast)


Lesenswert?

Pierre G. schrieb:
> #ifndef F_CPU
> #define F_CPU 1000000UL
> #endif

Soetwas kann eine ziemliche Falle sein.
Ist F_CPU möglicherweise schon vorher in der IDE definiert, aber anders?

von Pierre G. (bqube)


Lesenswert?

Wolfgang schrieb:
> Pierre G. schrieb:
>> #ifndef F_CPU
>> #define F_CPU 1000000UL
>> #endif
>
> Soetwas kann eine ziemliche Falle sein.
> Ist F_CPU möglicherweise schon vorher in der IDE definiert, aber anders?

? Ich bin da leider schon echt lange raus aus dem Thema, gibt es denn 
irgendwo die möglich die frequenz für den Compiler einzustellen.

MFG

von Wolfgang (Gast)


Lesenswert?

Pierre G. schrieb:
> gibt es denn irgendwo die möglich die frequenz für den
> Compiler einzustellen

Der Compiler hat da nichts mit zu tun. Der nimmt, was er vom 
Präprozessor übergeben bekommt.
Meist kann das in der IDE unter irgendwelchen Defines eingetragen 
werden.
"avr studio 7" gibt es nicht. Entweder heißt deine IDE "Atmel Studio" 
oder du hast dich mit der "7" vertan. ;-)

von Peter D. (peda)


Lesenswert?

Das Listing ist korrekt für F_CPU = 1MHz.
Diese Loop dauert 3 Zyklen * 40 = 120 Zyklen;
1
  d0:  28 e2         ldi  r18, 0x28  ; 40
2
  d2:  2a 95         dec  r18
3
  d4:  f1 f7         brne  .-4        ; 0xd2 <main+0x46>
4
5
    _delay_us(120);

Zeig mal das Listing für 8MHz.

von Stefan F. (Gast)


Lesenswert?

Pierre G. schrieb:
> Ich bin da leider schon echt lange raus aus dem Thema, gibt es denn
> irgendwo die möglich die frequenz für den Compiler einzustellen.

Das Stichwort dazu heißt "defines". In den meisten 
Entwicklungsumbegungen kann man Definitionen in den Projekteinstellungen 
vornehmen. Teileweise als Dialogfenster aufbereitet, teilweise als 
simple Liste von Name/Werte Päärchen, wobei Defines auch ohne Wert (nur 
mit Name) existieren können.

Diese werden dem Compiler als Kommandozeilenparameter -D übergeben. 
Schau Dir mal an, wie diene Kommandozeile vom gcc Aufruf aussieht.

von Wolfgang (Gast)


Lesenswert?

Stefan ⛄ F. schrieb:
> Diese werden dem Compiler als Kommandozeilenparameter -D übergeben.

Auch um diese "defines" kümmert sich bereits der Präprozessor und der 
Compiler bekommt soetwas wie "F_CPU" gar nicht mehr zu sehen.

von Hugo H. (hugohurtig1)


Angehängte Dateien:

Lesenswert?

Wolfgang schrieb:
> Ist F_CPU möglicherweise schon vorher in der IDE definiert, aber anders?

Vermutlich da (Bild) :-)   Project -> Properties (letzter Eintrag in der 
Auswahlliste)

: Bearbeitet durch User
von Axel S. (a-za-z0-9)


Lesenswert?

Pierre G. schrieb:
> Wolfgang schrieb:
>> Pierre G. schrieb:
>>> #ifndef F_CPU
>>> #define F_CPU 1000000UL
>>> #endif
>>
>> Soetwas kann eine ziemliche Falle sein.
>> Ist F_CPU möglicherweise schon vorher in der IDE definiert, aber anders?
>
> ? Ich bin da leider schon echt lange raus aus dem Thema, gibt es denn
> irgendwo die möglich die frequenz für den Compiler einzustellen.

Der wesentliche Punkt ist IMHO nicht rüber gekommen.

Es ist vollkommen egal, ob man F_CPU im Quelltext per #define festlegt 
oder ob man das in der Build-Umgebung macht (Makefile, IDE, $WHATEVER).

Der Fehler besteht darin, beim Fehlen dieses Makros einfach einen aus 
den Fingern gesaugten Wert einzusetzen. Wenn man das wegläßt, dann wird 
<util/delay.h> eine Fehlermeldung werfen, daß F_CPU nicht definiert ist. 
Und das ist wesentlich hilfreicher, weil man dann weiß, daß man was 
vergessen hat. Der jetzige Zustand überdeckt den eigentlichen Fehler und 
macht ihn dadurch schwerer zu finden.

von Wolfgang (Gast)


Lesenswert?

Axel S. schrieb:
> Es ist vollkommen egal, ob man F_CPU im Quelltext per #define festlegt

Genau, die Falle ist die Verpackung der Festlegung in #ifndef ... #endif

von Pete K. (pete77)


Lesenswert?

Hugo H. schrieb:
> Wolfgang schrieb:
>> Ist F_CPU möglicherweise schon vorher in der IDE definiert, aber anders?
>
> Vermutlich da (Bild) :-)   Project -> Properties (letzter Eintrag in der
> Auswahlliste)

32000000 ist dann wohl etwas zu viel.

von Hugo H. (hugohurtig1)


Lesenswert?

Pete K. schrieb:
> 32000000 ist dann wohl etwas zu viel.

Du bist ja ein ganz schlauer Typ.

von c-hater (Gast)


Lesenswert?

Axel S. schrieb:

> Quatsch. Ich habe gerade erst mal selber in das Datenblatt schauen
> müssen (habe noch was mit dem ATMega16 gemacht). Der hat gar keine
> CKDIV8 Fuse. Allerdings kann der interne RC-Oszillator wahlweise mit 1,
> 2, 4 oder 8MHz laufen. Default ist 1MHz.

Das stimmt so nicht.

Der Oszillator selber läuft immer mit ca. 8Mhz (sofern nicht mutwillig 
per OSCCAL davon abgebracht).

Die Fuses der ollen Megas machen letztlich dasselbe wie die der 
modernen, sprich: sie steuern einen Prescaler. Der einzige Unterschied 
ist halt, dass man bei den moderneren Megas auch softwaremäßigen Zugriff 
auf den Prescaler hat, dafür aber eben weniger per Fuse festlegen kann, 
nämlich darüber nur noch aus zwei Varianten wählen kann, statt der vier 
der ollen Megas.

Oder anders ausgedrückt: hier wurde schlicht eine Fuse eingespart, um 
sie anderen Zwecken widmen zu können.

von Peter D. (peda)


Lesenswert?

Pierre G. schrieb:
> ich hatte damals ein LCD Projekt
> hier im Forum was auch super lief

Nö.
Dein Programm ist fehlerhaft, kann also nie gelaufen sein. Einige 
Befehle dauern 1,64ms, Du wartest aber nur 120µs. Dadurch werden 
nachfolgende Befehle nicht ausgeführt.

von Pierre G. (bqube)


Lesenswert?

Guten Tag und vielen Dank für die großartige Hilfestellung hier im 
Forum,
ich habe nun nochmal das Internet durchsucht und alles zusammengetragen 
was man zum Timing wissen sollte.

Ich hab nun nochmal das komplette Programm neugeschrieben (Bitte kein 
Kommentar warum ich keine Funktionen benutzte für mich ist es so erstmal 
einfacher) aber das Ergebnis ist immer noch dasselbe.

Nicht wundern warum der DatenPort sich geändert hat von B auf C, ich 
habe um Fehler eingrenzen zu können das ganze nun auf eine Lochraster 
Platine aufgelötet.
1
#include <avr/io.h>
2
#ifndef F_CPU
3
#define F_CPU 1000000UL
4
#endif
5
#include <util/delay.h>
6
7
int main(void)
8
{
9
  DDRC = 0xFF;
10
  DDRD = 0xFF;
11
  
12
  
13
  _delay_ms(15); // Reset Abwarten
14
  
15
  PORTC = 0b00110000; // 8 Bit Modus muss 3 mal gesendet werden.
16
  _delay_us(5);
17
  
18
  PORTD |=  (1<<7);  // Enable auf PORTD Bit7
19
  _delay_us(5);
20
  PORTD &=~ (1<<7);
21
  _delay_us(5);
22
  
23
  _delay_ms(5);    // Interne verarbeitung abwarten
24
  
25
  PORTD |=  (1<<7);
26
  _delay_us(5);
27
  PORTD &=~ (1<<7);
28
  _delay_us(5);
29
  
30
  _delay_ms(5);      // Interne verarbeitung abwarten
31
  
32
  PORTD |=  (1<<7);
33
  _delay_us(5);
34
  PORTD &=~ (1<<7);
35
  _delay_us(5);
36
  
37
  _delay_us(100);
38
  PORTC =   0b00110000;  // 8 Bit Modus senden
39
  _delay_us(5);
40
  
41
  PORTD |=  (1<<7);
42
  _delay_us(5);
43
  PORTD &=~ (1<<7);
44
  _delay_us(5);
45
  
46
  _delay_us(100);
47
  PORTC =  0b00111000;  // 8 Bit / 2 Zeilen / 5x8 Matrix senden
48
  _delay_us(5);
49
  
50
  PORTD |=  (1<<7);
51
  _delay_us(5);
52
  PORTD &=~ (1<<7);
53
  _delay_us(5);
54
  
55
  _delay_us(100);
56
  PORTC = 0b00001000;    // Display AUS
57
  _delay_us(5);
58
  
59
  PORTD |=  (1<<7);
60
  _delay_us(5);
61
  PORTD &=~ (1<<7);
62
  _delay_us(5);
63
  
64
  _delay_us(100);
65
  PORTC = 0b00000001;    // Display Löschen
66
  _delay_us(5);
67
  
68
  PORTD |=  (1<<7);
69
  _delay_us(5);
70
  PORTD &=~ (1<<7);
71
  _delay_us(5);
72
  
73
  _delay_us(100);
74
  PORTC = 0b00000110;    // Kurser nach rechts kein Display shift
75
  _delay_us(5);
76
  
77
  PORTD |=  (1<<7);
78
  _delay_us(5);
79
  PORTD &=~ (1<<7);
80
  _delay_us(5);
81
  
82
  _delay_us(100);
83
  PORTC = 0b00001100;    // Display Ein
84
  _delay_us(5);
85
  
86
  PORTD |=  (1<<7);
87
  _delay_us(5);
88
  PORTD &=~ (1<<7);
89
  _delay_us(5);
90
  
91
  _delay_us(100); // T
92
  PORTC = 'T';
93
  _delay_us(5);
94
  PORTD |= (1<<5);
95
  _delay_us(5);
96
  PORTD |= (1<<7);
97
  _delay_us(5);
98
  PORTD = 0x00;
99
  PORTC = 0x00;
100
  _delay_us(5);
101
  
102
  
103
  
104
  while(1)
105
  {
106
    PORTD |= (1<<6);
107
    _delay_ms(500);
108
    PORTD &=~ (1<<6);
109
    _delay_ms(500);
110
  }
111
}

von Holger L. (max5v)


Lesenswert?

Weiter oben im Thread wurde ein Bild von den Fuse Einstellungen gezeigt, 
aus dem ersichtlich ist das JTAG eingeschaltet ist.
Ich bin mir nicht 100% sicher, meine aber mal gelesen zu haben, das es 
dadurch zu Problemen an den Pins PC2 - PC5 kommt.

von Pierre G. (bqube)


Lesenswert?

Holger L. schrieb:
> Weiter oben im Thread wurde ein Bild von den Fuse Einstellungen gezeigt,
> aus dem ersichtlich ist das JTAG eingeschaltet ist.
> Ich bin mir nicht 100% sicher, meine aber mal gelesen zu haben, das es
> dadurch zu Problemen an den Pins PC2 - PC5 kommt.

Okay danke das schau ich mir mal an.

von S. Landolt (Gast)


Lesenswert?

Holger L. schrieb:
>  ... zu Problemen an den Pins PC2 - PC5 kommt.


JTAG - "We call it a Klassiker"

("When the JTAG interface is enabled, this pin can not be used as an I/O 
pin.)

von Pierre G. (bqube)


Angehängte Dateien:

Lesenswert?

Ich hab mal mit dem Handy ein Foto vom PORTD. 6 gemacht, wo man das 
Timing recht gut erkennen kann  und ich finde da sieht man ganz gut die 
500ms.

von Pierre G. (bqube)


Lesenswert?

Geschafft … uff ich hab jetzt nach jedem Befehl die Wartezeit für den 
Nächsten Befehl auf 2ms angehoben und siehe da jetzt gibt das Display 
auch Zeichen aus.

Ich hatte auch die Datenleitung vom Display wieder auf den PORTB gelegt, 
da auf PORTC einige PORT's High Signal tragen, kann man die PORT's auch 
über Fuses umschalten oder ist das nicht möglich.

Mfg

von Magnus M. (magnetus) Benutzerseite


Lesenswert?

Pierre G. schrieb:
> Ich hatte auch die Datenleitung vom Display wieder auf den PORTB gelegt,
> da auf PORTC einige PORT's High Signal tragen, kann man die PORT's auch
> über Fuses umschalten oder ist das nicht möglich.

Siehe...

Holger L. schrieb:
> Weiter oben im Thread wurde ein Bild von den Fuse Einstellungen
> gezeigt,
> aus dem ersichtlich ist das JTAG eingeschaltet ist.
> Ich bin mir nicht 100% sicher, meine aber mal gelesen zu haben, das es
> dadurch zu Problemen an den Pins PC2 - PC5 kommt.

von Peter D. (peda)


Lesenswert?

Pierre G. schrieb:
> ich hab jetzt nach jedem Befehl die Wartezeit für den
> Nächsten Befehl auf 2ms angehoben

Man muß nicht gleich übertreiben. Schau mal ins Datenblatt des HD44780. 
Es sind nur 2 Befehle, die max 1,64ms dauern.

von Axel S. (a-za-z0-9)


Lesenswert?

Pierre G. schrieb:
> ich hab jetzt nach jedem Befehl die Wartezeit für den
> Nächsten Befehl auf 2ms angehoben und siehe da jetzt gibt das Display
> auch Zeichen aus.

Kanonen auf Spatzen.

Du mußt nicht nach jedem Befehl 2ms warten. Sondern nur nach denen, 
die länger dauern.

Und überhaupt: die deutlich bessere Strategie besteht darin, das BUSY 
Flag des Displays auszulesen. Wenn du das gemacht hättest, dann hätte es 
den ganzen Thread von Anfang an nicht gebraucht. Stumpfes Warten ist nur 
die zweitbeste (von zwei möglichen) Strategien.

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.