Forum: Mikrocontroller und Digitale Elektronik Wie Uhr (Zeitmultiplex) und Auslesen DS1820, effektiv Parallelisieren?


von Matze (Gast)


Lesenswert?

Hallo,

Möchte einen SD1820 Auslesen, welcher an einem ATxMega128A3 hängt,
gleichzeitig soll jedoch die Ausgabe der Zeit auf dem 7Seg-Display nicht 
flackern.

Die Temperatur soll alle 10Sec gesesen werden, das Aktualisieren der 
Anzeige wird jede ms und das weiterzählen der Uhr jede 1Sec ausgelöst.
Gesteuert wird alles durch den Timer 0 mit einer nun eingestellten 
System-Tick Zeit von 10us.
--> Der Prozessor kann je 320 Befehle zwischen jedem Tick ausführen.
Wenn die Entsprechende Zeit vorbei ist, wird von Timer je das Passende 
Event ausgelöst welches die 3 Tasks aktiviert.

Die 3 Aufgaben laufen also in Dauerschleife in Main, wird ein 
entsprechendes Event (globale Variable) ausgelöst so laufen sie durch.
Die Anzeige-Aktualisierung, sowie Uhr laufen komplett durch, da sie kurz 
sind, das auslesen des DS1820 dauert jedoch.
Also muss das Auslesen des DS1820 immer wieder unterbrochen werden.

Mein Problem ist nun dass mir meine Lösung des Auslesens des des DS1820 
zu kompliziert erscheint. Denn ich muss mir immer den Aktuellen zustand 
des Auslesevorgangs merken.
Eine art Sleep-Befehl z.b.(sleep(x*10us)) der den Prozessor von der Task 
DS1820 Auslesen abgibt würde es wohl stark vereinfachen.
Aber wie wird so etwas realisiert?



Dieser Code kann noch nicht Funktionieren, kommt mir aber jetzt schon zu 
kompliziert vor, grade das Lesen vom DS1820 wird ja furchtbar 
kompliziert.
1
int ReadTemp()
2
{
3
  static int zustand=0;
4
  if(evente&0x04)
5
  {
6
    if ((ResetDS1820()==2)&&(zustand==0))
7
    {
8
      zustand=1;
9
    }
10
    else if(zustand==1)
11
    {
12
      if(startconv()==2)
13
      {
14
        zustand=2;
15
      }
16
    }
17
    else if(zustand==2)
18
    {
19
      if(readout()==2)
20
      {
21
        readbit();    
22
      }
23
    }
24
  }  
25
  return 0;  
26
}
27
//    PORTF.DIRCLR=0xf4;  //1 = Rücksetzen --> Eingang
28
//    PORTF.OUTSET=0x00;  //1 = setzen     --> 1
29
30
int readbit()
31
{
32
  
33
}
34
35
int readout()  //oxbe
36
{
37
  static int zustand=0;
38
  switch (zustand)
39
  case 0:  sendo(); zustand++;
40
  break;
41
  case 1:  sendn(); zustand++;
42
  break;
43
  case 2:  sendo(); zustand++;
44
  break;
45
  case 3:  sendo(); zustand++;
46
  break;
47
  case 4:  sendo(); zustand++;
48
  break;
49
  case 5:  sendo(); zustand++;
50
  break;
51
  case 6:  sendo(); zustand++;
52
  break;
53
  case 7:  sendn(); zustand=0;
54
    return 2;
55
  break;
56
  return 0;
57
  
58
}
59
60
int startconv()
61
{
62
  static int sende=0;
63
  switch (sende)
64
  case 0:  sendn(); sende++;
65
    break;
66
  case 1:  sendn(); sende++;
67
    break;
68
  case 2:  sendn(); sende++;
69
    break;
70
  case 3:  sendn(); sende++;
71
    break;
72
  case 4:  sendn(); sende++;
73
    break;
74
  case 5:  sendo(); sende++;
75
    break;
76
  case 6:  sendn(); sende++;
77
    break;
78
  case 7:  sendn(); sende=0;
79
      return 2;
80
    break;
81
  return 0;
82
}
83
84
85
int sendn()
86
{
87
  PORTF.DIRSET=0x04;  //1 = setzen     --> Ausgang
88
  PORTF.OUTCLR=0x04;  //1 = Rücksetzen --> 0
89
  return 2;
90
}
91
92
int sendo()
93
{
94
  PORTF.DIRSET=0x04;  //1 = setzen     --> Ausgang
95
  PORTF.OUTSET=0x04;  //1 = Setzen     --> 1
96
  return 2;
97
}
98
99
100
int ResetDS1820()
101
{
102
  static int OK=0;
103
  PORTF.DIRSET=0x04;  //1 = setzen     --> Ausgang
104
  PORTF.OUTCLR=0x04;  //1 = Rücksetzen --> 0
105
  for(static int i=0;i<50;)
106
  {
107
    i++;
108
    return 0;
109
  }
110
  if(i<49 && i<55)
111
  {
112
    PORTF.OUTSET=0x04;  //1 = Setzen --> 0
113
    i++;
114
    return 0;
115
  }
116
  if(i==54)
117
  {
118
    PORTF.DIRCLR=0x04;  //1 = setzen --> Eingang
119
    if(!(PORTF.IN&0x04))//Wenn auf 0
120
    {          //OK --> Warten 240us
121
      OK=1;
122
    }
123
    else
124
    {
125
      OK=0;
126
      return 1;    //Ende mit fehler
127
    }
128
  }
129
  if(OK==1)
130
  {
131
    if(i>53 && i<78)
132
    {
133
      i++;
134
      return 0;
135
    }      
136
  }
137
  OK=0;
138
  i=0;
139
  return 2;        //Gutes Ende
140
}

von Falk B. (falk)


Lesenswert?

@ Matze (Gast)

>Möchte einen SD1820 Auslesen, welcher an einem ATxMega128A3 hängt,
>gleichzeitig soll jedoch die Ausgabe der Zeit auf dem 7Seg-Display nicht
>flackern.

Kein Problem. Flackern kommt meist davon, denn das LCD periodisch 
GELÖSCHT und neugeschrieben wird. Das macht man sinnvollerweise NICHT. 
Sondern man überschreibt nur das LCD. Dabei muss man ggf. auch 
Leerzeichen schreiben, um länger Zahlen und Texte vom letzten Mal zu 
löschen.

>Die Temperatur soll alle 10Sec gesesen werden, das Aktualisieren der
>Anzeige wird jede ms und das weiterzählen der Uhr jede 1Sec ausgelöst.

Nicht eher anders herum? Jede mus das LCD aktualisieren ist reichlich 
sinnlos.

>Gesteuert wird alles durch den Timer 0 mit einer nun eingestellten
>System-Tick Zeit von 10us.

Ein Interruot alle 10us? Das ist viel zu viel! 1ms reicht locker!

>Die 3 Aufgaben laufen also in Dauerschleife in Main, wird ein
>entsprechendes Event (globale Variable) ausgelöst so laufen sie durch.

Klingt schon mal brauchbar.

>Die Anzeige-Aktualisierung, sowie Uhr laufen komplett durch, da sie kurz
>sind, das auslesen des DS1820 dauert jedoch.
>Also muss das Auslesen des DS1820 immer wieder unterbrochen werden.

Nö. Du musst deine krampfhaften 10us erhöhen.

>Mein Problem ist nun dass mir meine Lösung des Auslesens des des DS1820
>zu kompliziert erscheint. Denn ich muss mir immer den Aktuellen zustand
>des Auslesevorgangs merken.

Dafür gibt es lokale, statische Variablen.

>Eine art Sleep-Befehl z.b.(sleep(x*10us)) der den Prozessor von der Task
>DS1820 Auslesen abgibt würde es wohl stark vereinfachen.
>Aber wie wird so etwas realisiert?

Siehe oben.

von Route_66 H. (route_66)


Lesenswert?

Falk Brunner schrieb:
> Kein Problem. Flackern kommt meist davon, denn das LCD periodisch
> GELÖSCHT und neugeschrieben wird. Das macht man sinnvollerweise NICHT.

Wer lesen kann: Er will 7-Segment-Multiplex, also LEDs ansteuern!

von Matze (Gast)


Lesenswert?

Falk Brunner schrieb:
> Kein Problem. Flackern kommt meist davon, denn das LCD periodisch
> GELÖSCHT und neugeschrieben wird. Das macht man sinnvollerweise NICHT.
> Sondern man überschreibt nur das LCD. Dabei muss man ggf. auch
> Leerzeichen schreiben, um länger Zahlen und Texte vom letzten Mal zu
> löschen.

Ne, ich habe ganz normale 7Segment Anzeigen in einem VFD, kein LCD, so 
dass ich die Passende Spalte (Gitter) auswählen muss, die Passenden 
Werte an die Anoden anlege. Da das Display 11 Stellen hat und eine 
Wiederholrate von 100Hz sich als sinvoll erwiesen hat, muss ich das 
Display jede ms umschalten.

Falk Brunner schrieb:
> Ein Interruot alle 10us? Das ist viel zu viel! 1ms reicht locker!

Jede ms reicht eben nicht, da der DS1820, mit einem Timing von etwa 15uS 
ausgelesen wird. Das Auslesen eines Datensatzes
1. wandlung starten,
2. warten
3. Auslesen
würde eben länger als 1ms dauern, deshalb soll es ja Quasi parallel 
ablaufen.
Damit die Anzeige nicht flackert.

Falk Brunner schrieb:
> Dafür gibt es lokale, statische Variablen.

Ja die nutze ich auch, aber kann ich mir nicht das merken hunterter 
zustände ersparen.
Wenn z.b. eine Wartezeit von 200us benötigt wird möchte ich sleep(20) 
schreiben, die CPU soll nun erstmal anderstwo weiterrechen und nach 
200us hier weitermachen.

Route 66 schrieb:
> Wer lesen kann: Er will 7-Segment-Multiplex, also LEDs ansteuern!

Erkannt ;)

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Matze schrieb:
> Gesteuert wird alles durch den Timer 0 mit einer nun eingestellten
> System-Tick Zeit von 10us.

Warum so übertrieben oft?

Deine Anzeige läuft mit 1ms, also reicht 1ms völlig aus.
Und nach der Anzeigeweiterschaltung hängst Du eine 1-Wire Aktion mit 
ran.
Damit stört diese nicht die Anzeige und umgekehrt.
Die 60µs bzw. 480µs machst Du mit einem weiteren Compareinterrupt 
danach.

Anbei mal ein 1-Wire mit Timerinterrupt auf nem 8051.

von Pandur S. (jetztnicht)


Lesenswert?

Was soll die Uhr auslesen ? Die kann man einmal bei powerup auslesen, 
dann kann der Controller selbst weitermachen. So spannend ist eine Uhr 
auch wieder nicht. Speziell wenn man das Datum nicht verwendet. Auf 60, 
60, 24 hochzaehlen...

von Falk B. (falk)


Lesenswert?

@ Matze (Gast)

>Ne, ich habe ganz normale 7Segment Anzeigen in einem VFD, kein LCD, so
>dass ich die Passende Spalte (Gitter) auswählen muss, die Passenden
>Werte an die Anoden anlege. Da das Display 11 Stellen hat und eine
>Wiederholrate von 100Hz sich als sinvoll erwiesen hat, muss ich das
>Display jede ms umschalten.

Also nutzt man einen 1ms Timer-Interrupt.

Du bist der 84762354826452te., der das tun will.

>Jede ms reicht eben nicht, da der DS1820, mit einem Timing von etwa 15uS
>ausgelesen wird. Das Auslesen eines Datensatzes
>1. wandlung starten,
>2. warten
>3. Auslesen
>würde eben länger als 1ms dauern, deshalb soll es ja Quasi parallel
>ablaufen.
>Damit die Anzeige nicht flackert.

Du hast einige Grundlagen vollkommen falsch verstanden.
Das Multiplexing packt man in einen Interrupt, viel passiert da ja 
nicht. Das Auslesen der DS1820 per One-Wire läuft als normale Funktion 
in der Hauptschleife. Und da ist es VOLLKOMMEN egal, wie lange das 
dauert, selbst 10ms wären OK.

Jaja, ich weiß, das Bittiming von One-Wire ist schon etwas flott, aber 
das ist kein Problem. Ein EINZELENES Bit kann man mit einer 
Interruptsperre bearbeiten, dazwischen hat man nahezu beliebig Zeit.

>Wenn z.b. eine Wartezeit von 200us benötigt wird möchte ich sleep(20)
>schreiben, die CPU soll nun erstmal anderstwo weiterrechen und nach
>200us hier weitermachen.

Wie das geht, siehe Statemachine.
Aber es ist hier der falsche Ansatz.

von chris (Gast)


Lesenswert?

1.ints sperren
2.preset send
3.skip Rom send
4.convert_T Dauer der Wandlung 750ms und hier Ints freigeben und nach 
Ablauf der 750ms sperren
5.preset send
6.skip Rom send
7.scratchpad lesen
8.preset send
9.ints freigeben

von Falk B. (falk)


Lesenswert?

@ chris (Gast)

>1.ints sperren
...
>9.ints freigeben

So sicher nicht.

von chris (Gast)


Lesenswert?

Falk Brunner schrieb:
> @ chris (Gast)
>
>>1.ints sperren
> ...
>>9.ints freigeben
>
> So sicher nicht.

ahaja was fehlt denn wenn mans so nicht machen sollte???

von Falk B. (falk)


Lesenswert?

@ chris (Gast)

>ahaja was fehlt denn wenn mans so nicht machen sollte???

Das Zeitgefühl!

Man muss nur für die Zeit EINES BITS die Interrutps sperren, das sind 
bei One Wire so um die 150us. Zwischen einzelnen Bits kann man sich alle 
Zeit der Welt lassen und auch Interrupts freischalten. Dann klappt das 
auch mit dem Multitasking.

von c-hater (Gast)


Lesenswert?

Falk Brunner schrieb:
> @ chris (Gast)
>
>>1.ints sperren
> ...
>>9.ints freigeben
>
> So sicher nicht.

Du hast Punkt 4. definitiv nicht gelesen. Da steht nämlich genau das 
drin, was du vermißt.

von Falk B. (falk)


Lesenswert?

@ c-hater (Gast)

>Du hast Punkt 4. definitiv nicht gelesen. Da steht nämlich genau das
>drin, was du vermißt.

Bla. Ersten ist das Geschreibsel alles andere als logisch und zweitens 
werden dort, semantisch sehr "sinnvoll", in einer Zeile die Interrupts 
freigegeben und gleich wieder gesperrt. Aber Hauptsache mal wieder dumm 
geschätzt, gell?

von Uwe Bonnes (Gast)


Lesenswert?

Wenn man die One-Wire Primitive mittels UART erzeugt, dann hat man keine 
Timingprobleme mehr:
http://www.maximintegrated.com/en/app-notes/index.mvp/id/214

von chris (Gast)


Lesenswert?

Falk Brunner schrieb:
> @ c-hater (Gast)
>
>>Du hast Punkt 4. definitiv nicht gelesen. Da steht nämlich genau das
>>drin, was du vermißt.
>
> Bla. Ersten ist das Geschreibsel alles andere als logisch und zweitens
> werden dort, semantisch sehr "sinnvoll", in einer Zeile die Interrupts
> freigegeben und gleich wieder gesperrt. Aber Hauptsache mal wieder dumm
> geschätzt, gell?

Geschreibsel sieht anders aus sonst wäre es überhaupt nicht zu verstehn.
Logisch ist es auf jeden Fall, da es stumpf aus dem Datenblatt kopiert 
wurde.
Die Ints werden nicht in einer Zeile sondern vor den 750ms freigegeben 
und nach ablauf wieder gesperrt.

Sicherlich kann man sich darüber streiten, auf welcher Ebene in der 
DS-Empfangs/Senderoutine die Ints bearbeitet werden pro 
Bit/Byte/Wandlung.

von Frank K. (fchk)


Lesenswert?

Wenn man genügend UARTs hat, kann man das Bittiming bei 1W durch einen 
solchen erledigen lassen. Dafür gibt es genügend Appnotes. Damit kann 
man die Interrupts eingeschaltet lassen, denn der UART lässt sich 
dadurch nicht stören.

fchk

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.