Forum: Mikrocontroller und Digitale Elektronik Optimierung bei delay.h


von marcel (Gast)


Lesenswert?

Nabend

Ich habe auch ein Problem bezueglich der Optimierung der Schleifen.
Habe nun gut ne Stunde gesucht, bis ich rausgefunden habe, dass meine 
Delayschleifen beim Initialisieren des LCD's vom Compiler wegoptimiert 
werden.

Nein, ich verwende keine eigene Schleifen sondern wie empfohlen die aus 
util/delay.h

Mit eingestellten -O0 funktioniert alles (auch wenn die delay.h wohl 
nicht absolut genau arbeitet) sobald ich jedoch auf -Os gehe, tut gar 
nix mehr.

Hat jemand eine Idee an was das problem liegen kann?

Im Einsatz sind:
AVR-Studio Version 4.14 und WinAVR 20090313

von marcel (Gast)


Lesenswert?

Oh!
Ich habe mich auf folgenden Beitrag bezogen
Beitrag "Warteschleife mit C - wird von WinAVR wegrationalisiert!"

Nur auf "neuer Beitrag" anstatt "Antworten" gedrueckt. War ein langer 
Arbeitstag ...

von Thomas (Gast)


Lesenswert?

Bitte Quellcode posten?

von Εrnst B. (ernst)


Lesenswert?

marcel schrieb:
> Mit eingestellten -O0 funktioniert alles (auch wenn die delay.h wohl
> nicht absolut genau arbeitet) sobald ich jedoch auf -Os gehe, tut gar
> nix mehr.

mit -O0 ist "nicht absolut genau" eine Untertreibung. Je nach Parameter 
liegt die Delay-Time damit um einen Faktor 1000 daneben.
nur mit Optimierung kommt eine richtige Delay-Zeit heraus.

Du hast nicht zufällig ms und µs in den Parametern verwechselt, und das 
Delay war mit -O0 nur rein zufällig "richtig"?

von marcel (Gast)


Lesenswert?

Prinzipiell der Code aus dem LCD AVR-GCC Tutorial

lcd.h:
1
#ifndef F_CPU
2
#define F_CPU 16000000UL     /* Quarz mit 16 Mhz */
3
#warning "F_CPU not defined. Define default Value 16Mhz"
4
#endif
5
6
//Default Port Definitions
7
#ifndef LCD_PORT
8
#define LCD_PORT  PORTA
9
#warning "LCD_PORT not defined. Define default Value Port A"
10
#endif
11
12
#ifndef LCD_DDR
13
#define LCD_DDR    DDRA
14
#warning "LCD_DDR not defined. Define default Value DDRA"
15
#endif
16
17
#ifndef PIN_RS
18
#define PIN_RS    4
19
#warning "PIN_RS not defined. Define default Value 4"
20
#endif
21
22
#ifndef PIN_E
23
#define PIN_E    5
24
#warning "PIN_E not defined. Define default Value 5"
25
#endif
26
27
//LCD Commands
28
#define LCD_CURSOR_HOME    2
29
#define LCD_CLEAR_DISPLAY  1
30
31
//LCD Functions
32
void lcd_enable(void);
33
void lcd_init(void);
34
void lcd_cmd(unsigned char);
35
void lcd_data(unsigned char);
36
void lcd_clear(void);
37
void lcd_home(void);

lcd.c:
1
#include <avr/io.h>
2
#include "lcd.h"
3
#include <util/delay.h>
4
5
void lcd_enable(void)
6
{
7
  LCD_PORT |= (1 << PIN_E);
8
  _delay_us(1);
9
  LCD_PORT &= ~(1 << PIN_E);
10
}
11
12
void lcd_init(void)
13
{
14
  LCD_DDR = (LCD_DDR | 0x0F | 1<<PIN_E | 1<<PIN_RS);
15
16
  _delay_ms(15);    //Wait for LCD Initialization
17
18
  //Initialize LCD
19
  LCD_PORT &= 0xF0;
20
  LCD_PORT |= 0x03;
21
  LCD_PORT &= ~(1<<PIN_RS);
22
23
  lcd_enable();
24
  _delay_ms(5);
25
26
  lcd_enable();
27
  _delay_ms(1);
28
29
  lcd_enable();
30
  _delay_ms(1);
31
32
  //4bit Mode
33
  LCD_PORT &= 0xF0;
34
  LCD_PORT |= 0x02;
35
  lcd_enable();
36
  _delay_ms(1);
37
38
  lcd_cmd(0x28);     //Config - 4bit, 2/4 Lines, 5x7 Font
39
  lcd_cmd(0x0C);    //Config - Display on, Cursor Off
40
  lcd_cmd(0x06);    //Config - LTR, scroll Display
41
42
  lcd_clear();
43
}
44
45
void lcd_cmd(unsigned char cmd)
46
{
47
  unsigned char tmp = cmd;
48
49
  LCD_PORT &= ~(1<<PIN_RS);
50
51
  tmp = tmp >> 4;
52
  tmp &= 0x0F;
53
  LCD_PORT &= 0xF0;
54
  LCD_PORT |= tmp;
55
  lcd_enable();
56
57
  cmd &= 0x0F;
58
  LCD_PORT &= 0xF0;
59
  LCD_PORT |= cmd;
60
  lcd_enable();
61
62
  _delay_us(42);
63
}
64
65
void lcd_data(unsigned char data)
66
{
67
  unsigned char tmp = data;
68
  LCD_PORT |= (1<<PIN_RS);
69
70
  tmp = tmp >> 4;
71
  tmp &= 0x0F;
72
  LCD_PORT &= 0xF0;
73
  LCD_PORT |= tmp;
74
  lcd_enable();
75
76
  data &= 0x0F;
77
  LCD_PORT &= 0xF0;
78
  LCD_PORT |= data;
79
  lcd_enable();
80
81
  _delay_us(42);
82
}
83
84
void lcd_clear(void)
85
{
86
   lcd_cmd(LCD_CURSOR_HOME);
87
   _delay_ms(5);
88
}
89
void lcd_home(void)
90
{
91
   lcd_cmd(LCD_CLEAR_DISPLAY);
92
   _delay_ms(5);
93
}

der Aufruf sieht folgendermassen aus (test.c):
1
#ifndef F_CPU
2
#define F_CPU     16000000UL     /* Quarz mit 16 Mhz */
3
#endif
4
5
#define LCD_PORT  PORTA
6
#define LCD_DDR    DDRA
7
#define PIN_E    PINA5
8
#define PIN_RS    PINA4
9
10
#include "lcd.h"
11
#include <avr/io.h>
12
#include <util/delay.h>
13
14
int main (void) {
15
  lcd_init();
16
17
  lcd_data('T');
18
  lcd_data('e');
19
  lcd_data('s');
20
  lcd_data('t');
21
22
  while(1) { }
23
  return 0;
24
}

von Εrnst B. (ernst)


Lesenswert?

Und die Delay-Werte passen auch zu deinem LCD? Datenblatt?
Versuch einfach mal die Delay-werte alle zu verdoppeln, schau ob es dann 
geht. Dann kannst du dich immer noch an bessere Werte rantasten.
Oder (noch besser): Nimm eine LCD-Library mit Auswertung des 
LCD-Status-Bits, da gehts dann großteils ohne Warten.
Und schalte die Compiler-Warnings ein, und achte auf diese! Der Compiler 
spuckt die nicht zum Spaß aus...

von holger (Gast)


Lesenswert?

>Oder (noch besser): Nimm eine LCD-Library mit Auswertung des
>LCD-Status-Bits, da gehts dann großteils ohne Warten.

Selten einen größeren Unsinn gelesen.

von Simon K. (simon) Benutzerseite


Lesenswert?

holger schrieb:
>>Oder (noch besser): Nimm eine LCD-Library mit Auswertung des
>>LCD-Status-Bits, da gehts dann großteils ohne Warten.
>
> Selten einen größeren Unsinn gelesen.

Was stimmt denn daran nicht? Man kann das Bit auch pollen und die Daten 
aus einem Puffer rübersenden, dann braucht man nicht drauf warten.

von marcel (Gast)


Lesenswert?

Ich hab die Werte nun vervierfacht und es macht keinen Unterschied!

Wenn ich mir die hex file nehme und disassemble, seh ich ja, dass die 
schleifen komplett wegoptimiert wurden.
Der Programmablauf an sich passt, nur die Schleifen tauchen in der 
disassembly einfach nicht auf.

von marcel (Gast)


Lesenswert?

Ach ja ... ich vergas zu erwaehnen, dass der compiler keine warnings 
wirft, ausser dass meine eigenen Varriablen nicht definiert sind und 
daher auf die default werte gesetzt werden (da ich die ja aber auch 
selbst definiere passen die auch ;)

von Εrnst B. (ernst)


Lesenswert?

marcel schrieb:

> Der Programmablauf an sich passt, nur die Schleifen tauchen in der
> disassembly einfach nicht auf.

Ups. Das sollte nun wirklich nicht passieren.
Schau mal nach nem WinAVR-Update, oder hol dir aktuelle util/delay.h und 
util/delay_basic.h - Dateien vom avr-libc server.

von holger (Gast)


Lesenswert?

>>>Oder (noch besser): Nimm eine LCD-Library mit Auswertung des
>>>LCD-Status-Bits, da gehts dann großteils ohne Warten.
>>
>> Selten einen größeren Unsinn gelesen.

>Was stimmt denn daran nicht? Man kann das Bit auch pollen und die Daten
>aus einem Puffer rübersenden, dann braucht man nicht drauf warten.

Das Statusbit kann man am Anfang der LCDInit gar nicht pollen.
Steht jedenfalls so in meinen Datenblättern zu LCDs.
Pollen des Statusbits bedeutet auch warten.

von marcel (Gast)


Lesenswert?

Problem hat sich soeben geloest...

Ich hab mir die Compiler Optionen nochmals genau angesehn und 
festgestellt, dass 16hz anstatt 16000000hz eingestellt waren

Jetzt gehts.

Wieso kann man sowas auch nicht in ner tauglichen Einheit abfragen

maaaan!
Danke an alle

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.