Optimierung bei delay.h

Gast #1550501
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
#1550534
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"?
Gast #1550542
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
}
#1550568
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...
Gast #1550582
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.
Gast #1550587
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 ;)
Gast #1550593
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.
Gast #1550596
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

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