Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] ATtiny13A: Wo kommt der eine Takt her?
Bernd_Stein
05.04.2020, 17:50
Hallo zusammen,
wieder habe ich ein Problem. Wo kommt der eine Takt her ?
Eins vorweg :
Theoretisch 4,8Mhz, praktisch ist der interne RC-Oszilator aber nur mit
3,2Mhz, bei meinem ATtiny13 (https://www.mikrocontroller.net/part/ATTINY13)A, bei 5V und ca. 20°C unterwegs. Um dies
festzustellen, habe ich meinen üblichen Trick verwendet ( Endlosschleife
-> Pin toggeln und ausmessen )
Heißt: *Ein Takt sind ca. 312,500ns *
Bei dem LA-Ausschnitt ist zu sehen, dass die LED (https://www.mikrocontroller.net/articles/LED)-Gelb ( PB2 ), 2,333µS
nach der steigenden Flanke von PB1 folgt.
34932
Für mein daherhalten, erzeugt diese Codesequenz 4 oder 6 Takte, bis die
steigende Flanke von LED (https://www.mikrocontroller.net/articles/LED)-Gelb kommt:
_main:
sbis PINB,1
rjmp _main
sbi LED_PORT,led.ge ;LED-Gelb einschalten ( TEST )################################################# ########################
6T wären 1,875µs. Bleiben also noch 458ns, was locker ein Takt ist.
Deshalb meine Frage : "Wo kommt der eine Takt her?"
;
.include "Header.inc" ;Label und Werte Zuweisungen
.include "Hardware.inc" ;Hardware Label Zuweisungen
;
;Programmstart nach RESET ( Interrupt Vektoren Tabelle )
;
.CSEG ;Was ab hier folgt kommt in den FLASH-Speicher
.ORG $0000 ;Programm beginnt an der FLASH-Adresse 0x0000..
rjmp _reset ;..mit der RESET-Vektortabelle
.include "IRQt13.inc" ;Restliche Interrupt Vektortabelle
.ORG INT_VECTORS_SIZE ;Programmadresse nach den ganzen IRQ-Vektoren
;
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIIII
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIIII
;I Erstinitialisierungen
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIIII
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIIII
;
_reset:
;
;Ports Erstkonfiguration
;
sbi DDRB,led.pla ;PORT-Bit als Ausgang f. PLA-LED
sbi DDRB,led.ora ;PORT-Bit als Ausgang f. SLEEP-LED
sbi DDRB,led.ge ;PORT-Bit als Ausgang f. TEST-LED
;
;Variablen initialisieren ( r0-r31 haben unbestimmten Inhalt )
;
;
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;H Hauptprogrammschleife
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;
;sbi PINB,led.pla ;Systemtakt -> Gemessene Frequenz..######################################## ##############################
;rjmp pc-1 ;..mal 8 nehmen ################################################## #######################
_test:
cbi PORTB,led.ora ;LED-Orange einschalten
sbi PORTB,led.ora ;LED Orange ausschalten
ldi xl,8
clr b
_main:
sbis PINB,1
rjmp _main
sbi LED_PORT,led.ge ;LED-Gelb einschalten ( TEST ) ################################################## #######################
cbi LED_PORT,led.ge ;LED-Gelb ausschalten ( TEST ) ################################################## ######################
_main_1:
sbic PINB,1
rjmp _main_1
sbi LED_PORT,led.pla ;LED-PLA einschalten ( TEST ) ################################################## #######################
cbi LED_PORT,led.pla ;LED-PLA ausschalten ( TEST ) ################################################## #######################
;
;Systemtakt ( 4,8MHz ) durch X teilen
;
in a,CLKPR ;Clock Prescaler Register laden..
sbr a,1<<CLKPCE ;..Sicherheitsprozedur..
cbr a,1<CLKPS3|1<<CLKPS2|1<<CLKPS1|1<<CLKPS0;..
out CLKPR,a ;..durchfuehren..
ldi a,$7F ;..CLKPCE loeschen..
and a,b
out CLKPR,a
inc b
cpse b,xl
rjmp _main
rjmp _test
; rjmp PC ;Endlosschleife
.EXIT ;Ende des Quelltextes
Bernd_Stein
Holomino
05.04.2020, 18:19
Ich hätte ja jetzt gesagt: Das ist ein Fall für den Simulator, in dem man sowohl Takte, als auch Zeiten von solchen Codefragmenten recht verlässlich vermessen kann.
Bernd_Stein
05.04.2020, 18:53
Ich hätte ja jetzt gesagt: Das ist ein Fall für den Simulator, in dem man sowohl Takte, als auch Zeiten von solchen Codefragmenten recht verlässlich vermessen kann.
Welcher?
Der im Atmel Studio 7 ( AS7 ) ist nicht so ganz dafür zu gebrauchen. Habe mir extra die neuste Version heruntergeladen. Was da genau unrund läuft berichte ich mal später.
Bernd_Stein
Searcher
05.04.2020, 18:57
Wo kommt der eine Takt her ?
...
....
Heißt: *Ein Takt sind ca. 312,500ns *
...
Für mein daherhalten, erzeugt diese Codesequenz 4 oder 6 Takte, bis die
steigende Flanke von LED (https://www.mikrocontroller.net/articles/LED)-Gelb kommt:
_main:
sbis PINB,1
rjmp _main
sbi LED_PORT,led.ge ;LED-Gelb einschalten ( TEST )################################################# ########################
Ablauf meiner Ansicht nach:
- steigende Flanke an PB1
- es dauert max. 1,5 Takte bis Status im PIN Register steht
( ww1.microchip.com/downloads/en/DeviceDoc/doc8126.pdf , 10.2.4 Reading the Pin Value )
- SBIS braucht einen Takt wenn PIN noch LOW ist
- RJMP braucht zwei Takte zum Springen nach _main
- Zwei Takte von SBIS wenn PIN jetzt high ist
- Zwei Takte von sbi LED_PORT,led.ge
1,5T + 1T + 2T + 2T + 2T = 8,5 Takte
worst case: 8,5T * 312,5ns = 2656,25ns
Gruß
Searcher
Hallo Bernd_Stein,
Ich prüfe auch immer als erstes ob meine CPU richtig läuft.
"Instruction Cycle Time". Bei den vielen Einstellungen in Registern liegt man gerne mal falsch.
Dazu toggle ich aber lediglich einen Pin 3 mal und dann kommt der Loop
So kann ich sicher gehen, dass innerhalb der 3 Signale kein Laufzeitverzögerungen/Takte usw. zusätzlich drin sind.
Mit dem Ossi schaue ich mir das Signal dann an. Normalerweise ergibt dies 3 symetrische Impulse
und dann folgt eine etwas längere Pause wegen dem Loop oder Jump.
loop:
Pin High
Pin Low
Pin High
Pin Low
Pin High
Pin Low
jump loop
Das der RC Oszillator derart daneben liegt kann ich mir kaum vorstellen,
statt 4,8 Mhz nur 3,2 Mhz ist eher unwahrscheinlich
Laut Datenblatt kann er 10 Prozent abweichen
somit läge die Frequenz bei 4,8-0,48 = 4,32 MHz
Dieser lässt sich aber noch kalibrieren.
Ob er dadurch dann derart verschoben werden kann bin ich mir aber nicht sicher.
Siro
Ich weiss jetzt zwar nicht, ob der tiny 13 einen PWM Generator hat, wenn ja würde ich da mal eine vom Prozessortakt abhängige PWM ausgeben lassen.
Der Timer läuft unabhängig vom Prozessorkern und somit auch von Interrups und Kommando Taktzyklen.
Damit sollte sich eine qualifizierte Aussage über den Takt treffen lassen.
Bernd_Stein
07.04.2020, 12:37
@Searcher
Danke, jetzt sehe ich den Worst-Case-Fall ebenfalls so.
Ich überlege mir später den " Best-Case-Fall", also die kürzeste Ausführungszeit.
Mein ( ein ) Problem mit dem Simulator vom AS7 ist, dass beim Rücksetzen des Programmzählers am Breakpoint, der Befehl zwar ausgeführt wird, aber der PC diesen Befehl nicht mitzählt :
34936
Edit: Die ist auch richtig, da der PC ja auf Null ist und somit erstmal nur " 1st Instruction Fetch " ausgeführt wird, aber in diesem Fall störend.
EDIT : -> Quatsch, der PC müsste gezählt werden, aber der Befehl nicht ausgeführt.
>>
Ich prüfe auch immer als erstes ob meine CPU richtig läuft.
"Instruction Cycle Time". Bei den vielen Einstellungen in Registern liegt man gerne mal falsch.
Dazu toggle ich aber lediglich einen Pin 3 mal und dann kommt der Loop
So kann ich sicher gehen, dass innerhalb der 3 Signale kein Laufzeitverzögerungen/Takte usw. zusätzlich drin sind.
Mit dem Ossi schaue ich mir das Signal dann an.
>>
@Siro
Ich mache es so ähnlich, deshalb die auskommentierte Codesequenz :
;sbi PINB,led.pla ;Systemtakt -> Gemessene Frequenz..########################
;rjmp pc-1 ;..mal 8 nehmen ########################
>>
Ich weiss jetzt zwar nicht, ob der tiny 13 einen PWM Generator hat, wenn ja würde ich da mal eine vom Prozessortakt abhängige PWM ausgeben lassen.
Der Timer läuft unabhängig vom Prozessorkern und somit auch von Interrups und Kommando Taktzyklen.
Damit sollte sich eine qualifizierte Aussage über den Takt treffen lassen.
>>
@wkrug
Halte dies für zu Aufwändig. Siehe Antwort zu @Siro
Sorry, für die Formatierung, habe jetzt aber keinen Bock da weiter herum zu experimentieren. Ein korreturversuch muss reichen.
Bernd_Stein
Searcher
07.04.2020, 13:59
Hallo Berd_Stein,
Ich hab mir den Ablauf nochmal durch den Kopf gehen lassen und meine, daß der worst case eigentlich nur 7,5T lang sein kann. Ich gehe dabei davon aus, daß der externe Pegel kurz nach fallender Flanke des System Clock, etwa bei Zeitpunkt "A" high wird. Das SBIS wird zum Zeitpunkt B ausgeführt. Da kann der Zustand noch nicht im PIN Register stehen sondern wird erst im Zeitpunkt C dort stehen.
34937
Also zweiter Versuch zum Ablauf:
- steigende Flanke an PB1
- es dauert max. 1,5 Takte bis Status im PIN Register steht
( ww1.microchip.com/downloads/en/DeviceDoc/doc8126.pdf , 10.2.4 Reading the Pin Value )
- SBIS beginnt einen halben Systemtakt nach steigender Flanke an PB1 und braucht einen Takt wenn PIN noch LOW
- RJMP braucht zwei Takte zum Springen nach _main
- Zwei Takte von SBIS wenn PIN jetzt high ist
- Zwei Takte von SBI LED_PORT,led.ge
0,5T + 1T + 2T + 2T + 2T = 7,5 Takte
worst case: 7,5T * 312,5ns = 2343,75ns
In der vorherigen Rechnung bin ich davon ausgegangen, daß SBIS zum Zeitpunkt C ausgeführt wird. Da kann dann aber schon der "echte" Zustand von PB1 im PIN Register stehen und der RJMP zur _main wäre nicht nötig.
Gruß
Searcher
Bernd_Stein
08.04.2020, 09:45
Hallo Berd_Stein,
Ich hab mir den Ablauf nochmal durch den Kopf gehen lassen und meine, daß der worst case eigentlich nur 7,5T lang sein kann. Ich gehe dabei davon aus, daß der externe Pegel kurz nach fallender Flanke des System Clock, etwa bei Zeitpunkt "A" high wird. Das SBIS wird zum Zeitpunkt B ausgeführt. Da kann der Zustand noch nicht im PIN Register stehen sondern wird erst im Zeitpunkt C dort stehen.
Um so genauer man sich mit dieser Sache auseinandersetzt, um so verwirrender wird es für mich.
Ich sehe es leider nicht so für den Worst-Case-Fall, da du ja
1. zum Zeitpunkt A richtigerweise erstmal angenommen hattest, dass der Signalpegel low ist.
2. Ja, zum Zeitpunkt C wird sbis ausgeführt, aber sbi ja noch nicht.
3. Dein jetziges Szenario mit High-Pegel direkt nach der fallenden Flanke des Systemtaktes ist genau das, was im DB beschrieben ist und wir in Figure 10-3 zu sehen bekommen.
Was ich jedoch blöd gemacht finde, denn woher weiß den PINxn, dass es den Zustand erst einen Takt später vom LATCH übernehmen soll und nicht zeitgleich, wenn LATCH sich im tranparenten Abschnitt ( High-Phase des Systemtaktes ) befindet ?
In dieser Zeit ist ja D direkt an Q vorhanden und somit auch an D von PINxn.
Diese Frage kam mir auf, als ich selbst mal ein Signalverlauf aufgezeichnet habe und und nicht wusste wie sich jetzt PINxn verhält ( siehe Punkte ).
Ich habe jedoch den LATCH-Bereich straffiert, da ich den Transparentenbereich für irrelevant halte.
34939
Ich suche schon verzweifelt nach einem günstigen Bitmustergenerator ( pattern generator ), finde jedoch nichts günstiges ( um die 50€ ).
Bernd_Stein
Searcher
08.04.2020, 10:21
Was ich jedoch blöd gemacht finde, denn woher weiß den PINxn, dass es den Zustand erst einen Takt später vom LATCH übernehmen soll und nicht zeitgleich, wenn LATCH sich im tranparenten Abschnitt ( High-Phase des Systemtaktes ) befindet ?
Habe ich dem Text aus dem DB unter der Grafik entnommen. Latched wird bei fallender Flanke und ins PIN Register einen halben Takt später mit steigender Flanke geschrieben.
Consider the clock period starting shortly after the first falling edge of the system clock. The latch
is closed when the clock is low, and goes transparent when the clock is high, as indicated by the
shaded region of the “SYNC LATCH” signal. The signal value is latched when the system clock
goes low. It is clocked into the PINxn Register at the succeeding positive clock edge. As indicated by the two arrows tpd,max and tpd,min, a single signal transition on the pin will be delayed
between ½ and 1½ system clock period depending upon the time of assertion.
3. Dein jetziges Szenario mit High-Pegel direkt nach der fallenden Flanke des Systemtaktes ist genau das, was im DB beschrieben ist und wir in Figure 10-3 zu sehen bekommen.
Nicht ganz. Für den worst case muß der Einlesebefehl (in Figure 10-3 das in) bzw Abfragebefehl (dein SBIS) einen Systemtakt früher beginnen damit der "echte" PB1 Zustand noch nicht im PIN Register steht und ein RJMP ausgeführt wird. Der SBIS danach bekommt dann den echten PB1 Zustand, macht den SKIP und kann die LED einschalten.
Gruß
Searcher
Bernd_Stein
09.04.2020, 15:00
Habe ich dem Text aus dem DB unter der Grafik entnommen. Latched wird bei fallender Flanke und ins PIN Register einen halben Takt später mit steigender Flanke geschrieben.
Hast wahrscheinlich nicht sehen bzw. genau erkennen können was ich selbst da aufgezeichnet hatte. Es ging mir um diese Punktsituationen, wo dass Signal ( Data ) z.B. wieder weg ist und nun dass Latch aber zeitgleich mit der Übnahmeflanke für dass PINnx ebenfalls wieder weg ist.
Was wird da jetzt vom PINxn-D-Flip-Flop übernommen?
Wenn man dass Latch durch ein weiteres D-Flip-Flop mit negiertem Takteingang nehmen würde, wäre diese Situation eindeutig.
Jetzt kam mir die Idee, dass es evtl. erwünscht ist, dass das Signal länger als mindestens einen halben Takt sein sollte um als " erwünscht " zu gelten und somit Punkt links doch eher eine Null erkennt und Punkt rechts eher eine Eins ? Ach ich weiß auch nicht was die sich dabei gedacht haben.
34940
Nicht ganz. Für den worst case muß der Einlesebefehl (in Figure 10-3 das in) bzw Abfragebefehl (dein SBIS) einen Systemtakt früher beginnen damit der "echte" PB1 Zustand noch nicht im PIN Register steht und ein RJMP ausgeführt wird. Der SBIS danach bekommt dann den echten PB1 Zustand, macht den SKIP und kann die LED einschalten.
Gruß
Searcher
Das lass ich mir später noch mal durch den Kopf gehen, jetzt ist erstmal der Kessel am Pfeifen ;-)
Bernd_Stein
Searcher
10.04.2020, 11:46
Hast wahrscheinlich nicht sehen bzw. genau erkennen können was ich selbst da aufgezeichnet hatte.
Weiß nicht genau. Die letzte Grafik ist bei den Handskizzen nicht lesbar. PNG Format ist meist besser als JPG bei Zeichnungen.
Es ging mir um diese Punktsituationen, wo dass Signal ( Data ) z.B. wieder weg ist und nun dass Latch aber zeitgleich mit der Übnahmeflanke für dass PINnx ebenfalls wieder weg ist.
Was wird da jetzt vom PINxn-D-Flip-Flop übernommen?
Ich bin mir wirklich nicht sicher, was Du meinst.
Vom PINxn-D-Flp-Flop wird das mit der positiven Übernahmeflanke übernommen, was zu dem Zeitpunkt am Latch Ausgang ausgegeben wird. Das, was da ausgegeben wird, ist ein halber Systemtakt lang im Latch gespeichert worden.
Es spielt also keine Rolle, ob das Signal (Data) zur positiven Übernahmeflanke für PINnx wieder weg ist, da es ja im Latch gespeichert ist. Um ein Signal zu erfassen, muß es bei einer fallenden Systemtaktflanke an PB1 anliegen, da dann im Latch gespeichert wird (am Ende des gestrichelten Bereichs in Fig. 10-3).
Da man von außen ja nicht unbedingt weiß, wann eine fallende Systemtaktflanke kommt, muß ein Signal mindestens einen Systemtakt lang anliegen damit es sicher bei einer fallenden Systemtaktflanke erwischt wird und das Latch es dann speichern kann.
Gruß
Searcher
Bernd_Stein
11.04.2020, 14:32
Ich bin mir wirklich nicht sicher, was Du meinst.
Vom PINxn-D-Flp-Flop wird das mit der positiven Übernahmeflanke übernommen, was zu dem Zeitpunkt am Latch Ausgang ausgegeben wird. Das, was da ausgegeben wird, ist ein halber Systemtakt lang im Latch gespeichert worden.
Es spielt also keine Rolle, ob das Signal (Data) zur positiven Übernahmeflanke für PINnx wieder weg ist, da es ja im Latch gespeichert ist. Um ein Signal zu erfassen, muß es bei einer fallenden Systemtaktflanke an PB1 anliegen, da dann im Latch gespeichert wird (am Ende des gestrichelten Bereichs in Fig. 10-3).
Searcher
Es ist schon ein Elend mit diesen Foren. Da hat man mal einen kompetenten Schreiber der sich der Sache annimmt, dann taugt die Forensoftware leider nichts.
Man investiert eine menge Arbeit und aus dem Bild wird dann nur noch ein " Piktogramm ". Oder die Forensorftware ist Top, aber es nehmen nur Trolle an der Diskusion teil.
Also nochmal etwas anders :
Meines Wissens her, ist bei einem Latch im transparenten Teil, der Eingang gleich dem Ausgang ( D = Q ). Das Latch ist in der High-Phase des Systemtaktes transparent, also ab der steigenden Flanke bis zur fallenden Flanke des Systemtaktes.
Höchstwahrscheinlich ist dies wieder nur ein Prinzipschaltbild und dass PINxn-Register speichert mit der steigenden Flanke immer nur den gespreicherten Zustand des Latches und nicht den im transparenten Moment, oder es ist grundsätzlich so, dass ein Latch nicht so schnell vom Latch-Zustand in den Transparenten umschaltet wie ich es jetzt annehme.
34943
Dass man ein Latch nimmt und nicht ein zweites D-FF mit negiertem Takteingang, muss irgend etwas damit zu tun haben, dass man versucht kurze Pegelwechsel auszublenden, wir aber nur ein Prinzipschaltbild zu sehen bekommen, wo dies nicht ersichtlich ist.
So, schicke dies erstmal los bevor noch was schiefgeht.
Bernd_Stein
Searcher
11.04.2020, 20:14
Da hat man mal einen kompetenten Schreiber der sich der Sache annimmt,...
Kompetent? Na ja, ich bin auch nur Hobbyist und versuche in diesem Fall aus dem Datenblatt klug zu werden.
Meines Wissens her, ist bei einem Latch im transparenten Teil, der Eingang gleich dem Ausgang ( D = Q ). Das Latch ist in der High-Phase des Systemtaktes transparent, also ab der steigenden Flanke bis zur fallenden Flanke des Systemtaktes.
Höchstwahrscheinlich ist dies wieder nur ein Prinzipschaltbild und dass PINxn-Register speichert mit der steigenden Flanke immer nur den gespreicherten Zustand des Latches und nicht den im transparenten Moment, oder es ist grundsätzlich so, dass ein Latch nicht so schnell vom Latch-Zustand in den Transparenten umschaltet wie ich es jetzt annehme.
Ich glaube, so langsam komme ich dahinter was Du meinst:
- Die positive Systemtaktflanke leitet die transparente Phase des ersten Synchronizerlatches ein
- Eine positive Systemtaktflanke übernimmt aber auch den Ausgang des ersten Synchronizerlatches in das PIN-Flip-Flop.
Es könnte also sein, daß der Eingang mit positiver Systemtaktflanke transparent durch das Latch zum Eingang des PIN-Flip-Flop geht und auch gleich mit der gleichen positiven Systemtaktflanke übernommen wird.?
Ich meine nein. Das Pin-Flip-Flop ist dem Schaltzeichen nach taktflankengesteuert, kann also nur während der Taktflanke auf den Eingang reagieren. Das Latch hat mit Sicherheit ein Propagation Delay (Laufzeit) in der der Eingang zum Ausgang durchgeschaltet wird. Hier behaupte ich jetzt, daß das länger ist als eine Taktflanke dauert. Auch wenn das Latch mit positiver Systemtaktflanke transparent wird, kann es nicht rechtzeitig den Eingang zum Ausgang durchschalten, so daß der Ausgang mit gleicher positiver Systemtakflanke auch gleich ins PIN-Flip-Flop übernommen wird. Ich versuche das jetzt nicht zu belegen, sondern verlasse mich da auf das Datenblatt Figure 10-3. Sozusagen Erklärung nach Datenblatt passend gemacht, aber für mich plausibel. Man könnte jetzt gängige D-Latch/Flip-Flop (taktzustandsgsteuerte/ taktflankengesteuerte) Datenblätter suchen und Laufzeiten und Flankenzeiten durchsehen - das überlasse ich Dir :-)
Ich glaube also auch, daß immer nur der gespeicherte Zustand ins PIN-Flip-Flop übernommen wird und kein transparent durchgereichter.
Dass man ein Latch nimmt und nicht ein zweites D-FF mit negiertem Takteingang, muss irgend etwas damit zu tun haben, dass man versucht kurze Pegelwechsel auszublenden, wir aber nur ein Prinzipschaltbild zu sehen bekommen, wo dies nicht ersichtlich ist.
Da kann ich nichts zu sagen. Ich glaube jedoch nicht, daß man kurze Pegelwechsel von der µC Seite her versucht auszublenden.
Gruß
Searcher
Wenn ich auch mal eine andere Ansicht einbringen darf, würde ich sagen, das Latch übernimmt den Zustand an seinem Eingang und gibt ihn direkt an den Ausgang weiter. Ändert sich der Zustand am Eingang wieder, kommt irgendwann die steigende oder fallende Flanke, wo das Latch wieder die Information übernimmt. Die Information bleibt erhalten, selbst wenn sie am Eingang nicht mehr vorhanden ist. Mehr würde ich da nicht vermuten.
MfG
Searcher
12.04.2020, 13:31
Hallo Moppi,
ich beziehe mich auf Figure "10-2. General Digital I/O" aus dem ATtiny13A Datenblatt. Der Synchronizer dort besteht aus zwei D-Flip-Flops. Das erste, an dem der Portpin der D-Eingang ist, ist ein taktzustandsgesteuertes. Nenn ich kurz Latch. Das zweite ist ein taktflankengesteuertes und nenne ich hier PIN-Flip-Flop. Das ist dann auch das PIN-Register für einen Portpin. Dessen D-Eingang ist der Ausgang des Latches.
... das Latch übernimmt den Zustand an seinem Eingang und gibt ihn direkt an den Ausgang weiter.
Aber nur wenn der Systemtakt "high" ist. Wenn Systemtakt low, dann ist das Latch nicht transparent.
Ändert sich der Zustand am Eingang wieder, kommt irgendwann die steigende oder fallende Flanke, wo das Latch wieder die Information übernimmt.
Welches Latch? Das erste im Sychronizer ist taktzustandsgesteuert. Das zweite, auch PIN-Flip-Flop übernimmt nur bei steigender Flanke.
Die Information bleibt erhalten, selbst wenn sie am Eingang nicht mehr vorhanden ist. Mehr würde ich da nicht vermuten.
Wenn die Information nicht bei einer fallenden Systemtakt Flanke am Eingand des ersten Latches anliegt, geht sie verloren, bzw wird ein falscher gepeichert. Wie oben schon mal erwähnt, meine ich, daß ein Signal, um es sicher zu erkennen, mindestens ein Systemtakt lang anliegen muß. Sie bleibt dann einen halben Systemtakt lang im Latch gespeichert. Hier kann das Signal sich am Portpin ändern ohne Auswirkung auf die Weitergabe zum PIN-Flip-Flop. Nach dem halben Systemtakt wird der gespeicherte Zustand vom PIN-Flip-Flop mit einer positiven Systemtaktflanke übernommen.
Gruß
Searcher
Bernd_Stein
14.04.2020, 15:38
...
Ich glaube, so langsam komme ich dahinter was Du meinst:
- Die positive Systemtaktflanke leitet die transparente Phase des ersten Synchronizerlatches ein
- Eine positive Systemtaktflanke übernimmt aber auch den Ausgang des ersten Synchronizerlatches in das PIN-Flip-Flop.
...
Gruß
Searcher
Schön,
ich denke es liegt auch ein wenig daran, dass meine Screenshots hier eher wie Piktogramme erscheinen.
Deshalb habe ich hier mal versucht meine Überlegungen zum Best-Case-Fall deutlich zu machen und würde mich freuen deine Sichtweise hierzu zu erfahren :
https://www.edv-dompteur.de/forum/index.php?page=Thread&postID=4004#post4004
Bernd_Stein
Searcher
15.04.2020, 18:25
ich denke es liegt auch ein wenig daran, dass meine Screenshots hier eher wie Piktogramme erscheinen.
Deshalb habe ich hier mal versucht meine Überlegungen zum Best-Case-Fall deutlich zu machen und würde mich freuen deine Sichtweise hierzu zu erfahren :
Ich denke, daß man hier auch alles deutlich darstellen kann, was nötig ist. Vielleicht nicht so komfortabel und mit einiger Formatiererei von Bildern verbunden. Aber es geht. Ich mag auch nicht forenübergreifend referenzieren.
Zum best case ist es nötig, daß das Signal, also das high an PB1 zu einem Zeitpunkt gerade vor einer fallenden Flanke des Systemtaktes angelegt wird. Dann wird es gelatcht (gespeichert). Das SBIS aus dem Assembler code muß dann zu Beginn der unmittelbar folgenden steigenden Systemtaktflanke beginnen. Dann ist auch das Signal in das PINxn übernommen worden (nach Fig. 10.3) und kann von SBIS gültig abgefragt werden. SBIS führt einen SKIP über den RJMP durch und schaltet die LED ein.
0,5T von fallender Falnke des Latches und speichern
2T vom SBIS (mit SKIP)
2T vom SBI zum LED einschalten.
Also 4,5 Systemtakttakte sehe ich als best case.
Gruß
Searcher
avr_racer
15.04.2020, 19:56
Hallo zusammen,
wieder habe ich ein Problem. Wo kommt der eine Takt her ?
Eins vorweg :
Theoretisch 4,8Mhz, praktisch ist der interne RC-Oszilator aber nur mit
3,2Mhz, bei meinem ATtiny13 (https://www.mikrocontroller.net/part/ATTINY13)A, bei 5V und ca. 20°C unterwegs. Um dies
festzustellen, habe ich meinen üblichen Trick verwendet ( Endlosschleife
-> Pin toggeln und ausmessen )
Heißt: *Ein Takt sind ca. 312,500ns *
Jo okay wenn ich es also richtig verstehe möchtest du den Takt sprich die Zeit ermitteln. Und der Tiny läuft auf 4,8Mhz um wenige Khz würde ich mich jetzt nicht festlegen wollen siehe
DB
During reset, hardware loads the calibration data into the OSCCAL register and thereby auto-matically calibrates the oscillator. There are separate calibration bytes for 4.8 and 9.6 MHzoperation but only one is automatically loaded during reset (see section “Calibration Bytes” onpage 104). This is because the only difference between 4.8 MHz and 9.6 MHz mode is an inter-nal clock divider
3,2/4,8 = 0,66666 sprich 66,66%
3,2Mhz = 312,5ns
4,8Mhz = 208,3ns Taktzeit
Sonst lese er mal vom Tiny das OSSCAL aus was nach einem RESET reingeschrieben wurde siehe Seite 104
The signature area of the ATtiny13 contains two bytes of calibration data for the internal oscilla-tor. The calibration data in the high byte of address 0x00 is for use with the oscillator set to 9.6MHz operation. During reset, this byte is automatically written into the OSCCAL register toensure correct frequency of the oscillator.There is a separate calibration byte for the internal oscillator in 4.8 MHz mode of operation butthis data is not loaded automatically. The hardware always loads the 9.6 MHz calibraiton dataduring reset. To use separate calibration data for the oscillator in 4.8 MHz mode the OSCCALregister must be updated by firmware. The calibration data for 4.8 MHz operation is located inthe high byte at address 0x01 of the signature area.
Bei dem LA-Ausschnitt ist zu sehen, dass die LED (https://www.mikrocontroller.net/articles/LED)-Gelb ( PB2 ), 2,333µS
nach der steigenden Flanke von PB1 folgt.
34932
Für mein daherhalten, erzeugt diese Codesequenz 4 oder 6 Takte, bis die
steigende Flanke von LED (https://www.mikrocontroller.net/articles/LED)-Gelb kommt:
_main:
sbis PINB,1
rjmp _main
sbi LED_PORT,led.ge ;LED-Gelb einschalten ( TEST )################################################# ########################
6T wären 1,875µs. Bleiben also noch 458ns, was locker ein Takt ist.
Deshalb meine Frage : "Wo kommt der eine Takt her?"
;
.include "Header.inc" ;Label und Werte Zuweisungen
.include "Hardware.inc" ;Hardware Label Zuweisungen
;
;Programmstart nach RESET ( Interrupt Vektoren Tabelle )
;
.CSEG ;Was ab hier folgt kommt in den FLASH-Speicher
.ORG $0000 ;Programm beginnt an der FLASH-Adresse 0x0000..
rjmp _reset ;..mit der RESET-Vektortabelle
.include "IRQt13.inc" ;Restliche Interrupt Vektortabelle
.ORG INT_VECTORS_SIZE ;Programmadresse nach den ganzen IRQ-Vektoren
;
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIIII
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIIII
;I Erstinitialisierungen
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIIII
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIIII
;
_reset:
;
;Ports Erstkonfiguration
;
sbi DDRB,led.pla ;PORT-Bit als Ausgang f. PLA-LED
sbi DDRB,led.ora ;PORT-Bit als Ausgang f. SLEEP-LED
sbi DDRB,led.ge ;PORT-Bit als Ausgang f. TEST-LED
;
;Variablen initialisieren ( r0-r31 haben unbestimmten Inhalt )
;
;
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;H Hauptprogrammschleife
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;
;sbi PINB,led.pla ;Systemtakt -> Gemessene Frequenz..######################################## ##############################
;rjmp pc-1 ;..mal 8 nehmen ################################################## #######################
_test:
cbi PORTB,led.ora ;LED-Orange einschalten
sbi PORTB,led.ora ;LED Orange ausschalten
ldi xl,8
clr b
_main:
sbis PINB,1
rjmp _main
sbi LED_PORT,led.ge ;LED-Gelb einschalten ( TEST ) ################################################## #######################
cbi LED_PORT,led.ge ;LED-Gelb ausschalten ( TEST ) ################################################## ######################
_main_1:
sbic PINB,1
rjmp _main_1
sbi LED_PORT,led.pla ;LED-PLA einschalten ( TEST ) ################################################## #######################
cbi LED_PORT,led.pla ;LED-PLA ausschalten ( TEST ) ################################################## #######################
;
;Systemtakt ( 4,8MHz ) durch X teilen
;
in a,CLKPR ;Clock Prescaler Register laden..
sbr a,1<<CLKPCE ;..Sicherheitsprozedur..
cbr a,1<CLKPS3|1<<CLKPS2|1<<CLKPS1|1<<CLKPS0;..
out CLKPR,a ;..durchfuehren..
ldi a,$7F ;..CLKPCE loeschen..
and a,b
out CLKPR,a
inc b
cpse b,xl
rjmp _main
rjmp _test
; rjmp PC ;Endlosschleife
.EXIT ;Ende des Quelltextes
Bernd_Stein
EIJJAAAAAAIJJAIIIIIIIIII da is ja so einiges im Argen.
1. Woher sollen wir wissen was in deinen Includes steht bzw ob es überhaupt sinnvoll ist ?
2. Includes entweder komplett vorne und hinten anfügen aber nicht unbedingt irgendwo im Programm.
3. Wenn du mit INT arbeitest was meinst du was du bei der Initialisierung noch brauchst ?
DEN STACKPOINTER!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
4. Was steht in der ISR als Rücksprung bzw ist das RETI eingetragen ? Wenn nicht läuft er dir dein CTRL die gesamten ISR-Routinen durch, bisher sind sie für uns alle UNSICHTBAR siehe Punkt 1, und wenn da irgendwas steht wird das
gnaaaadenlos abgearbeitet was dann zu unerwarteten Effekten führen kann wie zb ein RESET des gesamten CTRL. Besonders wenn ein RET/RETI ausgeführt wird ohne den SP angelegt zu haben.
5. Sieh dir mal an wie ich es Bibliotheken gepackt habe https://www.roboternetz.de/community/threads/70938-ATMega48-88-168-328-Bibliothek
6. Zu
.ORG INT_VECTORS_SIZE ;Programmadresse nach den ganzen IRQ-Vektoren
was komplett falsch verstanden worden ist
EINMAL folgendes lesen https://www.mikrocontroller.net/topic/265926
7. Was meinst du wie sehr ein Taster prellt ? Da arbeitet er die Befehle folgend auf SBIC/S sofort mehrmals ab deshalb ist absolut unelegant einen Taster ohne Wartezeit oder Entprellroutine so abzufragen.
Sollte das Signal natürlich DIGITAL vorliegen ist es so durchaus normal. Leider fehlt der Kommentar was die Ursache zum Auslösen ist.
8. Zum Systemtakt änder verweise ich auf S.28 des DB wie dort 100%ig zu verfahren ist und nicht irgendwie https://ww1.microchip.com/downloads/en/devicedoc/doc2535.pdf
Vorschlag wenn du ohne große INIT usw usf deinen Systemtakt ermitteln möchtest wie folgt
INIT:
SBI DDRX , Y ; 2Takte
Start:
SBI PORTX , Y ; 2Takte
CBI PORTX , Y ; 2Takte
SBI PORTX , Y ; 2Takte
CBI PORTX , Y ; 2Takte
SBI PORTX , Y ; 2Takte
CBI PORTX , Y ; 2Takte
rjmp Start ; 2Takte
Beim RJMP bleibt das Bit etwas länger gelöscht ist aber nicht weiter schlimm man könnte daran erkennen wann das Programm wieder von vorn beginnt. So eine Art Synch....
PS: Dein nicht erklärbarer Takt kommt von deiner Software und von nichts anderen !!!! ASM macht nur das was DU, der Programmierer geschrieben hast, auch wenn mal etwas vergessen wurde
- - - Aktualisiert - - -
Es ist schon ein Elend mit diesen Foren. Da hat man mal einen kompetenten Schreiber der sich der Sache annimmt, dann taugt die Forensoftware leider nichts.
Man investiert eine menge Arbeit und aus dem Bild wird dann nur noch ein " Piktogramm ". Oder die Forensorftware ist Top, aber es nehmen nur Trolle an der Diskusion teil.
Also nochmal etwas anders :
Meines Wissens her, ist bei einem Latch im transparenten Teil, der Eingang gleich dem Ausgang ( D = Q ). Das Latch ist in der High-Phase des Systemtaktes transparent, also ab der steigenden Flanke bis zur fallenden Flanke des Systemtaktes.
Höchstwahrscheinlich ist dies wieder nur ein Prinzipschaltbild und dass PINxn-Register speichert mit der steigenden Flanke immer nur den gespreicherten Zustand des Latches und nicht den im transparenten Moment, oder es ist grundsätzlich so, dass ein Latch nicht so schnell vom Latch-Zustand in den Transparenten umschaltet wie ich es jetzt annehme.
34943
Dass man ein Latch nimmt und nicht ein zweites D-FF mit negiertem Takteingang, muss irgend etwas damit zu tun haben, dass man versucht kurze Pegelwechsel auszublenden, wir aber nur ein Prinzipschaltbild zu sehen bekommen, wo dies nicht ersichtlich ist.
So, schicke dies erstmal los bevor noch was schiefgeht.
Bernd_Stein
Das Problem hat NIX, 0 mit der HW des CTRL zu tun !!!!
Aber um die Informationslage etwas zu verdichten kann man ganz vereinfacht sagen das Daten erst auf den PORT/DDR/PIN gelegt/abgefragt werden wenn der nächste Systemtakt kommt. Dies soll sicherstellen das die Daten immer und zu jeden Zeitpunkt KONSISTENT sind.
Man stelle sich vor dies wäre nicht so und am Eingang/Ausgang wird es ASynchron geändert was das für ein Durcheinander in UNSERER SW geben würde. Manche Programmteile würde immer ausgeführt manche gar nicht und andere wiederum nur ab und an und manch andere nur mit gaaaanz viel Glück.
Siehe ADC wenn 10bit ausgelesen werden sollen wird das Datenwort, also die 10Bit = 8 Bit low und 2 Bit High, MUSS ADCL als erstes gelesen werden und erst wenn ADCH gelesen WORDEN ist wird ADCH:L für den ADC freigegeben wieder Ergebnisse dort zu hinterlegen damit die Datensätze konsistent bleiben.
Bernd_Stein
16.04.2020, 10:36
...
Also 4,5 Systemtakttakte sehe ich als best case.
Gruß
Searcher
Oh, ja stimmt. Was habe ich wieder für ein Quatsch gedacht. Das zeichne ich konkret den Codeablauf Takt für Takt auf und interpretiere es dann doch falsch.
@avr_racer
Das war erstmal eine zu geballte Informationsflut, die ich mir einmal durchgelesen habe. Du scheinst ja mächtig viel in AVR8ASM zu programmieren, was ja schon mal gut ist. Das DB zu zitieren ist schon mal nicht schlecht, aber mit dem Verstehen des englischen hapert es leider bei mir. Werde evtl. irgendwann später auf dein Post eingehen, jetzt will ich aber auch mal weiterkommen.
Bernd_Stein
Bernd_Stein
17.04.2020, 16:08
@avr_racer und alle anderen Interessierten natürlich !
Da fällt mir heute ein um weiter zu kommen ist es vielleicht doch hilfreich mal komplett zu erklären was ich vor habe.
Damit sind evtl. auch schon viele Fragen beantwortet.
In der Header-Datei steht was ich vor habe. Derzeitiges Problem ist, dass das erste Bit zu spät eingelesen wird.
Header.inc -> Header-Datei
;
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
; Headerdatei
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;Programm CY800_E.ASM
;
;Auswerten eines Funksteckdosen-Protokolls des Bausteins CY800.
;
;Für ATtiny13A mit internem RC-Oszillator 4,8MHz
;FUSE-BITS High = $FF ; Low = $3B
;
;Am Pin 6 ( INT0 ) wird dass Signal des CY800 eingelesen.
;Am Pin 5 ( PCINT0 ) dieses Signal des CY800 ueber ein Monoflop.
;Der Pin 3 ( PB4 ), wird bei jedem neu empfangenem und uebereinstimmendem 3 Byte
;Bitmuster getoggelt.
;
;Der µC soll moeglichst stromsparend betrieben werden, deshalb wird er mit ver-
;schiedenen SLEEP-Modes und Systemtakten betrieben. Zu Beginn wird der µC in den
;SLEEP-Mode, PowerDown versetzt.
;
;Da der CY800 immer irgendwelche Signale ausgibt, wird hiermit ein retrigger-
;bares Monoflop ( 8,3ms ) beaufschlagt, was somit die meiste Zeit einen High-
;Pegel erzeugt. Im CY800-Protokoll kommt es nach dem Synchronisationsbit zu
;einer 8,5ms langen Low-Phase, wodurch dass MF nicht mehr nachgetriggert wird
;und es eine fallende Flanke erzeugt, wodurch die PCINT0-IRQ ausgeloest wird.
;In dieser ISR wird dann, unter anderem, die INT0-IRQ auf steigende Flanke ein-
;gestellt, um den Beginn des Datenpaketes zu erfassen. Mittels Timer/Couter0
;Overflow IRQ, wird dann nach 550µs dass erste Bit eingelesen und alle weiteren
;23 Bits mit 1100µs Abstand. Hiernach werden die drei eingelesen Bytes mit denen
;im Flash abgelegten ( Tastencode ) verglichen und bei Uebereinstimmung die
;LED-PLA getoggelt.
;
;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
; Einbinden der Controllerspezifischen Definitionsdatei
;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC CCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
;
.NOLIST ;List-Output ausschalten
;.INCLUDE "tn13Adef.inc" ;AVR-Definitionsdatei einbinden
.LIST ;List-Output wieder einschalten
;
;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR RRRRRRRRRRRRRRRRRRRRRRRRRRRRR
;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR RRRRRRRRRRRRRRRRRRRRRRRRRRRRR
; Arbeitsregister umbenennen
;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR RRRRRRRRRRRRRRRRRRRRRRRRRRRRR
;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR RRRRRRRRRRRRRRRRRRRRRRRRRRRRR
;
.DEF byte_0 = r0 ;Byte0 vom CY800-Paket
.DEF byte_1 = r1 ;Byte1 vom CY800-Paket
.DEF byte_2 = r2 ;Byte2 vom CY800-Paket
.DEF code = r3 ;Wird f. den Codevergleich benoetigt
;.DEF bytezeiger = r4
.DEF ovf0_zlr = r5 ;Timer0 Overflow-Zaehler
.DEF vergleichs_zlr = r6 ;Vergleichszaehler f. 3maligen Vergleich
;.DEF = r7 ;
;.DEF = r8 ;
;.DEF = r9 ;
;.DEF = r10 ;
;.DEF = r11 ;
;.DEF = r12 ;
;.DEF = r13 ;
;.DEF = r14 ;
.DEF s_sreg = r15 ;Zum Sichern des Statusregisters ( Nur 1 Takt )
.DEF ia = r16 ;Interrupt Arbeitsregister ia ( Nur in ISR genutzt )
;.DEF ib = r17 ;Interrupt Arbeitsregister ib ( Nur in ISR genutzt )
.DEF bytezeiger = r18 ;Zeiger f. dass jeweilige Byte
.DEF flag_reg = r19 ;Allgemeines Flaggen-Register
.DEF bit_zlr = r20 ;CY800 Bitzaehler
;.DEF = r21 ;
;.DEF = r22 ;
;.DEF = r23 ;
.DEF a = r24 ;Register 24 und 25 kann als universelles..
.DEF b = r25 ;..Doppelregister dienen
;.DEF xl = r26 ;Der X-Zeiger
;.DEF xh = r27 ;..adresse
;.DEF yl= r28 ;
;.DEF yh= r29 ;
;.DEF zl = r30 ;Verwendung als Z-Zeiger, also wie bereits in der..
;.DEF zh = r31 ;..Definitionsdatei von ATMEL angegeben
;
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
; Konstanten als Symbole
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;
.EQU #ovf0_zlr = 5 ;fuer PLA-LED blinken ( Werte von 0-7 )
.EQU #bit_zlr = 8 ;Bitzaehler innerhalb eines Bytes
.EQU #vergleichs_zlr = 3 ;Die 3 Bytes x mal vergleichen
;
;
;Bitbezeichner fuer das allgemeine Flaggenregister flag_reg
;
;.equ = 0 ;
;.equ = 1 ;
;.equ = 2 ;
.equ pdm = 3 ;Power-Down-Mode ist erwuenscht
.equ pla.flg = 4 ;Programmlaufanzeige-Flagge
.equ fertig = 5 ;CY800 Paket ( 24-Bits ) erfasst
;.equ = 6 ;
;.equ = 7 ;
;
Um ein detailreicheres Bild sehen zu können, bitte hier kurz reinschauen :
https://www.mikrocontroller.net/topic/487338#6099487
(https://www.mikrocontroller.net/topic/487338#6099487)
Im unteren Link ist zu sehen, dass nach der steigenden Flanke am INT0-Pin ( Hier durch IN/Data repräsentiert ) , dass Signal erst nach 969,333µs eingelesen werden würde ( LED-PLA = High ).
LED-Gelb High zeigt den Zeitpunkt, wo der Code in der INT0-ISR ausgeführt wird und LED-Gelb Low, dass Ende dieser ISR.
Das Erwachen aus dem IDLE-Mode dauert 16 Takte -> 16 x 9,827µs ~ 157µs, dann würde in die INT0-ISR eingesprungen werden. Dort wird der SYS-Takt auf Nominal 600kHz geändert und bereits der Timer/Counter0 Overflow Interrupt initialisiert, sowie gestartet. Ovfl-IRQ also nach 256 x 2,435µs ~ 626µs. 626 + 157 ~ 783µs. Ist zwar schon zu viel ( 550µs ), aber egal, da es mir jetzt erstmal um diese Diskrepanz zwischen Therorie und Praxis geht.
Verstehe einfach nicht, wieso ~186µs mehr entstehen ( 969 - 783 ~ 186µs bzw. ~76 Takte )?
Die 9,827µs sind die Echte Taktzeit bei Nominal 150kHz und die 2,435µs die bei Nominal 600kHz.
Also hier im unteren Link die jeweilige xyz.jpg Datei anklicken um die Bilder sichtbar zu machen :
https://www.edv-dompteur.de/forum/index.php?page=Thread&postID=4015#post4015
Hauptprogrammschleife :
;
.include "Header.inc" ;Label und Werte Zuweisungen
.include "Hardware.inc" ;Hardware Label Zuweisungen
;
;Programmstart nach RESET ( Interrupt Vektoren Tabelle )
;
.CSEG ;Was ab hier folgt kommt in den FLASH-Speicher
.ORG $0000 ;Programm beginnt an der FLASH-Adresse 0x0000..
rjmp _reset ;..mit der RESET-Vectortabelle
.include "IRQt13.inc" ;Restliche Interrupt Vektortabelle
.ORG INT_VECTORS_SIZE ;Programmadresse nach den ganzen IRQ-Vektoren
;
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIIII
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIIII
;I Erstinitialisierungen
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIIII
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII IIIIIIIIIIIIIIIIIIIIIIIIIIIII
;
_reset:
;
;Systemtakt ( 4,8MHz ) durch 32 teilen ( 150kHz = 6,666µs )
;
in a,CLKPR ;Clock Prescaler Register laden..
sbr a,1<<CLKPCE ;..Sicherheitsprozedur..
cbr a,1<CLKPS3|1<<CLKPS2|1<<CLKPS1|1<<CLKPS0;..
out CLKPR,a ;..durchfuehren..
in a,CLKPR ;Clock Prescaler Register laden..
cbr a,1<<CLKPCE ;..jetzt den Teiler..
sbr a,1<<CLKPS2|1<<CLKPS0 ;..neu einstellen..
out CLKPR,a ;..und ueberschreiben
;
;Stapelzeiger initialisieren (fuer Unterprogramme und / oder Interrupts)
;
;ldi a,High(RAMEND) ;RAMEND, also das Ende vom SRAM, ist in der..
;out SPH,a ;..Definitions-datei festgelegt
ldi a,Low (RAMEND) ;Hier reicht ein Byte, weil das...
out SPL,a ;...SRAM nur 64Byte gross ist
;
;Ports Erstkonfiguration
;
sbi DDRB,led.pla ;PORT-Bit als Ausgang f. PLA-LED
sbi DDRB,led.ora ;PORT-Bit als Ausgang f. SLEEP-LED
sbi DDRB,led.ge ;PORT-Bit als Ausgang f. TEST-LED
;
;Variablen initialisieren ( r0-r31 haben unbestimmten Inhalt )
;
clr flag_reg ;Allgemeines Flaggenregister;
clr ovf0_zlr ;Timer0 Overflow-Zaehler initialisieren
clr bit_zlr ;CY800 Bitzaehler
sbr flag_reg,1<<pdm ;Power-Down-Mode ist gewuenscht
sbr bytezeiger,1<<2 ;Zeiger auf Byte2 setzen
ldi zh,high(_code*2) ;Z-Zeiger mit Vergleichscode-Adresse..
ldi zl,low (_code*2) ;..laden
;
;Pin Change Interrupt 0 -> PCI0 initialisieren
;
in a,PCMSK ;Pin Change Mask Register laden und..
sbr a,1<<PCINT0 ;..Pin Change Interrupt 0 auswaehlen
out PCMSK,a ;..und Register ueberschreiben
in a,GIMSK ;General Interrupt Masken Register laden und..
sbr a,1<<PCIE ;..Pin Change Interruput 0 Freigabebit setzen..
out GIMSK,a ;..INT0 Interrupt freigeben und..
ldi a,1<<PCIF ;..Pin Change Interrupt Flag..
out GIFR,a ;..loeschen
sei ;Alle programmierbaren Interrupts freigeben
;
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;H Hauptprogrammschleife
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH HHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;
_main:
;
;SLEEP-Mode ausschalten und auf Werkseinstellung setzen
;
in a,MCUCR ;MCU Control Register laden und..
cbr a,1<<SM1|1<<SM0|1<<SE ;..auf Werkseinstellung..
out MCUCR,a ;..setzen
sbr flag_reg,1<<pla.flg ;Programmlaufanzeige-Flag quitieren
sbrc flag_reg,fertig ;CY800-Paket erfasst?
rjmp _fertig ;..JA -> LED-Gelb ( TEST ) einschalten
sbrs flag_reg,pdm ;Power-Down-Mode erwuenscht?
rjmp _idle ;Nein -> µC in IDLE-Mode versetzen
;
;SLEEP-MODE -> Power Down
;
cbi PORTB,led.ora ;LED-Orange einschalten T E S T Z W E C K E ###########################
in a,MCUCR ;MCU Control Register laden..
sbr a,1<<SM1|1<<SE ;..Power-Down-Mode und Sleep Enable vorbereiten..
out MCUCR,a ;..und freigeben
sleep ;µC in den Schlaf-Modus versetzen
rjmp _main ;Arbeitsschleife ausfuehren
;
;SLEEP-MODE -> IDLE
;
_idle:
sbi PORTB,led.ora ;LED Orange ausschalten T E S T Z W E C K E ###########################
in a,MCUCR ;MCU Control Register laden..
cbr a,1<<SM1|1<<SM0 ;..IDLE-Mode und..
sbr a,1<<SE ;..Sleep Enable vorbereiten..
out MCUCR,a ;..und freigeben
sleep
rjmp _main ;Arbeitsschleife ausfuehren
;
;Der Code stimmt nicht
;
_gescheitert:
ldi a,#vergleichs_zlr ;..NEIN -> Vergleichszaehler neu..
mov vergleichs_zlr,a ;..laden
rjmp _loeschen ;..Bytes sind ungleich, also alle 3 Bytes loeschen
;
;CY800-Paket vergleichen
;
_fertig:
lpm code,Z+ ;Code-Byte2 laden und Zeiger inkrementieren..
cp code,byte_2 ;..beide Bytes vergleichen..
brne _gescheitert ;Der Code stimmt nicht -> springen
lpm code,Z+ ;Code-Byte1 laden und Zeiger inkrementieren..
cp code,byte_1 ;..beide Bytes vergleichen..
brne _gescheitert ;Der Code stimmt nicht -> springen
lpm code,Z ;Code-Byte0 laden..
cp code,byte_0 ;..beide Bytes vergleichen..
brne _gescheitert ;Der Code stimmt nicht -> springen
tst vergleichs_zlr ;3 maliger Vergleichen der 3 Bytes positiv?
breq _umschalten ;JA -> Ausgang Umschalten
dec vergleichs_zlr ;Vergleichszaehler dekrementieren
;
;Systemtakt ( 4,8MHz ) durch 32 teilen ( 150kHz = 6,666µs )
;
_loeschen:
cli ;Alle globalen Interrupts sperren
in a,CLKPR ;Clock Prescaler Register laden..
sbr a,1<<CLKPCE ;..Sicherheitsprozedur..
cbr a,1<CLKPS3|1<<CLKPS2|1<<CLKPS1|1<<CLKPS0;..
out CLKPR,a ;..durchfuehren..
in a,CLKPR ;Clock Prescaler Register laden..
cbr a,1<<CLKPCE ;..jetzt den Teiler..
sbr a,1<<CLKPS2|1<<CLKPS0 ;..neu einstellen..
out CLKPR,a ;..und ueberschreiben
sei ;Alle globalen Interrupts wieder freigeben
clr byte_2 ;Die 3..
clr byte_1 ;..Bytes..
clr byte_0 ;..loeschen
cbr flag_reg,1<<fertig ;CY800 Paket erfasst FLAG loeschen
sbr bytezeiger,1<<2 ;Zeiger auf Byte2 setzen
sbr flag_reg,1<<pdm ;Power-Down-Mode freigeben
;
;Pin Change Interrupt 0 -> PCI0 initialisieren
;
in a,PCMSK ;Pin Change Mask Register laden und..
sbr a,1<<PCINT0 ;..Pin Change Interrupt 0 auswaehlen
out PCMSK,a ;..und Register ueberschreiben
in a,GIMSK ;General Interrupt Masken Register laden und..
sbr a,1<<PCIE ;..Pin Change Interruput 0 Freigabebit setzen..
out GIMSK,a ;..INT0 Interrupt freigeben und..
ldi a,1<<PCIF ;..Pin Change Interrupt Flag..
out GIFR,a ;..loeschen
rjmp _main ;Arbeitsschleife ausfuehren
;
;Ausgang Umschalten
;
_umschalten:
;sbi LED_PORT,led.ge ;LED-Gelb einschalten T E S T Z W E C K E ############################
ldi a,#vergleichs_zlr ;Vergleichszaehler neu..
mov vergleichs_zlr,a ;..laden
rjmp _main ;Arbeitsschleife ausfuehren
; rjmp PC ;Endlosschleife
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;Q Beginn der verwendeten Interrupt Service Routinen ( ISR )
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
.include "ISR.inc" ;Interrupt Service Routinen
;
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;K Beginn der Programmkonstanten
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK KKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;
_code:
.DB $C3,$50,$43,00 ;3 Codebytes f. Taste A ( Byte2,Byte1,Byte0 )
.EXIT ;Ende des Quelltextes
Hardware.inc :
;
;************************************************* ******************************
;* Hardware Zuweisungen
;************************************************* ******************************
;
;.EQU XTAL = 1843200 ;Quarzfrequenz in Hertz
.EQU LED_PIN = PINB ;Eingabeport an dem die LED angeschlossen ist
.EQU LED_DDR = DDRB ;Datenrichtungsregister fuer die LED
.EQU LED_PORT = PORTB ;Ausgabeport fuer die Programmlaufanzeige-LED
.EQU cy800.data = PB1 ;Pin Dataausgang vom CY800
.EQU led.ge = PB2 ;Pin an dem die LED-Gelb angeschlossen ist
.EQU led.ora = PB3 ;Pin an dem die LED-Orange angeschlossen ist
.EQU led.pla = PB4 ;Pin wo die LED-ProgrammLaufAnzeige dran ist
.EQU INT0_PIN = PINB ;CY800 Eingabeport
.EQU PIN_PLA = PINB ;Eingabeport wo die LED-ProgrammLaufAnzeige ist
IRQt13.inc -> Restliche Interrupt Vektortabelle :
;
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV VVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
; Interruptvektortabelle des ATtiny13 Mikrocontrollers
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV VVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
; ***** INTERRUPT VECTORS ************************************************
rjmp _INT0addr ; External Interrupt 0
rjmp _PCI0addr ; External Interrupt Request 0
rjmp _OVF0addr ; Timer/Counter0 Overflow
reti ;rjmp _ERDYaddr ; EEPROM Ready
reti ;rjmp _ACIaddr ; Analog Comparator
reti ;rjmp _OC0Aaddr ; Timer/Counter Compare Match A
reti ;rjmp _OC0Baddr ; Timer/Counter Compare Match B
reti ;rjmp _WDTaddr ; Watchdog Time-out
reti ;rjmp _ADCCaddr ; ADC Conversion Complete
ISR.inc -> Interrupt Service Routinen ( ISR ):
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;Q Beginn der verwendeten Interrupt Service Routinen ( ISR )
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
; INTERRUPT REQUEST 0 INT0
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
_INT0addr:
sbi LED_PORT,led.ge ;LED-Gelb einschalten T E S T Z W E C K E #############################
in s_sreg,SREG ;CPU-Statusregister sichern
;
;INT0 Interrupt sperren
;
in ia,GIMSK ;General Interrupt Mask Register laden..
cbr ia,1<<INT0 ;..INT0 Interrupt sperren vorbereiten und..
out GIMSK,ia ;..ausfuehren..
;
;Systemtakt ( 4,8MHz ) durch 8 teilen ( 600kHz = 1,666µs )
;
cli ;Alle globalen Interrupts sperren
in ia,CLKPR ;Clock Prescaler Register laden..
sbr ia,1<<CLKPCE ;..Sicherheitsprozedur..
cbr ia,1<CLKPS3|1<<CLKPS2|1<<CLKPS1|1<<CLKPS0;..
out CLKPR,ia ;..durchfuehren..
in a,CLKPR ;Clock Prescaler Register laden..
cbr ia,1<<CLKPCE ;..jetzt den Teiler..
sbr ia,1<<CLKPS1|1<<CLKPS0 ;..neu einstellen..
out CLKPR,ia ;..und ueberschreiben
sei ;Alle globalen Interrupts wieder freigeben
;
;Timer/Counter0 im CTC-Mode betreiben und Overflow-Interrupt initialisieren
;
in ia,TCNT0 ;Timer/Counter0 Zaehlregister laden und..
clr ia ;..ruecksetzen ( Null )..
out TCNT0,ia ;..ausfuehren
ldi ia,1<<TOIE0 ;Timer/Counter0 Overflow Interrupt...
out TIMSK0,ia ;...enablen (TOIE0) und..
in ia,TCCR0B ;..Timer/Counter0 ControlregisterB lesen..
sbr ia,1<<CS00 ;..Timer0 mit 1:1 Teiler..
out TCCR0B,ia ;..starten
ldi ia,1<<TOV0 ;..Timer/Counter0 Overflow Interrupt Flag..
out TIFR0,ia ;..loeschen..
;
;Bitzaehler einstellen
;
ldi ia,#bit_zlr ;Wert f. Bitzaehler laden..
mov bit_zlr,ia ;..und Bitzaehler einstellen
_exit_INT0addr:
out SREG,s_sreg ;Statusregister wiederherstellen
cbi LED_PORT,led.ge ;LED-Gelb ausschalten T E S T Z W E C K E ###########################
reti ;INT0addr ISR verlassen
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
; PIN CHANGE INTERRUPT 0
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
_PCI0addr:
in s_sreg,SREG ;CPU-Statusregister sichern
;
;Pin Change Interrupt 0 -> PCI0 sperren
;
in ia,PCMSK ;Pin Change Mask Register laden und..
cbr ia,1<<PCINT0 ;..Pin Change Interrupt 0 sperren
out PCMSK,ia ;..und Register ueberschreiben
in ia,GIMSK ;General Interrupt Masken Register laden und..
cbr ia,1<<PCIE ;..Pin Change Interruput 0 Freigabebit loeschen..
out GIMSK,ia ;..INT0 Interrupt sperren
cbr flag_reg,1<<pdm ;Power-Down-Mode sperren
;
;INT0 Interrupt initialisieren
;
in ia,MCUCR ;MCU Control Register laden..
sbr ia,1<<ISC01|1<<ISC00 ;..INT0 Interrupt auf steigende Flanke einstellen..
out MCUCR,ia ;..und ausfuehren
in ia,GIMSK ;General Interrupt Mask Register laden..
sbr ia,1<<INT0 ;..INT0 Interrupt Freigabe vorbereiten und..
out GIMSK,ia ;..ausfuehren..
ldi ia,1<<INTF0 ;..jetzt noch dass INT0 Interrupt-Flag..
out GIFR,ia ;..loeschen
_exit_PCI0addr:
out SREG,s_sreg ;Statusregister wiederherstellen
reti ;Ruecksprung aus der PCI0-ISR
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
; Timer0 Overflow ISR ( Interrupt Service Routine )
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
_OVF0addr:
sbi LED_PORT,led.pla ;LED-PLA einschalten T E S T Z W E C K E ###########################
cbi LED_PORT,led.pla ;LED-PLA ausschalten T E S T Z W E C K E ###########################
in s_sreg,SREG ;CPU-Statusregister sichern
;
;CY800-Bits erfassen
;
sec ;High-Bit vorgeben
sbis INT0_PIN,cy800.data ;CY800 Signalpin = 1 ?..
clc ;..Nein -> Bit = 0 setzen
sbrc bytezeiger,0 ;Ist dass Bit von Byte0 drann?..
rjmp _byte0 ;..JA -> dann dorthin springen
sbrc bytezeiger,1 ;Ist dass Bit von Byte1 drann?..
rjmp _byte1 ;..JA -> dann dorthin springen
rol byte_2 ;Carry-Flag und weitere Bits links rotieren..
rjmp _bitzlr ;..und Bitzaehler verringern
_byte0:
rol byte_0 ;Carry-Flag und weitere Bits links rotieren..
rjmp _bitzlr ;..und Bitzaehler verringern
_byte1:
rol byte_1 ;Carry-Flag und weitere Bits links rotieren
_bitzlr:
dec bit_zlr ;Bitzaehler um eins verringern
brne _systemtakt ;8-Bits erfasst?..
ldi bit_zlr,#bit_zlr ;..JA -> Bitzaehler neu setzen
;
;Alle 24 CY800-Bits erfasst?
;
lsr bytezeiger ;Naechstes Byte auswaehlen..
tst bytezeiger ;..Alle 24 CY800-Bits erfasst ( 3x8 Bits )?..
breq _bits_erfasst ;..JA -> Dekodieren in Main veranlassen
rjmp _pla ;ProgrammLaufAnzeige-LED ( PLA-LED ) bearbeiten
;
;Timer/Counter0 Overflow Interrupt sperren
;
_bits_erfasst:
in ia,TIMSK0 ;Timer/Counter0 Mask Register laden und..
cbr ia,1<<TOIE0 ;..Timer/Counter0 Overflow Interrupt..
out TIMSK0,ia ;...sperren
;
;CY800-Paket fertig FLAG setzen ( Vergleich in _main: veranlassen )
;
sbr flag_reg,1<<fertig ;CY800-Paket ( 24-Bits ) erfasst
;
;Systemtakt ( 4,8MHz ) durch 16 teilen ( 300kHz = 3,333µs )
;
_systemtakt:
cli ;Alle globalen Interrupts sperren
in ia,CLKPR ;Clock Prescaler Register laden..
sbr ia,1<<CLKPCE ;..Sicherheitsprozedur..
cbr ia,1<CLKPS3|1<<CLKPS2|1<<CLKPS1|1<<CLKPS0;..
out CLKPR,ia ;..durchfuehren..
in ia,CLKPR ;Clock Prescaler Register laden..
cbr ia,1<<CLKPCE ;..jetzt den Teiler..
sbr ia,1<<CLKPS2 ;..neu einstellen..
out CLKPR,ia ;..und ueberschreiben
sei ;Alle globalen Interrupts wieder freigeben
;
;ProgrammLaufAnzeige-LED ( PLA-LED ) bearbeiten
;
_pla:
sbrs flag_reg,pla.flg ;PLA-Flag in der Mainschleife quitiert?...
rjmp _exit_OVF0addr ;...Nein => ISR verlassen -> Kein blinken
;inc ovf0_zlr ;Overflowzaehler inkrementieren...
;sbrs ovf0_zlr,#ovf0_zlr ;...bis Bitposition X gezaehlt...
;rjmp _exit_OVF0addr ;...Nein => ISR verlassen
;clr ovf0_zlr ;Overflowzaehler ruecksetzen
;sbi PIN_PLA,led.pla ;PLA-LED toggeln bzw. blinken erzeugen
;
;Timer0 Overflow ISR verlassen
;
_exit_OVF0addr: ;Timer0 Overflow ISR verlassen
cbr flag_reg,1<<pla.flg ;Programmlaufanzeige-Flag quitieren
out SREG,s_sreg ;Statusregister wiederherstellen
reti ;Ruecksprung aus der Interrupt Service Routine
Wer sich mit dem ATMEL Studio 7 auskennt, kann dass ZIP-Projekt im Anhang dort öffnen. Geht leider doch nicht :
34946
Bernd_Stein
Bernd_Stein
18.04.2020, 12:44
Da es sicherlich für die aller, aller Meisten sehr schwer zu durchschauen ist, was im Code passiert, habe ich mal hier den überwiegenden Teil der Programmablaufpläne ( PAP ) hinterlegt.
Dort wieder einfach mit Linksklick auf das xyz.jpg klicken, wenn das Pfeil-Symbol in ein Hand-Symbol umschaltet :
https://www.edv-dompteur.de/forum/index.php?page=Thread&postID=4026#post4026
Ich kann diesen kostenlosen PAP-Designer, gerade bei der Assemblerprogrammierung, nur empfehlen :
https://www.heise.de/download/product/papdesigner-51889
Wer ihn schon hat -> siehe Anhang. Oder doch wieder einmal nicht -> Ungültige => Datei CY800.pap
Bernd_Stein
avr_racer
19.04.2020, 09:48
So mal ein AUSZUG aus der INC des TINY13A
; ***** INTERRUPT VECTORS ************************************************
.equ INT0addr = 0x0001 ; External Interrupt 0
.equ PCI0addr = 0x0002 ; External Interrupt Request 0
.equ OVF0addr = 0x0003 ; Timer/Counter0 Overflow
.equ ERDYaddr = 0x0004 ; EEPROM Ready
.equ ACIaddr = 0x0005 ; Analog Comparator
.equ OC0Aaddr = 0x0006 ; Timer/Counter Compare Match A
.equ OC0Baddr = 0x0007 ; Timer/Counter Compare Match B
.equ WDTaddr = 0x0008 ; Watchdog Time-out
.equ ADCCaddr = 0x0009 ; ADC Conversion Complete
.equ INT_VECTORS_SIZE = 10 ; size in words
#endif /* _TN13ADEF_INC_ */
; ***** END OF FILE ************************************************** ****
Also nochmal meinen ersten POST LESEN UND VERSTEHEN was die INT_VECTORS_SIZE aussagt nur das es 10 Vectoren gibt nicht mehr und nicht weniger.
Simuliert im AS 4.19 und was passiert er fängt das Programm direkt von vorn an abzuarbeiten wenn man auf PB0 den INT0 auslöst, weil der Sprungverweis per RJMP zur ISR fehlt, weil du meinst
so ein BOCKMIST zu machen
.CSEG ;Was ab hier folgt kommt in den FLASH-Speicher
.ORG $0000 ;Programm beginnt an der FLASH-Adresse 0x0000..
rjmp reset ;..mit der RESET-Vectortabelle
.ORG INT_VECTORS_SIZE ;Programmadresse nach den ganzen IRQ-Vektoren
Hausaufgabe 1
Setze die Sprungmarken für die ISR richtig das die ISR's auch angesprungen werden können!
Hausaufgabe 2
Lerne den Unterschied zwischen Spaghetticode und das arbeiten mit Unterprogrammen(UP) kennen und nutze den Vorteil von UP's die mit dem StackPointer arbeiten.
Hausaufgabe 3
Wenn du UP's verstanden hast, fange an dein Gesamtprogramm strukturiert mit UP's aufzubauen. Es gibt Pogrammteile die du immer wiederbrauchst und nur 1 mal schreiben musst z.B. die SleepRoutine.
Bernd_Stein
19.04.2020, 15:42
Also nochmal meinen ersten POST LESEN UND VERSTEHEN was die INT_VECTORS_SIZE aussagt nur das es 10 Vectoren gibt nicht mehr und nicht weniger.
Simuliert im AS 4.19 und was passiert er fängt das Programm direkt von vorn an abzuarbeiten wenn man auf PB0 den INT0 auslöst, weil der Sprungverweis per RJMP zur ISR fehlt, weil du meinst
so ein BOCKMIST zu machen
.CSEG ;Was ab hier folgt kommt in den FLASH-Speicher
.ORG $0000 ;Programm beginnt an der FLASH-Adresse 0x0000..
rjmp reset ;..mit der RESET-Vectortabelle
.ORG INT_VECTORS_SIZE ;Programmadresse nach den ganzen IRQ-Vektoren
Hausaufgabe 1
Setze die Sprungmarken für die ISR richtig das die ISR's auch angesprungen werden können!
Hausaufgabe 2
Lerne den Unterschied zwischen Spaghetticode und das arbeiten mit Unterprogrammen(UP) kennen und nutze den Vorteil von UP's die mit dem StackPointer arbeiten.
Hausaufgabe 3
Wenn du UP's verstanden hast, fange an dein Gesamtprogramm strukturiert mit UP's aufzubauen. Es gibt Pogrammteile die du immer wiederbrauchst und nur 1 mal schreiben musst z.B. die SleepRoutine.
Versteh zwar nicht wie dies passieren konnte, dass die wesentliche ( .include "IRQt13.inc" ;Restliche Interrupt Vektortabelle ) fehlt !
In meinem Eröffnungspost ist dies auf jeden Fall mit drinn, deshalb denke ich dass Hausaufgabe 1 erledigt ist ;-)
https://www.roboternetz.de/community/threads/74753-ATtiny13A-Wo-kommt-der-eine-Takt-her?p=659203&viewfull=1#post659203
Zu HA2 :
UP's nutze ich meistens nur, wenn ein und die selbe Codesequenz öfters benutzt werden soll. Halte mich aber nicht sklavisch daran ( siehe Hauptprogrammschleife -> SLEEP deaktivieren ).
Ich finde, es ist halt eine Sache des Programmierstils, den ich wahrscheinlich nicht mehr verändern werde.
Zu HA3 :
Ich habe sie verstanden, aber ist halt nicht mein Stil. Um die Struktur besser zu erkennen, benutze ich lieber den PAP.
Verstehe einfach nicht, wieso ~186µs mehr entstehen ( 969 - 783 ~ 186µs bzw. ~76 Takte )?
Ich verstehe zwar immer noch nicht warum diese Diskrepanz entsteht und glaube auch nicht dass sich irgendjemand durch meinen " Spaghetticode " arbeiten wird, um der Ursache auf den Grund zu gehen.
Deswegen arbeite ich jetzt mal mit der OC0A-Interrupt. Dort kann man dann wenigstens mittels Änderung des TOP-Wertes ( OC0RA ) im CTC-Mode bestimmen, wann genau die OC0A-IRQ auftreten soll.
Falls es überhaupt jemandem aufgefallen ist, habe ich erstens - a in ia geändert und zweitens cli & sei weggelassen, da ich mich ja hier in einer ISR befinde, die nicht unterbrochen wird.
ISR.inc -> Interrupt Service Routinen ( ISR ) :
;
;Systemtakt ( 4,8MHz ) durch 8 teilen ( 600kHz = 1,666µs )
;
cli ;Alle globalen Interrupts sperren
in ia,CLKPR ;Clock Prescaler Register laden..
sbr ia,1<<CLKPCE ;..Sicherheitsprozedur..
cbr ia,1<CLKPS3|1<<CLKPS2|1<<CLKPS1|1<<CLKPS0;..
out CLKPR,ia ;..durchfuehren..
in a,CLKPR ;Clock Prescaler Register laden..
cbr ia,1<<CLKPCE ;..jetzt den Teiler..
sbr ia,1<<CLKPS1|1<<CLKPS0 ;..neu einstellen..
out CLKPR,ia ;..und ueberschreiben
sei ;Alle globalen Interrupts wieder freigeben
Bernd_Stein
- - - Aktualisiert - - -
Ach, mal wieder was zum Simulator im Atmel Studio 7 ( AS7 ).
Ich bin ja leider ein wenig Lernresistent bei den Befehlen CBR & SBR und dann kommt noch dieser Simulator hinzu und schon ist die Verwirrung perfekt.
Beim SFR-CLKPR und noch so anderen SFR's sollte ich mir abgewöhnen RMW ( Read Modify Write ) per CBR & SBR zu realisieren, denn damit verarsche ich mich regelmäßig selbst.
Siehe hier :
https://www.edv-dompteur.de/forum/index.php?page=Thread&postID=4034#post4034
Bernd_Stein
Searcher
19.04.2020, 19:22
Um ein detailreicheres Bild sehen zu können, bitte hier kurz reinschauen :
https://www.mikrocontroller.net/topic/487338#6099487
(https://www.mikrocontroller.net/topic/487338#6099487)
Im unteren Link ist zu sehen, dass nach der steigenden Flanke am INT0-Pin ( Hier durch IN/Data repräsentiert ) , dass Signal erst nach 969,333µs eingelesen werden würde ( LED-PLA = High ).
LED-Gelb High zeigt den Zeitpunkt, wo der Code in der INT0-ISR ausgeführt wird und LED-Gelb Low, dass Ende dieser ISR.
Ich würde Dir ja gerne helfen. Finde mich aber überhaupt nicht mehr durch Deine Angaben. Wo ist zB der untere Link? Du verweist in diesem thread zu Deinen eigenen Infos in mindestens zwei weiteren Foren in dessen threads auch noch weiterführende Links existieren. Hast Du schon mal ein zusammenhängendes Programm gepostet?
Und überhaupt: Das ursprüngliche Topic wo denn der eine Takt herkommt ist doch schon geklärt?
Zum "Funksteckdosen-Protokoll auswerten ( CY800 -> HESUNSE )" solltest Du einen neuen thread aufmachen in dem alle Infos zu dem zu spät eingelesenen Signal existieren. Ich blicke in diesem thread jedenfalls nicht mehr durch.
Gruß
Searcher
avr_racer
19.04.2020, 20:14
Verstehe einfach nicht, wieso ~186µs mehr entstehen ( 969 - 783 ~ 186µs bzw. ~76 Takte )?
[/SIZE]
Ich verstehe zwar immer noch nicht warum diese Diskrepanz entsteht und glaube auch nicht dass sich irgendjemand durch meinen " Spaghetticode " arbeiten wird, um der Ursache auf den Grund zu gehen.
Deswegen arbeite ich jetzt mal mit der OC0A-Interrupt. Dort kann man dann wenigstens mittels Änderung des TOP-Wertes ( OC0RA ) im CTC-Mode bestimmen, wann genau die OC0A-IRQ auftreten soll.
Das was du in PAP beschreibst ist rein der Programmablauf wie dieser umgesetzt wird und mit welchen Befehlen, ist jedem natürlich selbst überlassen.
Wenn du aber möchtest das wir dir helfen dann geht es nur über eine annehmbare Programmstruktur. Dies beginnt schon nur damit das man nicht sinnlos alles in irgendwelche INC packt was absolut nicht notwendig ist Beispiel folgt.
Die Zeit wird auch mit dem OC-Int bleiben!!! Weil nicht verstanden wurde die Programmteile strukturiert zu erstellen um diese einzelnd prüfen zu können. Nur so wirst du den Fehler finden.
Jetzt zum Beispiel welches vereinfacht deine Stil dastellt.
.CSEG ;Was ab hier folgt kommt in den FLASH-Speicher
.ORG $0000 ;Programm beginnt an der FLASH-Adresse 0x0000..
rjmp reset ;..mit der RESET-Vectortabelle
.include IRQt13.inc
.ORG INT_VECTORS_SIZE ;Programmadresse nach den ganzen IRQ-Vektor
Sinvoller so
.CSEG ;Was ab hier folgt kommt in den FLASH-Speicher
.ORG $0000 ;Programm beginnt an der FLASH-Adresse 0x0000..
rjmp reset ;..mit der RESET-Vectortabelle
.ORG $0001
rjmp IRQ_? ;Sprung zu
.ORG $0002
rjmp IRQ_?? ;Sprung zu
.ORG $0003
reti ;zur Sicherheit RETI falls INT für $0003 doch ausgelöst wird ist keine ISR vorhanden aber
;der STACK wird nicht zerschoßen bzw falsche Ausführung von unerwünschten Programm
oder so
.CSEG ;Was ab hier folgt kommt in den FLASH-Speicher
.ORG $0000 ;Programm beginnt an der FLASH-Adresse 0x0000..
rjmp reset ;..mit der RESET-Vectortabelle
INT0addr
PCI0addr
OVF0addr
ERDYaddr
ACIaddr
OC0Aaddr
OC0Baddr
WDTaddr
ADCCaddr
Die ISR-Routinen selbst KÖNNEN natürlich in einer separaten INC stehen.
Somit erkennt jeder das die ISR sauber eingetragen sind und vorallem welche. Alles auf den ersten Blick erkennbar.
Bernd_Stein
27.04.2020, 17:07
Ich würde Dir ja gerne helfen. Finde mich aber überhaupt nicht mehr durch Deine Angaben. Wo ist zB der untere Link? Du verweist in diesem thread zu Deinen eigenen Infos in mindestens zwei weiteren Foren in dessen threads auch noch weiterführende Links existieren. Hast Du schon mal ein zusammenhängendes Programm gepostet?
Und überhaupt: Das ursprüngliche Topic wo denn der eine Takt herkommt ist doch schon geklärt?
Zum "Funksteckdosen-Protokoll auswerten ( CY800 -> HESUNSE )" solltest Du einen neuen thread aufmachen in dem alle Infos zu dem zu spät eingelesenen Signal existieren. Ich blicke in diesem thread jedenfalls nicht mehr durch.
Gruß
Searcher
Mann, mann, wie die Zeit vergeht.
Ja hier ist mal der komplette Code von mir gepostet worden :
Ist aber jetzt Obsolete, weil ich mich doch für einen etwas anderen Ansatz entschieden habe.
https://www.roboternetz.de/community/threads/74753-ATtiny13A-Wo-kommt-der-eine-Takt-her/page3?p=659423&viewfull=1#post659423
Ja, hast recht, werde ich tun. Werde dann auch hier dorthin verlinken.
Die Zeit wird auch mit dem OC-Int bleiben!!! Weil nicht verstanden wurde die Programmteile strukturiert zu erstellen um diese einzelnd prüfen zu können. Nur so wirst du den Fehler finden.
Stimmt. Hätte auch weiter mit dem Timer0 Overflow IRQ arbeiten können und dementsprechend dass Timer/Counter0 Register ( TCNT0 ) mit dem gewünschten Wert vorladen können.
Stimmt auch, ich blicke da nur sehr schwer durch und ohne die PAP's wäre es mir unmöglich überhaupt nur einen teilweisen Durchblick zu erhalten.
Wollte mich nur mal wieder melden, bleibe am Ball und werde wieder posten, wenn ich meine es besser präsentieren zu können, damit ihr auch die Chance habt da durchzublicken.
Bernd_Stein
Bernd_Stein
03.05.2020, 17:04
So, hiermit dürfte das Thema erledigt sein, was zum Nächsten führt :-) :
https://www.roboternetz.de/community/threads/74837-ATtiny13A-HESUNSE-%28CY800%29-Funksteckdosenprotokoll-auswerten?p=659655&viewfull=1#post659655
Bernd_Stein
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.