Forum: Mikrocontroller und Digitale Elektronik rollover save timer in c


von ch (Gast)


Lesenswert?

In Mikrocontrolleranwendungen gibt es oft das Problem, eine Schleife mit 
konstanter Frequenz durchlaufen zu lassen.

Hier wurde schonmal was in der Art
1
uint8_t stopTime;
2
uint8_t delayTime;
3
4
stopTimer=currentTime()+delayTime;
5
while(currentTime()<topTime);

vorgeschlagen. Bei diesem Verfahren gibt es aber Probleme mit dem 
Überlauf.
Hier werden verschiedenste Techniken vorgeschlagen:
http://stackoverflow.com/questions/61443/rollover-safe-timer-tick-comparisons

Wie löst Ihr das Problem auf einfach Weise?

von Stefan (Gast)


Lesenswert?

64bit Timer

von ch (Gast)


Lesenswert?

Damit verschiebst Du das Problem in die Zukunft.

von ROFL (Gast)


Lesenswert?

> Wie löst Ihr das Problem auf einfach Weise?

Wie wäre es die Überläufe mitzuzählen?

von Dr. Emmett Brown (Gast)


Lesenswert?

ch schrieb:
> Damit verschiebst Du das Problem in die Zukunft.

Mit einem µs-Timer in ca. 600000 Jahren.

von ch (Gast)


Lesenswert?

Nehmen wir an, Du hast nur einen 8Bit MC mit 16bit Timer ( Sind heute 
zum Teil noch gebräuchlich ).

von Stefan (Gast)


Lesenswert?

Dann bildet man neben dem Hard Timer noch ein Soft Timer.
Alternativ benutzt du für Wartezeiten einfach einen eigenen HardTimer 
und wartes drauf, dass er abgelaufen ist.

Also ich seh bei dem Thema nun kein großes Problem.

von Dr. Emmett Brown (Gast)


Lesenswert?

ch schrieb:
> Nehmen wir an, Du hast nur einen 8Bit MC mit 16bit Timer ( Sind heute
> zum Teil noch gebräuchlich ).
1
uint16_t delay;
2
uint16_t stop;
3
4
stop = TCNT + delay;
5
6
while(TCNT != stop);

von ROFL (Gast)


Lesenswert?

Dr. Emmett Brown schrieb:
> ch schrieb:
>> Damit verschiebst Du das Problem in die Zukunft.
>
> Mit einem µs-Timer in ca. 600000 Jahren.

Er kann zwischendurch den Timer oder die Überläufe zurücksetzen. Das 
hält dann ca. eine Ewigkeit.

von ch (Gast)


Lesenswert?

Dr. Emmett Brown (Gast) schrieb
>
1
>uint16_t delay;
2
>uint16_t stop;
3
>
4
>stop = TCNT + delay;
5
>
6
>while(TCNT != stop);
7
>


Das würde funktionieren, wenn sichergestellt ist, dass der Timer nicht 
"full speed" als mit Prozessortakt, läuft. In meinem Anwendungsfall ist 
das aber gegeben.

von danvet (Gast)


Lesenswert?

also bei UINT Werten kann man doch einfach subtrahieren, das stimmt auch 
bei einem Überlauf:
1
UINT8 startTime;
2
UINT8 delay = 20;
3
4
startTime = currentTime();
5
6
while( (currentTime() - startTime) < delay);

Oder habe ich das bisher immer falsch gemacht?

von Karl H. (kbuchegg)


Lesenswert?

danvet schrieb:
> also bei UINT Werten kann man doch einfach subtrahieren, das stimmt auch
> bei einem Überlauf:
>
>
1
> UINT8 startTime;
2
> UINT8 delay = 20;
3
> 
4
> startTime = currentTime();
5
> 
6
> while( (currentTime() - startTime) < delay);
7
>
>
> Oder habe ich das bisher immer falsch gemacht?

Nein, ist richtig.
entscheidend ist das unsigned.

von Dr. Emmett Brown (Gast)


Lesenswert?

ch schrieb:
> Das würde funktionieren, wenn sichergestellt ist, dass der Timer nicht
> "full speed" als mit Prozessortakt, läuft. In meinem Anwendungsfall ist
> das aber gegeben.

Meine Güte, ist denn das so schwierig?

In der Overflow-ISR deines mit 3,5GHz getakteten Timers:
1
static uint8_t ms_timer;
2
ms_timer++;
3
if(ms_timer == (3500000000UL / 65536 / 1000))
4
{
5
  millis++;
6
  ms_timer = 0;

millis ist eine globale Variable und mit den Rundungsfehlern mußt du 
leben.

von danvet (Gast)


Lesenswert?

UINT ist doch unsigned ???

von danvet (Gast)


Lesenswert?

sorry hab mich verlesen

von Karl H. (kbuchegg)


Lesenswert?

danvet schrieb:
> UINT ist doch unsigned ???

ja. Sag ich doch, dass es richtig ist.
Es gibt aber auch Zeitgenossen, die mitlesen und nicht erkennen, wo der 
springende Punkt liegt. Viele sehen in Datentypen nicht mehr als eine 
Art 'schmückendes Beiwerk'.

: Bearbeitet durch User
von Georg (Gast)


Lesenswert?

Hallo,

die meisten in Prozessoren verwendeten Timer können das ohne weiteres 
und ohne langes Nachdenken des Programmierers: vom eingestellten 
Startwert wird heruntergezählt auf 0, ein IRQ ausgelöst und der 
Startwert wieder geladen. Die IRQs folgen also äquidistant aufeinander 
ohne jeden Programmeingriff.

Das Problem existiert also eigentlich garnicht.

Georg

von danvet (Gast)


Lesenswert?

Georg schrieb:
> Hallo,
>
> die meisten in Prozessoren verwendeten Timer können das ohne weiteres
> und ohne langes Nachdenken des Programmierers: vom eingestellten
> Startwert wird heruntergezählt auf 0, ein IRQ ausgelöst und der
> Startwert wieder geladen. Die IRQs folgen also äquidistant aufeinander
> ohne jeden Programmeingriff.
>
> Das Problem existiert also eigentlich garnicht.
>
> Georg

Jepp, was wiederum heißt, dass "while(delay);" schlechter 
Programmierstil ist.
Es sei denn, man bezweckt was ganz spezielles damit.

von Karl H. (kbuchegg)


Lesenswert?

ch schrieb:
> In Mikrocontrolleranwendungen gibt es oft das Problem, eine Schleife mit
> konstanter Frequenz durchlaufen zu lassen.

Die bessere Variante ist es allerdings, nicht solange Däumchen zu 
drehen, bis eine bestimmte Zeit (voraussichtlich) um ist. Wobei es auch 
Ausnahmen gibt, wenn die Zeiten sehr kurz sind und nicht mit 
UNterbrechungen zu rechnen ist.

Die weit aus bessere Variante ist es, den Timer so aufzusetzen und so zu 
verwenden, dass er in den gewünschten regelmässige Zeitabständen das 
Startsignal für die nächste Abarbeitung von Funktionalitäten gibt.

von Mark B. (markbrandis)


Lesenswert?

Georg schrieb:
> die meisten in Prozessoren verwendeten Timer können das ohne weiteres
> und ohne langes Nachdenken des Programmierers: vom eingestellten
> Startwert wird heruntergezählt auf 0, ein IRQ ausgelöst und der
> Startwert wieder geladen. Die IRQs folgen also äquidistant aufeinander
> ohne jeden Programmeingriff.
>
> Das Problem existiert also eigentlich garnicht.

Genau so ist es. Man muss in der Software keine Probleme lösen, die man 
schon von der Hardware erschlagen bekommt.

von Dr. Emmett Brown (Gast)


Lesenswert?

danvet schrieb:
> Jepp, was wiederum heißt, dass "while(delay);" schlechter
> Programmierstil ist.
> Es sei denn, man bezweckt was ganz spezielles damit.

Meistens macht das nur Probleme.

1
#define SYSTICK 1000
2
3
static unsigned char intervaldo_ = 0;
4
5
#define INTERVAL(intervalvalue_){\
6
static unsigned int intervalct_ = 0;\
7
if(!intervalct_) intervalct_ = (unsigned int)((long)intervalvalue_ *SYSTICK / 1000);\
8
intervalct_--;\
9
intervaldo_ = !intervalct_;\
10
}\
11
if(intervaldo_)
12
13
14
int main(void
15
{
16
 while(1)
17
 {
18
  if(millisekundentakt)
19
  {
20
   INTERVAL(1000)
21
   {
22
     //Tu was alle 1000ms
23
   }
24
25
   INTERVAL(143)
26
   {
27
     //Tu was alle 143ms
28
   }
29
30
   INTERVAL(5000)
31
   {
32
     //Tu was alle 5000ms
33
   }
34
35
   INTERVAL(10)
36
   {
37
     //Tu was alle 10ms
38
   }
39
  }
40
 }
41
}

von ch (Gast)


Lesenswert?

1
> UINT8 startTime;
2
> UINT8 delay = 20;
3
> 
4
> startTime = currentTime();
5
> 
6
> while( (currentTime() - startTime) < delay);
7
>

Das hört sich ziemlich gut an.
Hier mal der Vorschlag umgesetzt auf einem Arduino Due. Es läuft ca. 
eine Sekunde und bleibt dann hängen.
Sieht jemand den Fehler?
1
void setup() 
2
{
3
  pinMode(13, OUTPUT);
4
}
5
6
void toogle()
7
{
8
  static uint8_t flag;
9
  flag ^= 1;
10
  digitalWrite(13, flag);
11
}
12
13
uint8_t systemTime()
14
{
15
  return millis();
16
}
17
18
uint8_t Start;
19
uint8_t Delay;
20
21
void setDelayTimer(uint8_t t)
22
{
23
  Start=systemTime();
24
  Delay=t;
25
}
26
27
void wait()
28
{
29
  while( (systemTime()-Start ) < Delay );
30
}

void loop()
{
  toogle();
  //delay(5);
  setDelayTimer(5);
  wait();

}

von Karl H. (kbuchegg)


Lesenswert?

ch schrieb:

> uint8_t Start;
> uint8_t Delay;

Vergessen.

uint8_t ist keine gute Idee.

Der springende Punkt ist das unsigned. Machst du aber Rechnungen mit 
uint8_t so wird das int (und zwar signed int) gerechnet. Genau das 
kannst du aber nicht brauchen! Du willst und musst die Berechnung 
unsigned halten.

Wozu das ganze? millis liefert dir einen unsigned long. Ob du den jetzt 
wie ein wilder runter castest oder gleich alles in unsigned long machst, 
schenkt sich nichts.

von ch (Gast)


Lesenswert?

>Der springende Punkt ist das unsigned. Machst du aber Rechnungen mit
>uint8_t so wird das int (und zwar signed int) gerechnet

Danke für die Antwort. Bist Du Dir aber sicher?

int8_t   Signed
uint8_t Unsigned

https://en.wikibooks.org/wiki/C_Programming/C_Reference/stdint.h

von irgendeintyp (Gast)


Lesenswert?

ch schrieb:
> uint8_t systemTime()
> {
>   return millis();
> }

laut Arduino.h:
>unsigned long millis(void);

unsigned long vs uint8_t ;) irgendwann ist der uint8_t voll...

von Sebastian V. (sebi_s)


Lesenswert?

ch schrieb:
>>Der springende Punkt ist das unsigned. Machst du aber Rechnungen
> mit
>>uint8_t so wird das int (und zwar signed int) gerechnet
>
> Danke für die Antwort. Bist Du Dir aber sicher?
>
> int8_t   Signed
> uint8_t Unsigned
>
> https://en.wikibooks.org/wiki/C_Programming/C_Refe...

Das Problem ist nicht der Typ sondern die Berechnung. Siehe hier: 
http://en.cppreference.com/w/cpp/language/implicit_cast

Entsprechender Auszug:
unsigned char or unsigned short can be converted to int if it can hold 
its entire value range, and unsigned int otherwise.

von B. S. (bestucki)


Lesenswert?

ch schrieb:
> Danke für die Antwort. Bist Du Dir aber sicher?

Ich bin mir sicher, dass sich Karl Heinz sicher ist. Die Datentypen 
selbst sind zwar unsigned, die Berechnung wird in diesem Fall jedoch als 
signed int durchgeführt. Kompiliere ich folgenden Code,
1
uint8_t Value =3;
2
Value = 2 * Value;
so erhalte ich eine Warnung:
1
warning: conversion to ‘uint8_t {aka unsigned char}’ from ‘int’ may alter its value [-Wconversion]|

Das ganze nennt sich integral promotion.

Konkret geht es um diese Zeile:
1
while( (systemTime()-Start ) < Delay );
Alle Operanden sind ein uint8_t und werden somit zu einem signed int 
gecastet. Dementsprechend wird die Berechnung als signed durchgeführt.

von Karl H. (kbuchegg)


Lesenswert?

be s. schrieb:

> Alle Operanden sind ein uint8_t und werden somit zu einem signed int
> gecastet. Dementsprechend wird die Berechnung als signed durchgeführt.


Und damit natürlich auch der Vergleich.

> Bist Du Dir aber sicher?

Ja, ich bin mir absolut sicher. So sind nun mal die C Regeln.
In einer Operation werden alle beteiligten Operanden immer auf den 
höchsten Types eines der beiden Operanden hochgehoben, mindestens aber 
int.

von ch (Gast)


Lesenswert?

> UINT8 startTime;
> UINT8 delay = 20;
>
> startTime = currentTime();
>
> while( (currentTime() - startTime) < delay);
>

Der oben gepostete Code war mit UINT8.
Mein Code ist mit uint8_t.
Seht Ihr da einen Unterschied?

von Mark B. (markbrandis)


Lesenswert?

ch schrieb:
> Der oben gepostete Code war mit UINT8.
> Mein Code ist mit uint8_t.
> Seht Ihr da einen Unterschied?

Nein. Sollte an und für sich beides auf unsigned char hinauslaufen.

Aber der Ansatz an sich ist zweifelhaft. Von daher solltest Du lieber 
das konkrete Problem beschreiben, welches du eigentlich lösen willst.

: Bearbeitet durch User
von ch (Gast)


Lesenswert?

be stucki (bestucki) schrieb
>Konkret geht es um diese Zeile:
>
>while( (systemTime()-Start ) < Delay );
>
>Alle Operanden sind ein uint8_t und werden somit zu einem signed int
>gecastet. Dementsprechend wird die Berechnung als signed durchgeführt.

Hmm, ich hätte gedacht, dass die Berechnung folgendermaßen durchgeführt 
wird:

(uint8_t)((uint8_t)systemTime()-(uint8_t)Start ) < (uint8_t)Delay

Dazu folgender Test:
1
void setup()
2
{
3
  Serial.begin(115200);
4
  
5
  uint8_t a;
6
  uint8_t b;
7
 
8
  a = 250;
9
  b = 255;
10
  Serial.print("a= ");Serial.println(a);
11
  Serial.print("b= ");Serial.println(b);
12
  Serial.println("Is (b-a < 6) true or false?");
13
  
14
  if (b-a < 6)Serial.println("  it is true");
15
  Serial.println("");
16
  Serial.println("");
17
  
18
  a = 255;
19
  b = 4;
20
  Serial.print("a= ");Serial.println(a);
21
  Serial.print("b= ");Serial.println(b);
22
  Serial.println("Is (b-a < 6) true or false?");
23
  
24
  if (b-a < 6)Serial.println("  it is true");
25
  Serial.println("");
26
}
27
28
void loop()
29
{
30
31
}

Das Ergebnis ist


a= 250
b= 255
Is (b-a < 6) true or false?
  it is true


a= 255
b= 4
Is (b-a < 6) true or false?
  it is true

von Ulrich F. (Gast)


Lesenswert?

Arduino?

Dann sind die Zeiten alle unsigned long zu definieren. Und auch so damit 
zu rechnen. uint8_t macht da wenig Sinn.



Hier mal ein Vorschlag in "Arduino", etwas Ressourcen verplempernd, aber 
das spielt ja hier erstmal keine Rolex.
1
class TimerTick
2
{
3
  private:
4
  unsigned long lastHit;
5
  unsigned long interval;
6
  
7
  public:
8
  TimerTick(unsigned long interval):interval(interval){}
9
  
10
  bool abgelaufen()
11
  {
12
    if(millis() - lastHit >= interval)
13
    {
14
        lastHit += interval; // mit aufholjagt
15
        return true;  
16
    }
17
    return false;
18
  }  
19
};
20
21
const byte led = 13;
22
TimerTick timer(500); // alle 0,5 sec
23
24
25
void tuwas()
26
{
27
    digitalWrite(led,!digitalRead(led)); // toggle LED
28
}
29
30
void setup() 
31
{
32
    pinMode(led,OUTPUT);
33
}
34
35
void loop() 
36
{
37
  if(timer.abgelaufen()) tuwas();   
38
}

von B. S. (bestucki)


Lesenswert?

ch schrieb:
> a= 255
> b= 4
> Is (b-a < 6) true or false?
>   it is true

Genu hier liegt dein Denkfehler:
x - 255 mit x[0...255] ergibt immer eine negative Zahl oder null. Somit 
ist deine Bedingung immer wahr. Daher musst du dafür sorgen, dass die 
Subtraktion als unsigned Operation durchgeführt wird.

: Bearbeitet durch User
von Karl H. (kbuchegg)


Lesenswert?

ch schrieb:

> Hmm, ich hätte gedacht, dass die Berechnung folgendermaßen durchgeführt
> wird:

Nein.
Genau deswegen gibt es Literatur, in der die Regeln genau und 
ausführlich vermittelt werden.

Kurz gesagt: Nein, C funktioniert nicht so.

> a= 255
> b= 4
> Is (b-a < 6) true or false?
>   it is true

4 - 255 ergibt -251. Und das ist selbstverständlich kleiner 6.

Und genau das willst du nicht haben. Du willst nicht haben, dass das 
Ergebnis ein Vorzeichen besitzt. Dazu muss aber die ganze Berechnung und 
der ganze Vergleich unsigned durchgeführt werden.

Das ist prinzipiell kein Problem, solange man berücksichtigt, dass in C 
niemals in einem kleineren Datentyp als int gerechnet wird. In diesem 
Zusammenhang spielt es daher keine Rolle, dass a und b als unsigned char 
definiert sind. Denn beide werden zuerst auf den Datentyp int 
hochgehoben, ehe die Berechnung überhaupt startet. Wichtig: int(!) - 
nicht unsigned int! Denn die Regeln sagen auch, dass in so einem Fall 
der erste Datentyp genomen wird, der alle Werte aufnehmen kann. Und das 
ist nun mal ein int. Ein unsigned char hat einen Wertebereich von 0 bis 
255 - passt perfekt in einen int hinein, womit sich über die Hintertür 
wieder ein Vorzeichen einschmuggelt, welches selbstverständlich dann in 
weiterer Folge berücksichtigt und ausgewertet wird.

: Bearbeitet durch User
von ch (Gast)


Lesenswert?

Stucki, Du hast recht.
Das oben von  danvet gepostete Beispiel
1
> UINT8 startTime;
2
> UINT8 delay = 20;
3
> 
4
> startTime = currentTime();
5
> 
6
> while( (currentTime() - startTime) < delay);
7
>
scheint dann zu funktionieren, wenn man in die Zeile mit dem while einen 
typecast einfügt:

while( (UINT8)(currentTime() - startTime) < delay);

von Karl H. (kbuchegg)


Lesenswert?

ch schrieb:

> scheint dann zu funktionieren, wenn man in die Zeile mit dem while einen
> typecast einfügt:
>
> while( (UINT8)(currentTime() - startTime) < delay);

Und jetzt lehnst du dich zurück, denkst noch mal über alles nach, was 
dir heute erzählt wurde und lässt dir durch den Kopf gehen, WARUM in 
diesem Fall das richtige passiert.

Es ist wichtig das du verstehst, was da warum passiert.

: Bearbeitet durch User
von ch (Gast)


Lesenswert?

>Und jetzt lehnst du dich zurück, denkst noch mal über alles nach, was
>dir heute erzählt wurde und lässt dir durch den Kopf gehen, WARUM in
>diesem Fall das richtige passiert

Ich weis, warum das richtige passiert. Nur leider habe ich eine Weile 
gebraucht, den Fehler zu finden. Hättest Du weiter oben nicht Folgendes 
geschrieben

 Karl Heinz (kbuchegg) (Moderator) schrieb
>>danvet schrieb:
>> UINT ist doch unsigned ???

>ja. Sag ich doch, dass es richtig ist.
>Es gibt aber auch Zeitgenossen, die mitlesen und nicht erkennen, wo der
>springende Punkt liegt. Viele sehen in Datentypen nicht mehr als eine
>Art 'schmückendes Beiwerk'.

und erwähnt dass in Beispiel von davnet der typecast fehlt, wäre auch 
alles etwas schneller gegangen.

von W.S. (Gast)


Lesenswert?

Karl H. schrieb:
> while( (currentTime() - startTime) < delay);

Ähemm.. sind ja alles vorzeichenlose Bytes, also beispielsweise:

currentTime = 254;
starttime = 250;
delay = 150;

Hab ich heut schon zuviel Rotwein intus, oder..?


Also wenn es bei mir auf kleinere, aber präzise Delays ankommt, dann 
reserviere ich dafür einen Timer, den ich geeignet programmiere und 
starte.

Wenn es lediglich größere Wartezeiten sind, dann setze ich einen 
"delayed_Event", der vom Timertick des Systems verwaltet wird. Dieser 
zählt die Millisekunden per long, also 32 Bit - UND!! er zieht am 
Tagesende einen ganzen Tag ab (sowohl bei der Uhrzeit als auch bei den 
verwalteten delayed Events). Da klappt immer, ist sauber und einfach zu 
benutzen.

W.S.

von 900ss (900ss)


Lesenswert?

W.S. schrieb:
> Hab ich heut schon zuviel Rotwein intus, oder..?

Um 18:34 Uhr schon? ;-)

von Karl H. (kbuchegg)


Lesenswert?

ch schrieb:

> und erwähnt dass in Beispiel von davnet der typecast fehlt, wäre auch
> alles etwas schneller gegangen.

Da hast du recht. Allerdings muss ich gestehen, dass ich da auch zu spät 
geschaltet habe.

von Karl H. (kbuchegg)


Lesenswert?

W.S. schrieb:
> Karl H. schrieb:
>> while( (currentTime() - startTime) < delay);
>
> Ähemm.. sind ja alles vorzeichenlose Bytes, also beispielsweise:
>
> currentTime = 254;
> starttime = 250;
> delay = 150;
>
> Hab ich heut schon zuviel Rotwein intus, oder..?

Mag sein. Aber bei einem unsigned char soll es auch schon mal 
vorgekommen sein, dass ein Überlauf zwischendurch passiert und 
currentTime dann effektiv kleiner als startTime ist.

Was an und für sich keine Rolle spielt, solange die Arithmetik unsigned 
durchgeführt wird. Was sie hier allerdings nicht wird, da da noch die 
"es wird nicht kleiner als int gerechnet" Regel mit ins Spiel kommt.
Sobald die uint8_t auf mindestens uint16_t geändert werden, ist dieses 
Problem keines mehr und das ganze läuft auch ohne unsigned cast des 
Subtraktionsergebnisses völlig richtig ab.

: Bearbeitet durch User
von Bernd K. (prof7bit)


Lesenswert?

ch schrieb:
>> [64 bit]
> Damit verschiebst Du das Problem in die Zukunft.

500 Millionen Jahre bis die ersten Reklamationen eintrudeln, bis dahin 
sollte Version 2 und ein kostenloses Update auf nen 128 bit Zähler 
ausgerollt sein.

von ch (Gast)


Lesenswert?

Karl Heinz (kbuchegg) (Moderator) schrieb:
>Sobald die uint8_t auf mindestens uint16_t geändert werden, ist dieses
>Problem keines mehr und das ganze läuft auch ohne unsigned cast des
>Subtraktionsergebnisses völlig richtig ab.

Naja, der Arduino Due ist ein ARM-Controller mit 32 bit, da führt das 
weglassen des typcast zur Fehlfunktion.
Damit die Routine portabel auf verschiedenen Architekturen funktioniert, 
sollter der typecast auf jeden Fall drinn bleiben.
Meine Routinen laufen auf mindestens 5 verschiedenen 
Controller-Architekturen.

von ch (Gast)


Lesenswert?

Und am Schluss der korrekte Code, damit man ein Resume des Threads hat:
1
uint8_t startTime;
2
uint8_t delay = 20;
3
 
4
startTime = currentTime();
5
 
6
while( (uint8_t) (currentTime() - startTime) < delay);

von Stefan (Gast)


Lesenswert?

Und dann wollen wir ein Delay, dass mehr als 255 irgendwas beträgt und 
schwupp ist sie auch nicht korrekt. Warum du unbedingt einen uint8_t 
verwendest auf einem 32bitter ist mir schleierhaft.

von ch (Gast)


Lesenswert?

Weil es ein Beispiel zum testen ist.
Du kannst auch uint16_t auf einem Atmega verwenden.

von chris_ (Gast)


Lesenswert?


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.