Forum: Mikrocontroller und Digitale Elektronik Optimierung (Optimization)<->Probleme


von Robert P. (Firma: ---) (ausmilkel)


Lesenswert?

Hallo,

ich bin ein noch unerfahrener Programmierer in Bezug auf AVR. Habe 
Grundkentnisse in C und mir schon ein Programm zur Ansteuerung für ein 
Display implementiert und auch schon andere dazugehörige Programmabläufe 
um es dann zu visualisieren. Da die Code-größe jedoch sehr schnell 
"explodiert" probierte ich die Option zum Optimieren des Quellcodes 
(Optimization). Das Problem: vor der Optimierung verhielt sich das 
Programm ordnungsgemäß ( nach meinen Erwartungen ), wenn ich jedoch die 
verschiedenen Optimierungsgrade verwende kommen teiweise wirre Zeichen 
auf meinem Display zum Vorschein ( zusätzliche Buchstaben...). Teilweise 
wird auch der Programmablauf komplett gestört, beispielsweise nur zum 
Teil ausgeführt.

Hat jemand ähnliche Erfahrungen, Tipps oder Links zu Threads die mir 
helfen könnten?
Bei Bedarf kann ich auch den Quellcode schicken, ist halt nur "sehr 
viel", da ich viele eigene Headerdateien verwende.

mfg

Robert

von Berti (Gast)


Lesenswert?

for schleifen
1
for(i=0;i<100;i++);
werden eventuell "wegoptimiert"
da hilft ein
1
asm"nop"
 in der for Schleife

von Falk B. (falk)


Lesenswert?

@ Robert P. (Firma ---) (ausmilkel)

>(Optimization). Das Problem: vor der Optimierung verhielt sich das
>Programm ordnungsgemäß ( nach meinen Erwartungen ), wenn ich jedoch die
>verschiedenen Optimierungsgrade verwende kommen teiweise wirre Zeichen

Unsaubere Programmierung, selbstgebastelte Delays, etc.

>Bei Bedarf kann ich auch den Quellcode schicken, ist halt nur "sehr
>viel", da ich viele eigene Headerdateien verwende.

Pack es alles in ein ZIP und poste es hier.

MFG
Falk

von Robert P. (Firma: ---) (ausmilkel)


Angehängte Dateien:

Lesenswert?

Ok

hab hier im Anhang mal alles als ZIP-File angehangen. Ist doch nicht 
mehr so ivle Quellcode, hab nicht alles genutzt.

danke schon mal.

mfg
Robert

von Falk B. (falk)


Lesenswert?

@ Robert P. (Firma ---) (ausmilkel)

>hab hier im Anhang mal alles als ZIP-File angehangen. Ist doch nicht
>mehr so ivle Quellcode, hab nicht alles genutzt.

Nun, das sieht man recht schnell.
1
//
2
//
3
// external clock 12Mhz
4
//
5
//
6
#include <avr/io.h>
7
#include <stdlib.h>
8
#include <util/delay.h>
9
#include <stdio.h>
10
#include <string.h>
11
[c]
12
13
Dein AVR läuft mit 12 MHz, aber wo ist das define für F_CPU?
14
15
Wenn das fehlt bzw. im AVR-Studio falsch angegeben ist, dann arbeiten die delay-Funktionen mit angenommenen 1 MHz. Dadurch werden aber deine Delays zu kurz (jetzt sind sie auf Grund der fehlenden Optimierung und der dadurch implementierten Fliesskommaberechnung wesentlich zu lang).
16
17
Also ein 
18
19
[c]
20
#define F_CPU 12000000L

VOR die Verwendnung von #include <util/delay.h> einfügen.

MFG
Falk

von Robert P. (Firma: ---) (ausmilkel)


Lesenswert?

das mit der Frequenz kann man doch unter Project-> Configuration options 
und dann unter General bei frequency eintragen !? Hatte bisher 
funktioniert, jedenfalls laut Simulation. Ich trag es trotzdem noch in 
den Quellcode ein und probiere es.

mfg
Rober

von Karl H. (kbuchegg)


Lesenswert?

Da haben wir schon mal den ersten

in lcdroutines.c findet sich

void lcd_data_2xint(unsigned int wert)
{
   int i=0;
   unsigned char temp22=0,temp12=0;
   char change[2]={0},temp[1]={0};

   if(wert>=10)  itoa(wert,change,10);

wenn wert größer als 10 ist, dann wird die ASCII
Repräsentierung davon logischerweise aus mehr als 2
Zeichen bestehen. Aus der Zahl 123 wird der String
"123". Das sieht auf den ersten Blick nach 3 Zeichen
aus. In Wirklichkeit braucht der String aber 4 Bytes,
weil jeder String in C mit einem '\0' Zeichen abgeschlossen
wird.

Das Feld, in welches du itoa schreiben lässt, ist aber
nur 2 Zeichen gross. Ergo-> die restlichen 2 Zeichen
landen im Speicher an Positionen die nicht mehr zu change
gehören.    Buum

Selbiges im einstelligen Fall. Wenn deine Zahl kleiner
9 ist, dann besteht der enstehende String aus 2 Zeichen.
Nämlich der '9' und dem obligatorischen abschliessenden
'\0' Zeichen.


Mir ist insgesammt nicht wirklich klar, was du
damit

void lcd_data_2xint(unsigned int wert)
{
   int i=0;
   unsigned char temp22=0,temp12=0;
   char change[2]={0},temp[1]={0};

   if(wert>=10)  itoa(wert,change,10);
   else { change[0]='0';
   itoa(wert,temp,10);
   strcat(change,temp);}

   for(i=0;i<=1;i++)
   {temp22=change[i];
   temp12=temp22;


bezwecken willst.

Ich werd das mal etwas umformatieren, damit man die Programm-
logik etwas besser sieht

void lcd_data_2xint(unsigned int wert)
{
   int i=0;
   unsigned char temp22=0,temp12=0;
   char change[2]={0};
   char temp[1]={0};

   if( wert >= 10 )
     itoa( wert,change,10 );
   else {
     change[0]='0';
     itoa( wert, temp, 10);
     strcat( change, temp );
   }

Ach, jetzt verstehe ich. Du willst führende Nullen haben.
Warum benutzt du eigentlich in dieser Funktion nicht die Funktion
lcd_string. Nach diesem ganzen Hack-Mack von da oben ist doch
das Endergebnis ein String. Und die Funktion um diesen auszugeben
heist nun mal lcd_string. Kein Grund das ganze Bit-gewackle
auch noch in diese Funktion hineinzupacken.
1
void lcd_data_2xint( unsigned int wert )
2
{
3
  char Ascii[10];    // langt dicke. Knausrig sein an dieser
4
                     // Stelle ist meist keine gute Idee
5
6
  itoa( wert, Ascii, 10 );
7
8
  if( wert < 10 )     // ist eine führende 0 notwendig, wenn ja
9
    lcd_data( '0' );  // -> '0' ausgeben
10
11
  lcd_string( Ascii );  // und dann noch die Stringrepräsentierung
12
                        // der Zahl hinten nachschicken.
13
}


Mal schauen was sich sonst noch so alles findet :-)

von Karl H. (kbuchegg)


Lesenswert?

Der Rest sieht soweit beim schnellen drüberschauen eigentlich
ganz ok aus. Zumindest sollten keine wilden optimize-only
Effekte mehr drinnen sein.

Ein Wort noch:
Versuch möglichst bald zu einer vernünftigen Formatierung
zu kommen. Das was du zur Zeit hast ist noch sehr daneben.

Vergleich mal das hier
1
#include <stdlib.h>
2
#include <util/delay.h>
3
#include <stdio.h>
4
#include <string.h>
5
6
#include "lcdroutines.h"
7
#include "timefunktion.h"
8
#include "schrift_display.h"
9
10
11
12
13
int main(void)
14
{
15
   
16
  
17
   
18
   int minuten=0,sekunden=-1,hundertstel=-1,lauf=5,warte=0,z=0;
19
20
21
   lcd_init();
22
23
   
24
   hallo();         
25
26
   for(z=0;z<=180;z++)
27
   { _delay_ms(10); }
28
   lcd_clear();
29
   erste_zeile();   
30
31
32
   for(lauf=0;lauf<=120;lauf++)
33
       { 
34
       rise_time(&hundertstel);
35
       rise_time(&sekunden);    
36
         if(sekunden>=60) {rise_time(&minuten);sekunden=0;}
37
         
38
         zeitausgabe1(minuten,sekunden,hundertstel);
39
       for(warte=0;warte <=30;warte++)
40
         {_delay_ms(10);}
41
        } 
42
43
   while(1)
44
   {
45
       
46
   }
47
 
48
   return 0;
49
   
50
}

mit dem hier
1
#include <stdlib.h>
2
#include <util/delay.h>
3
#include <stdio.h>
4
#include <string.h>
5
6
#include "lcdroutines.h"
7
#include "timefunktion.h"
8
#include "schrift_display.h"
9
10
int main(void)
11
{
12
   int minuten     =  0
13
   int sekunden    = -1;
14
   int hundertstel = -1;
15
   int lauf        =  5;
16
   int warte       =  0;
17
   int z           =  0;
18
19
   lcd_init();
20
21
   hallo();         
22
23
   for( z = 0; z <= 180; z++ )
24
   {
25
     _delay_ms(10);
26
   }
27
28
   lcd_clear();
29
   erste_zeile();   
30
31
   for( lauf = 0; lauf <= 120; lauf++ )
32
   { 
33
     rise_time( &hundertstel );
34
     rise_time( &sekunden );    
35
     if( sekunden >= 60 )
36
     {
37
       rise_time( &minuten );
38
       sekunden = 0;
39
     }
40
         
41
     zeitausgabe1( minuten, sekunden, hundertstel );
42
43
     for( warte = 0; warte <= 30; warte++ )
44
     {
45
       _delay_ms(10);
46
     }
47
   } 
48
49
   while( 1 )
50
   {
51
   }
52
 
53
   return 0;
54
}

Es ist immer wieder interessant, dass Neulinge zwar möglichst
viel in einer Wurscht (also ohne Leerzeichen) dahinschreiben,
dafür aber eine Unmenge an aufeinanderfolgenden Leerzeilen
setzen.

* Aufeinanderfolgende Leerzeilen tragen selten zur Übersicht
  im Code bei. Wenn dir etwas wichtig genug ist, dass du
  es absetzen musst um es hervorzuheben, dann mach einfach nur
  eine Leerzeile und setzte einen Kommentar hinein, der den
  geneigten Leser darüber aufklärt was als nächstes passiert.
  Aber spar dir die vielen Leerzeilen. Sie ziehen den Code
  nur unnötig in die Länge.

* Für den Anfang:
  Eine Anweisung - Eine Zeile
  Bei einem if-Block ist das if und die davon abhängende
  Anweisung jeweils eine eigene Anweisung. Das if kriegt
  seine eigene Zeile. Die davon abhängenden Anweisung
  kriegt seine eigene Zeile (und ist eingerückt).

  Auf die Art vermeidest du Zeilen, die über den ganzen
  Bildschirm von links nach rechts reichen und das ganze
  wird auch optisch gegliedert. Auf der einen Seite (Zeile)
  die Bedingung, auf der anderen Seite (Zeile) das was von der
  Bedingung abhängt. Jede Information für sich kann so besser
  und schneller erfasst werden, als wie wenn du erst mal in dem
  Buchstabenwust die Teile auseinanderpfriemeln musst.

* Benutze Leerzeichen um den Code zu gliedern. Mach es dem
  Leser leicht, im Code einzelne 'Wörter' zu erkennen.

  Vergleich mal das hier
1
     {rise_time(&minuten);sekunden=0;}

  mit dem hier
1
    {
2
      rise_time( &minuten );
3
      sekunden = 0;
4
    }

  Im ersten Abschnitt musst du schon mal 10 Sekunden den Code
  zu studieren um den ';' zu bemerken und festzustellen, dass
  hier eigentlich 2 Anweisungen zu finden sind.

* Mach Einrückungen konsistent.
  Es ist nicht wirklich wichtig, wo du die { - } Klammern
  setzt. Es gibt da mehrere verbreitete Stile

  if( ... ) {
    Anweisung;
  }

  if( ... )
  {
    Anweisung;
  }

  if( ... )
    {
    Anweisung;
    }

  Es ist auch nicht wirklich wichtig, um wieviele Stellen du einrückst.
  Manche rücken um 2 Zeichen ein, manche um 4.

  Es ist aber wichtig, dass du den Stil konsequent durchziehst.
  Und nein: Kraut und Rüben ist kein anerkannter Stil :-)

von Robert P. (Firma: ---) (ausmilkel)


Lesenswert?

@  Karl heinz Buchegger (kbuchegg):

danke für die erste Korrektur bei der Unterfunktion in der 
lcdrotuines.c. Es funktioniert jetzt auch  mit der Optimierung. Schon 
schwer zu finden so ne sache. Vor allem wenn es an sich ohne der 
Optimierung funktioniert hat.

mfg
Robert

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.