Forum: Mikrocontroller und Digitale Elektronik AVR verrechent sich / Speicherproblem ?


von Studentle (Gast)


Lesenswert?

Guten Tag,

ich bin am verzweifeln. Und brauche euren Rat. Ich habe einen ATMega168 
mit einer RTC.

Ich möchte nun zu bestimmten Zeiten schalten. Hierfür habe ich mir eine 
funktion geschrieben, mit welcher 2 Zeiten verglichen werden können. Nur 
wenn ich das ganze auf einem PC Teste als Konsolenproramm tut alles wie 
gewünscht.

Auf dem AVR habe ich jedoch unsinnige Werte, und der Vergleich schlägt 
fehl. Ich habe den Code angehängt, und die Werte die ich im AVR erhalte 
als Kommentar geschrieben (dort Wandlung mit ultoa und Ausgabe auf LCD).

Was kann dieses Verhalten verursachen? RAM zu voll? Wie kann ich das 
Prüfen. Meine Toolchain AVRStudio 4 + MKII, demnächst AVR Dragon.

Für Ideen wäre ich sehr dankbar.

Grüßle
Studentle
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <inttypes.h>
4
5
typedef struct _time
6
{
7
  uint8_t sec;
8
  uint8_t min;
9
  uint8_t hour;
10
} time;
11
12
int rtc_time_compare(time* time1, time* time2)
13
{
14
  uint32_t iTime1, iTime2;
15
  iTime1 = time1->hour*3600 + time1->min*60 + time1->sec;
16
  iTime2 = time2->hour*3600 + time2->min*60 + time2->sec;
17
18
  printf("Time 1%i\n",iTime1);  // AVR: 4294937750
19
  printf("Time 2%i\n",iTime2); // AVR: 17264
20
21
  if(iTime1 > iTime2) return 1;
22
  else return 0;
23
}
24
  
25
int main(int argc, char *argv[])
26
{
27
    time switchOnTime, currentTime;
28
    
29
  currentTime.hour   = 9;
30
  currentTime.min    = 59;
31
  currentTime.sec    = 30;
32
    
33
    switchOnTime.hour   =  8;
34
  switchOnTime.min    =  0;
35
  switchOnTime.sec    =  0;
36
  
37
  printf("Compare : %i\n",rtc_time_compare(&currentTime,&switchOnTime));
38
  
39
  system("PAUSE");  
40
  return 0;
41
}

von Hans M. (Firma: mayer) (oe1smc) Benutzerseite


Lesenswert?

hallo

> iTime1 = time1->hour*3600 + time1->min*60 + time1->sec;

probiere es einmal mit dedizierten cast anweisungen. vielleicht gibt es 
unterschiede beim compiler.

gruss
hans

--

von sam (Gast)


Lesenswert?

ich glaube du musst vor der multiplikation typecasten.


 iTime1 = (uint32_t)(time1->hour)*3600 + (uint32_t)(time1->min)*60 + 
(uint32_t)(time1->sec);

von MitLeser (Gast)


Lesenswert?

Du musst die 8bit-Variablen auf 32bit casten.

von Matthias (Gast)


Lesenswert?

Studentle schrieb:
> uint8_t hour;
> ...
> iTime1 = time1->hour*3600 + ...
Da muß man nicht probieren. Der Compiler führt time1->hour*3600 als 
16-bit Multiplikation aus, da 3600 zunächst uint ist.

Mit iTime1 = time1->hour*3600UL + ... paßt das besser.

von Studentle (Gast)


Lesenswert?

Okey, stimmt das könnte es sein.

Ich kann den AVR erst wieder heute Abend flashen.

Dann bin ich mal gespannt...

von Wolfgang Horn (Gast)


Lesenswert?

Hi, Studentle,

in welcher Reihenfolge werden die Additionen iTime1 = time1->hour*3600 + 
time1->min*60 + time1->sec; durchgeführt?

Zum Debuggen mit JTAG/ICE ist es günstiger, diese Ziele aufzudröseln in 
drei separate Anweisungen.
Im Single-Step-Modus siehst Du dann, was in welcher Reihenfolge 
geschieht.

Ciao
Wolfgang Horn

von sam (Gast)


Lesenswert?

Ok ... muss man wohl nicht typecasten.

aber ich hab das Problem gefunden:
lokale Variablen und Zeiger.

der Compiler versucht tatsächlich die lokalen Variablen in Registern 
unterzubringen .... deswegen deklariere die alle Variablen die du 
brauchst global.
besonders fürs Debuggen ist das Sinnvoll, da so Variablen nicht dauernd 
aus dem Scope sind. und für den Speicherverbrauch ist das wohl das Selbe 
oder besser.

von sam (Gast)


Lesenswert?

hier ein anderer ansatz zum Zeitenvergleichen ...
ist nicht so Rechenlastig:
1
int rtc_time_compare(time* time1, time* time2)
2
{
3
  if(time1->hour > time2->hour) return 1;
4
  else if(time1->min > time2->min) return 1;
5
  else if(time1->min > time2->min) return 1;
6
    else return 0;  
7
}

von Studentle (Gast)


Lesenswert?

@ Wolfgang

Nun ja die Reihenfolge ist mir unbekannt. Ich habe nur den MKII kann 
also nicht onchip debuggen kann.

Allerdings könnte ich es mir noch im Simulator anschauen.

@ Sam
Für das Testen kann ich schon mal mit globalen Variablen arbeiten, doch 
für das finale Programm nicht gewünscht. Die Übersichtlichkeit leidet 
sonst zu sehr.

Grüßle Studentle

von Reinhard B. (brainstorm)


Lesenswert?

@sam:

Teste deinen Code mal z.B. mit 01:30:00 und 00:40:00. Ich denke, das 
klappt so nicht.

von Ralf (Gast)


Lesenswert?

Studentle schrieb:
> Für das Testen kann ich schon mal mit globalen Variablen arbeiten, doch
> für das finale Programm nicht gewünscht. Die Übersichtlichkeit leidet
> sonst zu sehr.

Lieber nicht global, aber ausnahmsweise die Variablen für den 
Simulator mal volatile deklarieren. (Dann liegen die auf jeden Fall im 
Speicher.)

von Studentle (Gast)


Lesenswert?

Hallo Sam,

du meinst wohl:
1
int rtc_time_compare(time* time1, time* time2)
2
{
3
  if(time1->hour > time2->hour) return 1;
4
  else if(time1->min > time2->min) return 1;
5
  else if(time1->sec > time2->sec) return 1;
6
    else return 0;  
7
}

genau diesen Ansatz hatte ich am Anfang auch.

Allerdings hat das ganze einen Haken, der Vergleich schlägt fehl:

Zeit 1 = 08:00:30
Zeit 2 = 23:00:00

8 > 23 ok
0 > 0 ok
30 > 0 ! -> return 1

von sam (Gast)


Lesenswert?

sam schrieb:
> hier ein anderer ansatz zum Zeitenvergleichen ...
> ist nicht so Rechenlastig:
> int rtc_time_compare(time* time1, time* time2)
> {
>   if(time1->hour > time2->hour) return 1;
>   else if(time1->min > time2->min) return 1;
>   else if(time1->min > time2->min) return 1;
>     else return 0;
> }

ich merk gerade, dass das nicht so funktioniert :)

so sollte es aber gehen :)

int rtc_time_compare(time* time1, time* time2)
{
  if(time1->hour < time2->hour) return 0;
  if(time1->hour > time2->hour) return 1;
  if(time1->min < time2->min) return 0;
  if(time1->min > time2->min) return 1;
  if(time1->sec < time2->sec) return 0;
  else return 1;
}

von Smarti (Gast)


Lesenswert?

Okey,

also die 3600UL haben das Problem gelöst ;)

THX

von Karl H. (kbuchegg)


Lesenswert?

sam schrieb:

> ich merk gerade, dass das nicht so funktioniert :)
>
> so sollte es aber gehen :)

Immer noch falsch.
Überleg dir einfach was das Ergebnis ist, wenn die beiden Zeiten gleich 
sind.

Der Schlüssel liegt darin, dass so ein allgemeiner Vergleich 3 
Ergebnisse haben muss:

* A ist größer als B
* A ist kleiner als B
* A ist gleich B

Oder aber man baut eine Funktion, die definitiv auf 'größer' vergleicht. 
Dann kann man das so lassen, wie du das hast. Nur ist es dann weise, 
wenn sich das auch im Funktionsnamen niederschlägt.

>
> int rtc_time_compare(time* time1, time* time2)
> {
>   if(time1->hour < time2->hour) return 0;
>   if(time1->hour > time2->hour) return 1;
>   if(time1->min < time2->min) return 0;
>   if(time1->min > time2->min) return 1;
>   if(time1->sec < time2->sec) return 0;
>   else return 1;
> }

nach einem return brauchst du kein else.

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.