Forum: Mikrocontroller und Digitale Elektronik ATmega32 Berechnungszeit ermitteln


von Rush .. (rush)


Lesenswert?

Hallo Community...

Ich wollte gerade eine simple Gegenüberstellung von einigen AVRs und 
deren Berechnungszeit für eine "einfache" Rechnung aufstellen.

Dafür habe ich einmal

ergebnis  = sqrt(465.983154/4135.964*sqrt(168*1256.942));

und einmal

ergebnis = 1.0+1.0

gerechnet.

Das ganze vorerst im Simulator. Was mich allerdings wundert: Egal was 
ich rechnen lasse, der Cyclecounter zeit immer 1 an und die StopWatch 
60ns.

Kennt zufällig jemand das Problem und kann mir weiterhelfen?
Danke schonmal im Voraus.

--
ATmega32@16Mhz
AVR-Studio 5.1

von Bastler (Gast)


Lesenswert?

Einfaches Hilfsmittel:

Pin setzen
Funktion / Berechnung aufrufen
Pin rücksetzen

so kann man einfach die Abarbeitungszeit einer Funktion betrachen.

von Rush .. (rush)


Lesenswert?

Das wäre doch nichts anderes als die Berechnung per Knopfdruck zu 
starten. Ich will aber die genau Zeit wissen.

von ucWriter (Gast)


Lesenswert?

Da ich aufgrund deiner Beschreibung nichts sagen kann, bleibt nur der 
Hinweise auf das optionale (Dis-)Assembler-Listing .

Mal eine Gegenfrage. Sind denn die AVR so unterschiedlich. Es kann doch 
nur einen Unterschied geben, wenn ein AVR-Typ beispielsweise einen 
Hardware-Multiplizierer besitzt und ein anderer nicht: ATTiny vs ATmega. 
(Die ganz alten lasse jetzt mal weg)

von holger (Gast)


Lesenswert?

>ergebnis  = sqrt(465.983154/4135.964*sqrt(168*1256.942));
>
>und einmal
>
>ergebnis = 1.0+1.0

>Das ganze vorerst im Simulator. Was mich allerdings wundert: Egal was
>ich rechnen lasse, der Cyclecounter zeit immer 1 an und die StopWatch
>60ns.

Was machst du mit ergebnis? Nichts, dann optimiert der Compiler
dir den ganzen Kram weg.

Versuch mal volatile float ergebnis.

von Thomas W. (thomas100)


Lesenswert?

Hallo Rush,

schau dir mal den Assemblercode an, den der Compiler erzeugt.
Im besten Fall macht der Atmega nämlich nur ne Zuweisung, und der 
Compiler rechnet das vorher schon aus.

aus wird
1
ergebnis = 1.0+1.0

wird dann
1
ergebnis = 2.0

und aus
1
ergebnis  = sqrt(465.983154/4135.964*sqrt(168*1256.942));

wird
1
ergebnis  = 154.2442536

Was in der Ausführungszeit genau das gleiche ist!

Ich bin mir jetzt nur nicht sicher, ob der Compiler so intelligent ist 
und kann die Funktion sqrt () rechnen. Aber das siehst du im 
Assemblercode.

Und wenn du ergebnis nicht weiter benutzt, dann kann es dir passieren, 
dass der Compiler eh alles wegoptimiert.

VG
Thomas

von Rush .. (rush)


Lesenswert?

Ich brauche diese Gegenüberstellung für die Vorlesung -.-
Ich weiss, eigentlich totaler Quatsch aber was solls...

Wollte das ganze auf diesen Typen laufen lassen:

AT90S2313
ATtiny2313
ATmega8 - mega128
ATmega644 und 644P

MSP430

Ich weiss nicht ob sich beispielsweise ein ATmega16 von dem 
Berechnungsalgorithmus von einem mega128 unterscheidet. Schätzungsweise 
nicht, aber muss es eben machen.

von ucWriter (Gast)


Lesenswert?

Zu den verschiedenen Controllern gibt von TI ein PDF (inkl. Quellcode) 
im Anhang zu diesem App-Note. Hilft Dir zwar jetzt nicht...

von Rush .. (rush)


Angehängte Dateien:

Lesenswert?

Das hier ist praktisch der Teil für die berechnung und ausgabe:
1
sei();
2
a = sqrt(465.983154/4135.964*sqrt(168*1256.942));
3
cli();
4
5
dtostrf(a, 5,8, chr_a);
6
set_cursor(0,1);
7
lcd_string(chr_a);
8
itoa(i, chr_i, 10);
9
set_cursor(0,2);
10
lcd_string(chr_i);
11
12
// chr_a = ergebnis string
13
// i = Anzahl der Timerinterrupts
14
// chr_i = Anzahl der Timerinterrupts als String

Assembler habe ich bis heute erfolgreich meiden können, von daher 
verstehe ich ihn nicht ;-)  Thomas kannst du vielleicht drüber schauen? 
Habe den Assemblercode mal drangehängt.

von spess53 (Gast)


Lesenswert?

Hi

Wenn in deinem Code vor sei(); ein timerinit(); steht, dann fehlt der 
Assemblercode für a = sqrt(465.983154/4135.964*sqrt(168*1256.942));

MfG Spess

von Rush .. (rush)


Lesenswert?

der dazugehörige c-code sieht so aus:
1
/*
2
 * ATmega32_Berechnungsdauer.c
3
 *
4
 * Created: 22.03.2012 16:59:56
5
 *  Author: Rush
6
 */ 
7
8
#include <avr/io.h>
9
#include <avr/interrupt.h>
10
#include "lcd-routines.h"
11
#include <math.h>
12
13
extern void lcd_data(unsigned char temp1);
14
extern void lcd_command(unsigned char temp1);
15
extern void lcd_enable(void);
16
extern void lcd_init(void);
17
extern void lcd_home(void);
18
extern void lcd_clear(void);
19
extern void set_cursor(uint8_t x, uint8_t y);
20
extern void lcd_string(char *data);
21
22
23
volatile unsigned int i = 0;
24
volatile unsigned char chr_i[10];
25
26
volatile double d = 123.43684;
27
volatile unsigned char chr_d[10];
28
29
30
31
ISR(TIMER0_COMP_vect)
32
{
33
  
34
  i++;
35
  
36
}
37
38
void timerinit(void)
39
{
40
  //TCCR0 = (1<<WGM01) | (1<<CS00);        //prescaler none; CTC-Mode
41
  //TCCR0 = (1<<WGM01) | (1<<CS01);        //prescaler 8; CTC-Mode
42
  //TCCR0 = (1<<WGM01) | (1<<CS01) | (1<<CS00);  //prescaler 64; CTC-Mode
43
  //TCCR0 = (1<<WGM01) | (1<<CS02);        //prescaler 256; CTC-Mode
44
  TCCR0 = (1<<WGM01) | (1<<CS02) | (1<<CS00);  //prescaler 1024; CTC-Mode
45
  
46
  OCR0 = 15;                  // ((1000000/8)/1000) = 125 für 1ms
47
  TIMSK = (1<<OCIE0);              // enable interrupts on compare match
48
49
  //Berechnung
50
  // 0,001sec / ((1/16000000)*Prescaler)
51
}
52
53
int main(void)
54
{
55
  timerinit();
56
  
57
  double a = 0;
58
  char chr_a[100];
59
  
60
    sei();
61
    a = sqrt(465.983154/4135.964*sqrt(168*1256.942));
62
    cli();
63
    dtostrf(a, 5,8, chr_a);
64
    set_cursor(0,1);
65
    lcd_string(chr_a);
66
    itoa(i, chr_i, 10);
67
    set_cursor(0,2);
68
    lcd_string(chr_i);
69
    
70
    
71
    while(1)
72
    {
73
  
74
    }
75
}

dann frage ich mich ehrlich gesagt wo meine Berechnung hin ist.
denn im Assenblercode folgt nach dem sei() direkt das cli().

Und was hat denn mein timerinit() mit dem Berechnungsteil zu tun? 
Eigentlich doch nichts.

von Peter II (Gast)


Lesenswert?

Rush ... schrieb:
> dann frage ich mich ehrlich gesagt wo meine Berechnung hin ist.

wegoptimiert, der compiler hat es einfach ausgerechnet.

von Rush .. (rush)


Lesenswert?

Hast recht. Habe jetzt die Optimierung ausgeschaltet. Jetzt kommt raus:

ergebnis = 1.0 + 1.0

Cyclen: 13
StopWatch: 0,81 us

bei
ergebnis = sqrt(465.983154/4135.964*sqrt(168*1256.942))
kommen wieder die selben werte drin.

und diesmal steht die berechnung im assemblercode auch drin.

Kann doch wirklich nicht sein dass beide Berechnungen die selben Zeiten 
bringen...

von Peter II (Gast)


Lesenswert?

Rush ... schrieb:
> Hast recht. Habe jetzt die Optimierung ausgeschaltet. Jetzt kommt raus:

jetzt hast du aber auch keine sinnvollen ergebnisse mehr. Denn kein 
sinnvolles Programm wird ohne optimierung eingesetzt.

du must also den compiler dazu bringen, mit optimierung zu rechnen.

von Rush .. (rush)


Lesenswert?

na das ergebnis stimmt schonmal.

du hast ja recht was die optimierung angeht. mir gehts einfach nur darum 
dass ich mit ein und denselben einstellungen das selbe programm auf 
mehreren controllern laufen lasse. einfach nur um die vergleichbarkeit 
zu schaffen. sicher, normalerweise gehört dort die optimierung mit rein.
naja, mit wenn ich meine ergebnisvariable als volatile deklariere dann 
wird sie auch nicht wegoptimiert.

von Peter II (Gast)


Lesenswert?

Rush ... schrieb:
> naja, mit wenn ich meine ergebnisvariable als volatile deklariere dann
> wird sie auch nicht wegoptimiert.
die variabel nicht, aber die berechnung kann dann genso weg optimiert 
werden. Es bleibt nur noch das ergebniss stehen.

von Rush .. (rush)


Lesenswert?

sorry, hab mich falsch ausgedrückt. also die berechnung steht komplett 
im assemblercode drin

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.