digitalWrite(OE,LOW);//Disable Outputs to prevent flicker
4
5
for(unsignedlongi=0;i<32;i++){
6
digitalWrite(DATA,bitRead(firstValue,i));//Select postion to Read and set state
7
digitalWrite(CLK,HIGH);// Set Clock Pin High,
8
digitalWrite(CLK,LOW);// Set Clock Pin Low
9
}
10
for(unsignedlongi=0;i<32;i++){
11
digitalWrite(DATA,bitRead(secondValue,i));//Select postion to Read and set state
12
digitalWrite(CLK,HIGH);// Set Clock Pin High,
13
digitalWrite(CLK,LOW);// Set Clock Pin Low
14
}
15
digitalWrite(OE,HIGH);//Enable Outputs
16
17
}
Es werden jeweils zwei 32-bit Variablen übergeben. In meinem Versuch
genau zweimal der selbe inhalt.
Auf der Suche nach der Ursache eines anderen Problems (Flackern) stiess
ich auf folgendes Phänomen
Beim shiften der 2ten 32-bit Variable, scheint die Clock schneller zu
laufen,Siehe Screenshot, in der mitte ist genau der Wechsel von Variable
1 auf 2 zu sehen.
Das es mit der ungenauikeit des Quarz zutun hat bezweifle ich, weil die
einzelnen HIGH/LOW jeweils genau gleich sind. Und das bei x Durchläufen
so war.
Auch der Code ist ja exakt der selbe.
Hat jemand irgendeine Idee warum/was da passiert?
Johnny S. schrieb:> Auch der Code ist ja exakt der selbe.
Hast du dir den erzeugten Assembler Code angesehen oder wie meinst du
das?
Der selbe Code kann es schon nicht sein, weil die beiden Argumente
unterschiedlich liegen.
Mach die Ausgabe mal über eine Zwischenvariable, also
1
unsigned long y = firstValue;
2
for ( unsigned long i=0; i<32; i++){
3
digitalWrite(DATA, bitRead(y,i)); //Select postion to Read and set state
4
...
5
y = secondValue;
6
for ( unsigned long i=0; i<32; i++){
7
digitalWrite(DATA, bitRead(y,i)); //Select postion to Read and set state
p.s. Man könnte sich auch fragen, warum die Laufvariable mit einem
Wertebereich von 0..31 unbedingt 32 Bit haben muss. Da würden es auch
fünf tun oder was dem Prozessor so am bequemsten in ein Register passt.
Willi schrieb:> Tausch mal in den bitRead() Anweisungen first und secondValue,> vielleicht kommst du der Sache dann näher.>> MfG Willi
Passiert nix...
Tom E. schrieb:> Johnny S. schrieb:>> Auch der Code ist ja exakt der selbe.>> Hast du dir den erzeugten Assembler Code angesehen oder wie meinst du> das?> Der selbe Code kann es schon nicht sein, weil die beiden Argumente> unterschiedlich liegen.>> Mach die Ausgabe mal über eine Zwischenvariable, also
1
unsigned
2
> long y = firstValue;
3
> for ( unsigned long i=0; i<32; i++){
4
> digitalWrite(DATA, bitRead(y,i)); //Select postion to Read and set
5
> state
6
> ...
7
> y = secondValue;
8
> for ( unsigned long i=0; i<32; i++){
9
> digitalWrite(DATA, bitRead(y,i)); //Select postion to Read and set
10
> state
>> p.s. Man könnte sich auch fragen, warum die Laufvariable mit einem> Wertebereich von 0..31 unbedingt 32 Bit haben muss. Da würden es auch> fünf tun oder was dem Prozessor so am bequemsten in ein Register passt.
Ok werd ich probieren, seh aber nicht warum das etwas bringen sollte,
und [long y] zerschneided mir doch den code? wenn dann [unsigned long]
oder.
Wie meinst du mit Laufvariable? es muss doch 32bit sein, weil 32bits
geshifted werden sollen.
Johnny S. schrieb:> Wie meinst du mit Laufvariable? es muss doch 32bit sein, weil 32bits> geshifted werden sollen.
Da sie nie größer als 32 werden kann, ist es völlig überflüssig sie 32
Bit breit zu machen.
@Johny
Letztlich hast du da eine in software gelöste SPI.
Mit dem Arduino Framework bist du ja nicht direkt auf der Hardware,
sondern arbeitest auf einer Art "Abstraction Layer" der dir dann sowas
wie digitalWrite() anbietet.
In dem Ardu-Framwork laufen im Hintergrund permanent irgendwelche Dinge
ab, die man nicht unmittelbar sieht. Z.B. gibt es z.B. einen Systick
basierend auf einem der Hardwaretimer, der dir mittels Interrupt immer
mal dazwischen funkt und z.B. deine digitalWrite() oder andere
unterbricht. Das führt dann zu "jitternden" Ausführungszeiten.
Letztlich müsste man um sicher zu gehen auch bei shiftOut() in den
Quellcode der Bibliothek schauen.
Der springende Punkt sind solche Formulierungen
in den Arduino References (https://www.arduino.cc/en/Reference/ShiftOut)
:
"This is a software implementation; see also the SPI library, which
provides a hardware implementation that is faster but works only on
specific pins. "
>Wie meinst du mit Laufvariable? es muss doch 32bit sein, weil 32bits>geshifted werden sollen.
Hier verwechselst du Wertebereich und Speicherbreite.
Gemünzt auf unser 10er Zahlensystem würde deine Überlegung bedeuten,
dass wenn du z.B. eine 1000 darstellen willst, eine Zahl mit 1000
Ziffern bräuchtest.
Frage google mal nach so etwas wie "Zahlendarstellung im Binärsystem",
da kommt sicher was.
Jasson J. schrieb:> @Johny>> Letztlich hast du da eine in software gelöste SPI.> Mit dem Arduino Framework bist du ja nicht direkt auf der Hardware,> sondern arbeitest auf einer Art "Abstraction Layer" der dir dann sowas> wie digitalWrite() anbietet.> In dem Ardu-Framwork laufen im Hintergrund permanent irgendwelche Dinge> ab, die man nicht unmittelbar sieht. Z.B. gibt es z.B. einen Systick> basierend auf einem der Hardwaretimer, der dir mittels Interrupt immer> mal dazwischen funkt und z.B. deine digitalWrite() oder andere> unterbricht. Das führt dann zu "jitternden" Ausführungszeiten.>> Letztlich müsste man um sicher zu gehen auch bei shiftOut() in den> Quellcode der Bibliothek schauen.> Der springende Punkt sind solche Formulierungen> in den Arduino References (https://www.arduino.cc/en/Reference/ShiftOut)> :> "This is a software implementation; see also the SPI library, which> provides a hardware implementation that is faster but works only on> specific pins. "
Ich benutze ja nicht die ShiftOut libaray, weil diese nur 8 bit
unterstützt, es ist ja mit digitalWrite gelöst.
Die SPI kann ich ja nicht nutzen,weil die Pins belegt sind...
Johnny S. schrieb:> Ich benutze ja nicht die ShiftOut libaray, weil diese nur 8 bit> unterstützt, es ist ja mit digitalWrite gelöst.
Dann ruf sie halt 4 mal auf mit dem jeweiligen Byte deiner 32bit
Variable.
Du siehst doch das digitalWrite unglaublich lange braucht um mal so ein
Portbit zu setzen. Rechne das mal in Prozesssorzyklen aus.
Der fährt erst drei mal mit dem Fahrad um den Block bis der Pin gesetzt
wird.
Großes Rätsel was der im Hintergrund tut und vieleicht resultiert daraus
Deine Abweichung.
>>Ich benutze ja nicht die ShiftOut libaray, weil diese nur 8 bit>> unterstützt, es ist ja mit digitalWrite gelöst.>Dann ruf sie halt 4 mal auf mit dem jeweiligen Byte deiner 32bit>Variable.
Das mach ich immer gerne mit Uninions, da kommt man ohne shifterei an
die bytes.
Michael K. schrieb:> Du siehst doch das digitalWrite unglaublich lange braucht um mal so ein> Portbit zu setzen. Rechne das mal in Prozesssorzyklen aus.> Der fährt erst drei mal mit dem Fahrad um den Block bis der Pin gesetzt> wird.>> Großes Rätsel was der im Hintergrund tut und vieleicht resultiert daraus> Deine Abweichung.
Unglaublich lange?
Also nur so zur info, die dauer des Clock high ist 6us!!!!
Laut IC-Spezifkation muss Data vor Clock anstehen, dazwischen sind vlt
2-3us wie man erkennen kann.
Kann ich herausfinden was im Hintergrund passiert?
Johnny S. schrieb:> Kann ich herausfinden was im Hintergrund passiert?
Erstmal kannst du das digitalWrite() gegen einen direkten Portzugriff
tauschen und die Auseinanderprökelei der jeweils 32 Bit mit bitRead(y,i)
von der Aussendung trennen. Damit hast du schon mal Rechenzeit für
Bitprökelei von der eigentlichen Aussendung getrennt. Striktes Einhalten
von EVA kann in solchen Fällen schon mal zur Übersichtlichkeit
beitragen...
Johnny S. schrieb:> Unglaublich lange?>> Also nur so zur info, die dauer des Clock high ist 6us!!!!
Oder miss doch mal aus, wie auf dem Scope eine reine Sequenz aus
Johnny S. schrieb:> Also nur so zur info, die dauer des Clock high ist 6us!!!!
Und wie viele Clock Cycles sind das bei 16Mhz und wie wiele Befehle
arbeitet die MCU währenddessen ab ?
Dafür das Du direkt hintereinander sagst mache Pin High, mache Pin Low
grenzen 6us an kompletter Arbeitsverweigerung.
> Kann ich herausfinden was im Hintergrund passiert?
Ja, indem Du den generierten ASM Code anschaust.
Wahnsinn, vielen Dank
Ich habe heute eine Messung gemacht
32 x CLOCK High/Low mit digitalWrite dauert 495 macht ca 1ms bei
2x32bit
danach
32 x CLOCK High/Low mit PORTE |= _BV(PE4) dauert es gerade mal 5us !!!
Werde heute meinen Code umbauen und dann nochmals testen. Ich glaube
damit ist auch das ursprüngliche Problem erledigt, ich hatte Probleme
das beim neu setzen der Werte in den 2 Registern die Anzeige kurz
flackerte, liegt wohl abere daran das ja die Outputs in diesem fall für
mehr als eine Millisekunde ausgeschaltet sind.