Light to frequency

Allerdings spukt mir noch'ne ganz elegante Geschichte im Kopf rum:
-Man lasse den Zeit-Zähler seinen Output-Compare-Pin toggeln (bzwim PWM setzen/löschen), und verbinde diesen Pin mit dem IC-Pin von Timer1.
-Timer1 zählt wie gehabt die Frequenz (also die Perioden).
-die entsprechende Flanke am IC-Pin bewirkt automatisch, daß TCNT1 ins ICR kopiert wird. (Da steht dann also die Anzahl der Perioden pro 8bit-Timerüberlauf - bisher alles in Hardware im Hintergrund)
-das IC-Event kann einen IRQ triggern, in dessen ISR muß möglichst schnell TCNT1 zurückgesetzt werden (Reihenfolge!), und dann das ICR ausgelesen werden (was allerdings Zeit bis zum nächsten 8bit-Timerüberlauf hat). (Oder kann man Timer1 mit CTC mit ICR als TOP UND ICR durch den entsprechenden Pin gleichzeitig ... hmm... grübel)
Edit:
Das Kauderwelsch da oben soll heissen: Kann ich einen Flankenwechsel/steigende/fallende Flanke am InputCapturePin GLEICHZEITIG zum :
-Clear Timer (CTC)
-(vorheriges) abspeichern des TCNT im ICR
-Generierung eines IRQ
verwenden, bis auf die ISR alles in Hardware, versteht sich?

Das hört sich spannend an! Allerdings überschaue ich das noch nicht, Da muß ich noch ein bischen studieren. Ich komm später darauf zurück!
 
Und noch'n Edit: erstelle erstmal einen Programmablaufplan (und schreibe den hier).
Von der TSL-Routine oder dem ganzen Programm?
Trotzdem ein paar Sachen:
-Den Stackpointer mußt Du nicht reinitialisieren (stört aber auch nicht weiter, nur ein paar Takte und Words)
Mir ist auch schon aufgefallen, daß der schon entsprechend initialisiert ist, zumindest im Debugger des Studios. Die Resetroutine wird ja aber unter Umständen in anderen Situationen (außer Start up) angesprungen. Ob für solche Fälle die Initialisierung wichtig ist, habe ich noch nicht herausgefunden.
-bei unbenutzten Interruptvektoren ist Schnurz, was drinnsteht, da dieser Code in einem korrekten Programm nie ausgeführt wird, es sei denn man bringt da sinnigen Code unter - ja, ich weiß - da scheiden sich die Geister... (in einer Offiziellen AppNote von Atmel wird übrigens eine ISR direkt an den Interruptvektor geschrieben - ohne Sprungbefehl und über die anderen Vektoren hinweg. geht natürlich nur, wenn man diese nicht braucht. Hab ich auch schon so gemacht...
-zumindest innerhalb der ISRs/Prozeduren kannst Du statt JMP RJMP nehmen.
Ist schon klar. Wenn ich mal Platzprobleme kriege kann ich dort noch was rausschinden.
 
Hi und guten Morgen
Ich hoffe, ich kann was beitragen, denn wenn ich die Augen schon richtig auf hab, sehe ich einen kleinen. aber gravierenden Fehler...

aber dann folgt ein RCALL in ein Unterprogramm..... warum nicht
doch nach dem Rücksprung sehe ich nur
Code:
Doit:
JMP Doit

Ist nicht viel, was dann getan wird. In der ISR kann ich auch nicht erkennen, das dort was passiert, was den neugierigen User vor der Kiste interessieren könnte.
Vielleicht ist es ja auch Absicht, den Programmcode zu verbergen.
Es ist noch so verdammt früh.....
Gruß oldmax

oldmax: Danke, daß Du da drauf geschaut hast. Aber ich bin einfach noch nicht weiter. Nach dem Unterprogrammaufruf geht's später noch weiter. Multiplikation mit 75 und übertragen des Ergebnisses an den PC per RS232.

Das ganze ist eigentlich nur ein Testprogramm für den Sensor. Wahrscheinlich werde ich das dann noch um einen Taster erweitern und das ganze Tastendruckabhängig in die Hauptschleife nehmen.

Kannst Du noch was zu meinen Fragen sagen?
 
Hallo,

Trotzdem ein paar Sachen:
-Den Stackpointer mußt Du nicht reinitialisieren (stört aber auch nicht weiter, nur ein paar Takte und Words)
Mir ist auch schon aufgefallen, daß der schon entsprechend initialisiert ist, zumindest im Debugger des Studios. Die Resetroutine wird ja aber unter Umständen in anderen Situationen (außer Start up) angesprungen. Ob für solche Fälle die Initialisierung wichtig ist, habe ich noch nicht herausgefunden.
ich hab mir angewöhnt den SP, die Register und IOs selber zu initialisieren. Wenn es der Controller beim Reset macht ... OK. Aber die paar Bytes machen den Kohl nicht fett. Mach es selber dann weißt du das genau das richtige drinsteht ;)

Gruß
Dino
 
Hier die zweite Version:
Code:
.INCLUDE "m168def.inc"

.EQU	Fcpu		= 19660800    

.DEF	Freq3		= R19
.DEF	FreqH		= R18
.DEF	FreqL		= R17
.DEF	Temp		= R16

.CSEG
.ORG	0

	jmp	Reset	; External pin, power-on reset, brown-out reset and watchdog system reset
	reti	;jmp	Int0	; External interrupt request 0
	reti	;jmp	Int1	; External interrupt request 1
	reti	;jmp	PCInt0	; Pin change interrupt request 0
	reti	;jmp	PCInt1	; Pin change interrupt request 1
	reti	;jmp	PCInt1	; Pin change interrupt request 2
	reti	;jmp	Wdt	; Watchdog time-out interrupt
	reti	;jmp	T2cmpA	; Timer/Counter2 compare match A
	reti	;jmp	T2cmpB	; Timer/Counter2 compare match B
	jmp	T2ovfl	; Timer/Counter2 overflow
	reti	;jmp	T1capt	; Timer/Counter1 capture event
	reti	;jmp	T1cmpA	; Timer/Counter1 compare match A
	reti	;jmp	T1cmpB	; Timer/Counter1 compare match B
	reti	;jmp	T1ovfl	; Timer/Counter1 overflow
	reti	;jmp	T0cmpA	; Timer/Counter0 compare match A
	reti	;jmp	T0cmpB	; Timer/Counter0 compare match B
	reti	;jmp	T0ovfl	; Timer/Counter0 overflow
	reti	;jmp	SPI	; serial transfer complete
	reti	;jmp	RxUsart	; USART, Rx complete
	reti	;jmp	UdreUsart	; USART, data register empty
	reti	;jmp	TxUsart	; USART, Tx complete
	reti	;jmp	Adc	; ADC conversion complete
	reti	;jmp	Eeprom	; EEPROM ready
	reti	;jmp	Acomp	; Analog comparator
	reti	;jmp	TWI	; 2-wire serial interface
	reti	;jmp	SPM	; Store program memory ready

Reset:
    	ldi	Temp, HIGH(RAMEND)	; Stack initialisieren
	out	SPH, Temp
	ldi	Temp, LOW(RAMEND)
	out	SPL, Temp

; DDRD PD5 auf Input
; Pullups?

	ldi	Temp, 1<<TOIE2			; enable timer2 interrupt
	sts	TIMSK2, Temp
	sei

	rcall	GetLightFreq

	lds	FreqL, TCNT1L				; Zähler sichern
	lds	FreqH, TCNT1H

	ldi	Temp, 75				; *75
	mul	FreqH, Temp
	movw	FreqH, R0

	mul	FreqL, Temp
	mov	FreqL, R0
	add	FreqH, R1
	clr	R0
	adc	Freq3, R0				; Ergebnis in Freq3/H/L


			
; Ergenis steht jetzt in: Freq3:FreqH:FreqL


Doit:
	jmp	Doit

GetLightFreq:
	clr	Temp					; Timer 1 löschen
	sts	TCNT1H, Temp
	sts	TCNT1L, Temp
	sts	TCNT2, Temp				; Timer 2 löschen
	ldi	Temp, 1<<CS12 | 1<<CS11 | 1<<CS10	; T1=PD5 steigende Flanke
	sts	TCCR1B, Temp
	ldi	Temp, 1<<CS22 | 1<<CS20		; Vorteiler 1024
	sts	TCCR2B, Temp
	set
WaitTSL:
	brts	WaitTSL
	clr	Temp					; beide Timer ausschalten
	sts	TCCR1B, Temp
	sts	TCCR2B, Temp
	ret

T2ovfl:
	clt
	reti

Ich habe mich noch nicht dazu durchringen können, Timer2 durchlaufen zu lassen.:)
 
ICH reinitialisiere den SP nicht, wenn es nicht nötig ist; ICH reinitialisiere auch andere I/Os nicht, wenn der Wert bereits default ist, ABER vermerke diesen als Kommentar im Quelltext. Ich will hier auch niemanden dazu "bekehren" - man liest nur in diversen Tutorials daß das (SP initialisieren, alle nicht verwendeten IntVektoren mit Reti abschließen etc) gemacht werden muß. Muß es aber nicht. Man muß sicherstellen, daß der SP sinnig initialisiert ist, bevor man ihn verwenden will. Wenn das bei einem konkreten µC bereits während des Reset automatisch erledigt wird, kann man das auch nutzen. Man sollte das Datenblatt lesen, und mitdenken, und nicht nur blind irgendwelche Formalismen anwenden... sorry, aber das ist nur meine Meinung - kann ja jeder so machen, wie er es will...
egal, will hier keinen Glaubenskrieg lostreten - nur darauf hinweisen...
aber btt:
Dein Programm (nochmals) kurzgefaßt:
-verwendete Register benannt
-Interruptvektoren
-Stackpointer
-Timer2-Überlaufinterrupt und globale Ints scharf
-Sprung in die Subroutine
-- dort beide Zähler auf 0
--beide gestartet (T1 als counter, T2 als Timer mit Presc 1024) - (Zeitdifferenz zwischen beiden Starts)
-- T-Flag gesetzt
--Warteschleife bis T=0 (**)
--dann beide Timer gestoppt
--rückkehr aus der Subroutine
-Auslesen des 16bit-Zählers
-Verrechnung/Ablegen des Ergebnisses
-Endlosschleife

(**)Währenddessen im Hintergrund:
-Timer2 läuft mit Systemtakt/1024 bis zum Überlauf (und darüber hinaus, aber Du stoppst ihn ja später).
-beim Überlauf wird das TOV2-Flag in TIFR2 gesetzt, welches den freigegebenen Überlaufsinterrupt triggert
-dieses Flag wird durch die Ausführung der ISR automatisch wieder gelöscht
-in der ISR setzt Du jetzt stattdessen das T-Flag (um es in der Subroutine zu pollen)

Du könntest also genauso gut auf das Scharfschalten des Überlaufsinterruptes verzichten (und auf die ISR), und in der Subroutine statt des T-Flags das TOV2 selbst pollen (und dann statt des T-Flags das TOV2 löschen - Achtung: durch Schreiben einer 1).

Und noch ein Hinweis zur Berechnung: Du zählst ja die Perioden innerhalb von ca 13ms. Auf 10ms wirst Du den 8bit-Timer sicher nicht bekommen (CTC), aber vielleicht ausreichend dicht ran? Dann würden im 16bit-Zähler quasi direkt zehntel Kilohertz (oder hab ich mich da jetzt vertan?) stehen - das Komma mußt Du dann bei der Ausgabe nur noch dazwischenmogeln.
 
-beim Überlauf wird das TOV2-Flag in TIFR2 gesetzt, welches den freigegebenen Überlaufsinterrupt triggert
-dieses Flag wird durch die Ausführung der ISR automatisch wieder gelöscht
-in der ISR setzt Du jetzt stattdessen das T-Flag (um es in der Subroutine zu pollen)

Du könntest also genauso gut auf das Scharfschalten des Überlaufsinterruptes verzichten (und auf die ISR), und in der Subroutine statt des T-Flags das TOV2 selbst pollen (und dann statt des T-Flags das TOV2 löschen - Achtung: durch Schreiben einer 1).

Das hört sich plausibel an!

Und noch ein Hinweis zur Berechnung: Du zählst ja die Perioden innerhalb von ca 13ms. Auf 10ms wirst Du den 8bit-Timer sicher nicht bekommen (CTC), aber vielleicht ausreichend dicht ran? Dann würden im 16bit-Zähler quasi direkt zehntel Kilohertz (oder hab ich mich da jetzt vertan?) stehen - das Komma mußt Du dann bei der Ausgabe nur noch dazwischenmogeln.

Ich will den Quarz nicht wechseln. Maximal könnte ich einen 20MHz Quarz nehmen, der bringt mir mit einem Vorteiler von 1024 13,1072 ms. Mit meinem Baudratenquarz komme ich exakt auf 1/75 s und habe die Vorteile einer fehlerfreien Baudratenteilung.
 
--beide gestartet (T1 als counter, T2 als Timer mit Presc 1024) - (Zeitdifferenz zwischen beiden Starts)
Siehst Du einen Weg diese Differenz zu beseitigen? Ich meine abgesehen von Deinem spannenden Vorschlag, an dem ich noch herumlaboriere.
 
Das hört sich spannend an! Allerdings überschaue ich das noch nicht, Da muß ich noch ein bischen studieren. Ich komm später darauf zurück!

Mit sowas ist der Simulator sicher am Ende, oder? Immerhin wird mir so langsam klar, von was Du da sprichst.
 
...Ich will den Quarz nicht wechseln. Maximal könnte ich einen 20MHz Quarz nehmen, der bringt mir mit einem Vorteiler von 1024 13,1072 ms. Mit meinem Baudratenquarz komme ich exakt auf 1/75 s und habe die Vorteile einer fehlerfreien Baudratenteilung.
Laß den mal ruhig drin, rechnet sich zwr manchmal etwas holperig, aber genau genommen ist der sogar besser für Dich. Wenn ich das richtig überschlagen habe würdest Du mit mit einem 8bit-Timer mit Prescaler 1024 im CTC (Überlauf bei 192) auf exact 10ms kommen - klar: 256*0.75.
 
Laß den mal ruhig drin, rechnet sich zwr manchmal etwas holperig, aber genau genommen ist der sogar besser für Dich. Wenn ich das richtig überschlagen habe würdest Du mit mit einem 8bit-Timer mit Prescaler 1024 im CTC (Überlauf bei 192) auf exact 10ms kommen - klar: 256*0.75.
Das sehe ich auch so, aber dann wird mir mein Messintervall noch kleiner!:(
Ich möchte die 16Bit möglichst ausnutzen!
Ich werde sehr wahrscheinlich am oberen Rand der Kennlinie herumlaborieren. Ich weiß nicht bis zu welcher Frequenz der Sensor geht. Das Datenblatt erreicht 1MHz nicht mehr. Wenn ich dennoch 1MHz mit einem Zählerstand von 2^16-1 assoziiere, dann bräuchte ich ein Messintervall von 65ms. Die nächste schöne Zahl wäre 50ms. Oder was ich auch schon überlegt habe sind 40ms (256*3). Aber das eine, wie das andere erfordert einen zusätzlichen Zähler.
 
Habe gerade eine spannende Fehlersuchorgie hinter mir.

(Vorteiler auf 1)

Effekt war: Bei Timer2 Overflow wurde der Interruptvektor für Timer0 !!! angesprungen!

Habe deshalb zu Testzwecken Timer2 durch Timer0 ersetzt, um zu sehen wohin mich ein Overflow dann führt. Allerdings wurde jetzt
Code:
    	ldi	temp1, 1<<CS00			; Vorteiler 1
	sts	TCCR0B, temp1
nicht mehr ausgeführt. D.h. temp1 wurde noch geladen, aber sts hatte keinen Effekt!

Habe dann die Bits im Simulator manuel gesetzt und bin nach einem Overflow direkt nach meiner SP-Initialisierung gelanded.

Lösung:

1. Die reti Befehle sind 1 Byte Befehle und müssen in der Interruptvektortabelle mit je einem nop aligned werden.
2. Bei Timer0 funktioniert sts nicht
Code:
    	ldi	temp1, 1<<CS00			; Vorteiler 1
	out	TCCR0B, temp1

Ich wußte, daß out bei den höheren Registern nicht funktioniert. Daß sts bei den niederen nicht geht, war mir neu!
 
Hi,

Lösung:
1. Die reti Befehle sind 1 Byte Befehle und müssen in der Interruptvektortabelle mit je einem nop aligned werden.

kleine Falle ;)

Bei manchen CPUs fassen die Interruptvektoren zwei Befehlswörter und bei manchen nur ein Befehlswort :rolleyes:

Das mit den in/out und sts/lds für die Funktionsregister ist auch recht nett ;)

Ich wußte, daß für out bei den höheren Registern nicht funktioniert. Daß sts bei den niederen nicht geht, war mir neu!

sollte aber eigentlich gehen. Nur die Adressen sind gegenüber den In/Out-Adressen andere.

Memory_m48-88-168-328.png

Hier sieht man es genau ...

IO-Register-Addr.png

Die linke Angabe is die IO-Adresse und die in den Klammern die Speicheradresse.

Wenn du sts/lds mit den IO-Adressen verwendest dann wirst du mit etwas Glück in deinen normalen CPU-Register R00-R31 landen.

Gruß
Dino
 
Wenn du sts/lds mit den IO-Adressen verwendest dann wirst du mit etwas Glück in deinen normalen CPU-Register R00-R31 landen.

Tatsächlich! Nicht nur, daß es nicht funktioniert, es hat auch noch Nebenwirkungen!

Code:
	ldi	R22, 9
	sts	TIFR2, R22

Das ist also die komplizierte Variante für 'mov R23,R22'. Obergemein!!! :(
 
Das sehe ich auch so, aber dann wird mir mein Messintervall noch kleiner!:(
Ich möchte die 16Bit möglichst ausnutzen!
Ich werde sehr wahrscheinlich am oberen Rand der Kennlinie herumlaborieren. Ich weiß nicht bis zu welcher Frequenz der Sensor geht. Das Datenblatt erreicht 1MHz nicht mehr. Wenn ich dennoch 1MHz mit einem Zählerstand von 2^16-1 assoziiere, dann bräuchte ich ein Messintervall von 65ms. Die nächste schöne Zahl wäre 50ms. Oder was ich auch schon überlegt habe sind 40ms (256*3). Aber das eine, wie das andere erfordert einen zusätzlichen Zähler.
???
Das ist doch genau andersrum. Du zählst die Perioden (Flanken) innerhalb einer (durch den Timer) festgelegten Zeit. Je höher also die zu messende Frequenz, desto schneller wird der Counter. Dieser darf aber innerhalb der 8-bit-Timerzeit nicht überlaufen. Die Verkürzung der Meßzeit begrenzt Dich nicht oben, sondern bei den tiefen Frequenzen. Eine Periode pro 10ms entsprächen 100 Perioden pro 1000ms, also 100Hz. Weniger kannst Du (mit 10ms) nicht auflösen. Obergrenze wären theoretisch (Dino hat ja schonmal was zur max Frequenz am Timereingang geschrieben) 2^16 Perioden pro 10ms - also ca 6,6MHz. Für mehr mußte also entweder das Meßintervall weiter verkürzt werden, oder eben ein weiteres Byte für den Zähler (mehr als16bit).

Zu den unterschiedlichen Registeradressen...
ST/LD etc können beginnend mit den 32Rechenregistern, den I/Os (low/extended) bis in den SRAM hinein Register adressieren, erstmal nur 2Byte-viele, wenns mehr werden muß, gibt es auch RAMP-Register, die einen 3Byte Adressraum erlauben.
Die schnelleren Befehle IN/OUT "remappen" die Adressen. Sie können nur 6 Bit adressieren. Und für die Rechenregister gibts ja bereits andere potente Operationen.

Zum Interruptvektortabellenproblem:
Alle AVR die mehr als 4KByte Flash (also 2KWords Flash) haben, können mit RJMP nicht mehr den gesamten Flash anspringen, sondern müssen JMP nehmen. RJMP war ein 1Word-Befehl, deswegen hat bis dahin eine ein-Word breite Interruptvektortabelle genügt. JMP ist ein 2-Word-Befehl, also benötigen AVR mit großem Flash eine 2Word-breite INTTabelle, klar?
RETI ist aber auch ein ein-Word-Befehl.

Um sicher zu gehen verzichte ich auf den "Quatsch" mit den Retis in der Tabelle, und schreibe mittels ".org InterruptEinsprungAdresse" den Sprungbefehl an die richtige Adresse. Die jeweiligen InterrutEinsprungAdressen sind in der inkludierten Definitionsdatei definiert.

Edit zum ersten Punkt: Ok, hatte Dich wohl falsch verstanden - für mehr Genauigkeit (bzw kleinere Frequenzen) brauchst Du 'ne längere Meßzeit, richtig. Ich hab noch irgendwas im Kopf, wie man ein paar bits an einen Timerüberlauf koppeln konnte, in Hardware - ich komm nur grad nicht drauf...
 
???
Das ist doch genau andersrum. Du zählst die Perioden (Flanken) innerhalb einer (durch den Timer) festgelegten Zeit. Je höher also die zu messende Frequenz, desto schneller wird der Counter. Dieser darf aber innerhalb der (bit-Timerzeit nicht überlaufen. Die Verkürzung der Meßzeit begrenzt Dich nicht oben, sondern bei den tiefen Frequenzen. Eine Periode pro 10ms entsprächen 100 Perioden pro 1000ms, also 100Hz. Weniger kannst Du (mit 10ms) nicht auflösen. Obergrenze wären theoretisch (Dino hat ja schonmal was zur max Frequenz am Timereingang geschrieben) 2^16 Perioden pro 10ms - also ca 6,6MHz. Für mehr mußte also entweder das Meßintervall weiter verkürzt werden, oder eben ein weiteres Byte für den Zähler (mehr als16bit).

Mich interessieren die tiefen Frequenzen nicht. Ich sagte doch, daß ich im oberen Bereich messen will.
Rechne doch einfach mal nach, welchem Zählerstand ein 1MHz bzw. ein 200KHz Signal bei 10ms bzw. 50ms Meßdauer entspricht:

10ms: 1MHz (10000) 200KHz(2000) entspricht einer Auflösung von 100Hz/Bit
50ms: 1MHz(50000) 200kHz(10000) entspricht einer Auflösung von 20Hz/Bit also 5 mal so gut!!!
 
Mich interessieren die tiefen Frequenzen nicht. Ich sagte doch, daß ich im oberen Bereich messen will
...
50ms: 1MHz(50000) 200kHz(10000) entspricht einer Auflösung von 20Hz/Bit also 5 mal so gut!!!
Das sind doch aber grad die "kleinen Hertze", das meinte ich mit Genauigkeit.

Zum Edit da oben: Bei den Tinies mit USI kann man (wenn man den USI nicht wie vorgesehen nutzt) den 4-Bit-USI-Counter an einen 8-Bit-Timer/counter "anbinden". Dann incrementiert der USI-Counter bei jedem Überlauf des 8-Bitters. Fazit: 12-Bit-Timer. Du hast hier aber kein USI (hat mir nur keine Ruhe gelassen, WO ich das herhatte).
 
Das sind doch aber grad die "kleinen Hertze", das meinte ich mit Genauigkeit.
Also ich denke, ich werde 1/25s nehmen. Das sind 66 2/3 ms, also 5 volle Durchläufe. Sollte der Sensor wirklich 1MHz liefern können, dann reichen die 16Bit gerade nicht mehr, dafür werde ich ein Overflow-Bit setzen. Ich vermute, daß es in der Praxis aber doch reicht. Meine Auflösung beträgt dann 15Hz/Bit.
 
Um sicher zu gehen verzichte ich auf den "Quatsch" mit den Retis in der Tabelle, und schreibe mittels ".org InterruptEinsprungAdresse" den Sprungbefehl an die richtige Adresse. Die jeweiligen InterrutEinsprungAdressen sind in der inkludierten Definitionsdatei definiert.
Also mir hat die Tabelle mit den vielen retis einen guten Dienst erwiesen. Man konnte im Simulator schön sehen, daß der falsche Vektor angesprungen wurde. Das würde auch hilfreich sein, wenn man aus Versehen den falschen Int scharf gemacht hat. Ich hatte auch kurz überlegt, ob ich die retis nicht durch einen
Code:
jmp error
ersetze. Man könnte dort event. eine LED anzünden!? Ich werd's aber vorerst bleiben lassen.
 
Also ich denke, ich werde 1/25s nehmen. Das sind 66 2/3 ms, also 5 volle Durchläufe. Sollte der Sensor wirklich 1MHz liefern können, dann reichen die 16Bit gerade nicht mehr, dafür werde ich ein Overflow-Bit setzen. Ich vermute, daß es in der Praxis aber doch reicht. Meine Auflösung beträgt dann 15Hz/Bit.

5 8-Bit-Timerüberläufe:
-Du hast einen Hilfszähler, initialisiert mit 5
-in der TOV-ISR dekrementiest Du den Hilfszähler, und überspringst bei Z-Flag=0 (also mit BRNE) die folgenden Instruktionen
--16-Bit-Zähler auslesen/abspeichern und Zurücksetzen (inklusive eventuelles Overflow-Bit)
--Hilfszähler reinitialisieren
--ggf neues Messergebnis ans Hauptprogramm signalisieren (Du wolltest das T-Flag nehmen)
-BRNE-Einsprungpunkt=Reti
(Sichern und wiederherstellen verwendeter Register drumherum, klar...)

Overflow-Bit:
Das liefert Dir der Timer quasi selbst mit - das Timer/Counter Overflow Flag (TOVn). Es wird bei einem Timerüberlauf automatisch gesetzt (auch wenn der Interrupt selbst nicht scharf ist) - es wird beim Ausführen der entsprechenden ISR (und wenns auch nur Dein Reti ist) automatisch gelöscht (also in unserem Falle nicht, da IRQ nicht scharf). Du kannst es also irgendwann innerhalb des nächsten Überlaufes auslesen; um es zu löschen mußt Du eine 1 in das entsprechende Registerbit schreiben. (cave! üblicherweise sind in dem entsprechenden Interrupt-Flag-Register auch andere Interrupt-Flags (mit derselben Lösch-Mechanik), also kein Read-Modify-Write verwenden, klar?)

Interruptvektortabelle:
versehentlich aktivierte Interrupts finde ich nicht plausibel - vielleicht ist aber nur mir noch nicht passiert. Wenns nur eine falsche Adresse ist, würdest Du bei den ".orgs..." dann halt im Simulator auch auf den nächsten Befehl stoßen (ggf ein Sprung in eine andere ISR) - der Effekt ist also derselbe wie bei Dir.
Obwohl... ich bin mir jetzt nicht sicher, aber ich denke, daß alle Words im Flash beim Programmieren beschrieben werden. Wenn der Sourcecode keine Informationen dazu enthält, eben mit NOP. Ich kann mich aber auch irren.
Egal, wenn Du dabei bleiben willst, mach es so.

JMP error:
Meiner meinung wäre es sogar so möglich:
direkt in der Interruptvektortabelle:
1tes Word: CBI Portregister, Ledbit
2tes Word: Reti
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)