PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : ATtiny13A: HESUNSE (CY800) Funksteckdosenprotokoll auswerten



Bernd_Stein
03.05.2020, 16:58
Hallo zusammen,

dort ist dass Protokoll zu sehen, wenn die Taste A der Funk-Fernbedienung gedrückt wurde und wie es der vermeindliche CY800-Baustein dann am Data-Ausgang ausgibt.

Das 1te Bit lese ich nach 550µs ein und alle weiteren im Abstand von 1100µs.

Dort bitte auf die XYZ.jpg Datei klicken um den Screenshot zu sehen :

https://www.edv-dompteur.de/forum/index.php?page=Thread&postID=4113#post4113


Ich verstehe nicht warum die kontinuierlichen Abstände von 1100µs, Werte zwischen 1092µs und 1098µs annehmen, wenn doch jedes mal dass Gleiche passiert?

Nämlich aus dem IDLE-Mode per OC0A-IRQ geweckt werden, in die OC0A-ISR springen und danach wieder in den IDLE-Mode usw.

Hier mal der komplette Code. In der Header-Datei steht wie es funktioniert :

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 ( 14CK+64 )
;
;FUSE-BITS High = $FF ; Low = $39
;
;Am Pin 5 ( PCINT0 ) wird dass Signal des CY800 eingelesen ( Data )
;Am Pin 6 ( INT0 ) ueber ein retriggerbares Monoflop das Einlesen vorbereitet.
;
;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 Level-Interupt an INT0 erzeugt.
;In dieser INT0-ISR wird nun, unter anderem, die PCINT0-IRQ intialisiert, um den
;Beginn des Datenpaketes zu erfassen. INT0-IRQ wird danach wieder abgeschaltet.
;In der PCINT0-ISR wird unter anderem der Timer/Counter0 Compare Match A IRQ
;initialisiert (OC0A), welcher durch den CTC-Mode erzeugt wird, wo der OC0A-Pin
;als normaler Portpin betrieben wird bzw. als PCINT0-Eingang.
;Hiernach wird ebenfalls der PCINT0-IRQ abgeschaltet.
;In der OC0A-ISR wird dann nach 550µs dass erste Bit eingelesen und alle wei-
;teren 23 Bits mit 1100µs Abstand. In der Mainloop werden die drei eingelesen
;Bytes mit denen im Flash abgelegten ( Tastencode ) verglichen und bei Ueber-
;einstimmung zum Test die LED-ge eingeschaltet ( High-Pegel ).
;
;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 = r4 ;
;.DEF = r5 ;
.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 = r18 ;
.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 #bit_zlr = 24 ;Bitzaehler der empfangenen Bits
.EQU #vergleichs_zlr = 3 ;Die 3 Bytes x mal vergleichen
.EQU #ocr0a = 66 ;Fuer Timer0, CTC-Mode -> TOP-Wert > 58
.EQU #ocr0a_rest = 192 ;Fuer restlichen 23 Bits -> TOP-Wert > 58

;
;
;Bitbezeichner fuer das allgemeine Flaggenregister flag_reg
;
;.equ = 0 ;
;.equ = 1 ;
;.equ = 2 ;
.equ pdm = 3 ;Power-Down-Mode ist erwuenscht
;.equ = 4 ;
.equ fertig = 5 ;CY800 Paket ( 24-Bits ) erfasst
;.equ = 6 ;
;.equ = 7 ;
;


Hauptprogramm:


;
.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:
;
;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

rcall _loeschen ;Anfangsbedingungen herstelllen
;
;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

sbi LED_PORT,led.ora ;LED-Orange ausschalten
;
;Variablen initialisieren ( r0-r31 haben unbestimmten Inhalt )
;
clr flag_reg ;Allgemeines Flaggenregister;

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<<SE|1<<SM1|1<<SM0 ;..auf Werkseinstellung..
out MCUCR,a ;..setzen

sbrc flag_reg,fertig ;CY800-Paket erfasst?
rjmp _fertig ;..JA -> Paket vergleichen
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 ###########################
sbi PORTB,led.ora ;LED-Orange ausschalten T E S T Z W E C K E ###########################
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<<SE|1<<SM1 ;..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 ###########################
cbi PORTB,led.ora ;LED-Orange einschalten T E S T Z W E C K E ###########################
sbi PORTB,led.ora ;LED-Orange ausschalten T E S T Z W E C K E ###########################

in a,MCUCR ;MCU Control Register laden(IDLE ist vorgegeben)..
sbr a,1<<SE ;..Sleep Enable vorbereiten..
out MCUCR,a ;..und freigeben
sleep

rjmp _main ;Arbeitsschleife ausfuehren
;
;Der Code stimmt nicht
;
_gescheitert:

cbi LED_PORT,led.pla ;LED-PLA ausschalten T E S T Z W E C K E #############################
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 #############################
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 #############################

rcall _loeschen ;..Bytes sind ungleich, also alles von vorn

rjmp _main ;Arbeitsschleife ausfuehren

;
;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

rcall _loeschen ;Neubeginn einrichten

rjmp _main ;Arbeitsschleife ausfuehren
;
;Ausgang Umschalten
;
_umschalten:
sbi LED_PORT,led.pla ;LED-PLA einschalten T E S T Z W E C K E #############################

rcall _loeschen ;Neubeginn einrichten

rjmp _main ;Arbeitsschleife ausfuehren
;
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;U Beginn der verwendeten Unterprogramme
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;
.include "UP.inc";Unterprogramme
;
;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 )
;.DB $FC,$00,$00,00 ;3 Codebytes f. T E S T ( Byte2,Byte1,Byte0 )

.EXIT ;Ende des Quelltextes


Hardware:


;
;************************************************* ******************************
;* 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 = PB0 ;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 CY800_PIN = PINB ;CY800 Eingabeport

.EQU PIN_PLA = PINB ;Eingabeport wo die LED-ProgrammLaufAnzeige ist


IRQt13 ( Interrupt Vektortabelle ):



;
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV VVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
; Interruptvektortabelle des ATtiny13 Mikrocontrollers
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV VVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
; ***** INTERRUPT VECTORS ************************************************
rjmp _INT0addr ; External Interrupt 0
rjmp _PCI0addr ; External Interrupt Request 0
reti ;rjmp _OVF0addr ; Timer/Counter0 Overflow
reti ;rjmp _ERDYaddr ; EEPROM Ready
reti ;rjmp _ACIaddr ; Analog Comparator
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


UP's ( Unterprogramme ):


;
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;U Beginn der verwendeten Unterprogramme
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU UUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;
_loeschen:
;
;Systemtakt ( 4,8MHz ) durch 8 teilen ( 600kHz = 1,666µs )
;
ldi ia,1<<CLKPCE ;Im Clock Prescaler Register Bit..
out CLKPR,ia ;..Clock Prescaler Change Enable setzen..
ldi ia,1<<CLKPS1|1<<CLKPS0;..und CLKPS[3:0] loeschen (Sicherheitsprozedur)..
out CLKPR,ia ;..nun mit CLKPCE=0 und CLKPS[3:0] SYS-Takt aendern
;
;Die drei Bytes loeschen
;
clr byte_2 ;Die 3..
clr byte_1 ;..Bytes..
clr byte_0 ;..loeschen
;
;Bitzaehler einstellen
;
ldi a,#bit_zlr ;Wert f. Bitzaehler laden..
mov bit_zlr,a ;..und Bitzaehler einstellen
;
;Vergleichszaehler einstellen
;
ldi a,#vergleichs_zlr ;..Vergleichszaehler..
mov vergleichs_zlr,a ;..laden
;
;Codeadresse fuer Taste A laden
;
ldi zh,high(_code*2) ;Z-Zeiger mit Vergleichscode-Adresse..
ldi zl,low (_code*2) ;..laden
;
;Job-FLAGS bearbeiten
;
cbr flag_reg,1<<fertig ;CY800 Paket erfasst FLAG loeschen
sbr flag_reg,1<<pdm ;Power-Down-Mode FLAG setzen
;
;INT0 Low-Level-interrupt initialisieren
;
cli ;Global Interrupts sperren
ldi a,1<<INTF0 ;External Interrupt Flag 0 im..
out GIFR,a ;General Interrupt Flag Register loeschen
in a,GIMSK ;General Interrupt Mask Register laden..
sbr a,1<<INT0 ;..und External Interrupt Request 0 freigeben..
out GIMSK,a ;..zurueckschreiben
sei ;Globale Interruptfreigabe
;
;OCR0A fuer dass 1te Bit einstellen
;
ldi ia,#ocr0a ;Wert f. Timer0 CTC-Mode Compare Match A laden und..
out OCR0A,ia ;..ins Output Compare0 Match A Register schreiben

ret ;UP_loeschen verlassen


ISR ( Interrupt Service Programme ):


;
;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 #############################
cbi LED_PORT,led.ge ;LED-Gelb ausschalten T E S T Z W E C K E #############################

in s_sreg,SREG ;CPU-Statusregister sichern
;
;Pin Change Interrupt 0 -> PCI0 initialisieren
;
in ia,PCMSK ;Pin Change Mask Register laden und..
sbr ia,1<<PCINT0 ;..Pin Change Interrupt 0 auswaehlen
out PCMSK,ia ;..und Register ueberschreiben
in ia,GIMSK ;General Interrupt Masken Register laden und..
sbr ia,1<<PCIE ;..Pin Change Interruput 0 Freigabebit setzen..
out GIMSK,ia ;..INT0 Interrupt freigeben und..
ldi ia,1<<PCIF ;..Pin Change Interrupt Flag..
out GIFR,ia ;..loeschen
;
;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 16 teilen ( 300kHz = 3,333µs )
;
ldi a,1<<CLKPCE ;Im Clock Prescaler Register Bit..
out CLKPR,a ;..Clock Prescaler Change Enable setzen..
ldi a,1<<CLKPS2 ;..Sicherheitsprozedur nun mit CLKPCE=0 und
out CLKPR,a ;..CLKPS[3:0] SYS-Takt aendern, abschliessen

_exit_INT0addr:
out SREG,s_sreg ;Statusregister restaurieren

sbi LED_PORT,led.ge ;LED-Gelb einschalten T E S T Z W E C K E #############################
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:

sbi LED_PORT,led.ge ;LED-Gelb einschalten T E S T Z W E C K E #############################
cbi LED_PORT,led.ge ;LED-Gelb ausschalten T E S T Z W E C K E #############################
sbi LED_PORT,led.ge ;LED-Gelb einschalten T E S T Z W E C K E #############################
cbi LED_PORT,led.ge ;LED-Gelb ausschalten T E S T Z W E C K E #############################

in s_sreg,SREG ;CPU-Statusregister sichern
;
;Timer0 ruecksetzen
;
clr ia
out TCNT0,ia
;
;Timer/Counter0 im Waveform Generation Mode 2 -> CTC betreiben
;und Compare Match A interrupt initialisieren
;
in ia,TIMSK0 ;Timer/Counter0 Masken Register laden und..
sbr ia,1<<OCIE0A ;..T/C0 Output Compare Match A Interrupt enabeln..
out TIMSK0,ia ;..und dies zurueckschreiben
ldi ia,1<<OCF0A ;Output Compare Flag 0 A..
out TIFR0,ia ;..im T/C0 Interrupt Flag Register loeschen
in ia,TCCR0A ;Timer/Counter0 Control Register A laden..
sbr ia,1<<WGM01 ;..Waveform Generations Mode 2 ( CTC ) einstellen..
out TCCR0A,ia ;..und
in ia,TCCR0B ;Timer/Counter0 Control Register B laden..
sbr ia,1<<CS00 ;..Timer0 mit 1:1 Teiler einstellen..
out TCCR0B,ia ;..und starten
;
;PCINT0 Interrupt sperren
;
in ia,GIMSK ;General Interrupt Masken Register laden und..
cbr ia,1<<PCIE ;..Pin Change Interruput 0 Freigabebit loeschen..
out GIMSK,ia ;..INT0 Interrupt freigeben und..

cbr flag_reg,1<<pdm ;Power-Down-Mode sperren
_exit_PCI0addr:
out SREG,s_sreg ;Statusregister restaurieren

sbi LED_PORT,led.ge ;LED-Gelb einschalten T E S T Z W E C K E #############################
cbi LED_PORT,led.ge ;LED-Gelb ausschalten T E S T Z W E C K E #############################
sbi LED_PORT,led.ge ;LED-Gelb einschalten T E S T Z W E C K E #############################
cbi LED_PORT,led.ge ;LED-Gelb ausschalten T E S T Z W E C K E #############################

reti ;_PCI0addr ISR verlassen
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
; Timer/Counter0 Compare Match A ISR ( Interrupt Service Routine )
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ QQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
_OC0Aaddr:
in s_sreg,SREG ;CPU-Statusregister sichern

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 ##############################

;
;CY800-Bits erfassen
;
sec ;High-Bit vorgeben
sbis CY800_PIN,cy800.data ;CY800 Signalpin = 1 ?..
clc ;..Nein -> Bit = 0 setzen
;
;Bits zusammenfassen
;
rol byte_0 ;Carry-Bit und weitere Bits links rotieren..
rol byte_1 ;Carry-Bit und weitere Bits links rotieren
rol byte_2 ;Carry-Bit und weitere Bits links rotieren..
dec bit_zlr ;Bitzaehler um eins verringern
brne _pla ;Alle 24 Bits erfasst? NEIN -> springen..
;
;Timer/Counter0 Compare Match A Interrupt sperren
;
_bits_erfasst:
in ia,TIMSK0 ;Timer/Counter0 Mask Register laden und..
cbr ia,1<<OCIE0A ;..T/C0 Output Compare Match A Interrupt..
out TIMSK0,ia ;...sperren
;
;CY800-Paket fertig FLAG setzen ( Vergleich in _main: veranlassen )
;
sbr flag_reg,1<<fertig ;CY800-Paket ( 24-Bits ) erfasst
_pla:
;
;Wert fuer den Timer0 CTC-Mode Compare Match speichern ( restlichen 23 Bits )
;
ldi ia,#ocr0a_rest ;Wert f. Timer0 CTC-Mode Compare Match A laden und..
out OCR0A,ia ;..ins Output Compare0 Match A Register schreiben
;
;Timer0 ruecksetzen
;
clr ia
out TCNT0,ia

_exit_OC0Aaddr:
out SREG,s_sreg ;Statusregister restaurieren
reti ;_OC0Aaddr ISR verlassen



Bernd_Stein

Searcher
03.05.2020, 21:11
Das 1te Bit lese ich nach 550µs ein und alle weiteren im Abstand von 1100µs.

Hallo,

ich kann das Timing im Programm nicht nachvollziehen.

Im Unterprogramm _loeschen wird der 4,8MHz Systemtakt durch 8 geteilt und OCR0A mit 66 beschrieben.
Da der Timer mit prescaler 1:1 läuft, bedeutet das zu diesem Zeitpunkt ein Timer0 Comparematch nach 111µs wenn er bei 0 beginnt ( 4,8MHz/ 8 =600kHz. (1/600kHz)*(66+1) = 111µs )

In der INT0 ISR wird mit CLKPS2 der 4,8MHz Systemtakt durch 16 geteilt (SYSCLK=300kHz), daß dann ein Comparematch in Timer0 nach der doppelten Zeit, also nach 222µs auslösen würde.

In der PCINT ISR wird Timer0 im CTC gestartet aber OCR0A nicht neu gesetzt; Inhalt immer noch 66. Der erste Comparematch findet demnach nach 222µs statt, nicht nach 550µs!?

In der Comparematch A ISR wird dann 192 in das OCR0A geladen. Das macht bei 300kHz dann eine Zeit von (1/300kHz)*(192+1) = 643µs und keine 1100µs.

Kann auch sein, das ich den Faden durch die ganzen Umtaktungen verloren habe.


Abstände von 1100µs, Werte zwischen 1092µs und 1098µs annehmen
1. könnte der Systemtakt nicht 100%ig stimmen und
2. Wenn der µC mit 300kHz läuft, dauert ein Cycle 3,33µs. Bei Branch- oder Testbefehlen kommen da schnell 6µs Unterschiede je nach Ergebnis zustande. Müßte man aber nochmal genauer betrachten.



Dort bitte auf die XYZ.jpg Datei klicken um den Screenshot zu sehen :
https://www.edv-dompteur.de/forum/index.php?page=Thread&postID=4113#post4113

Ich finde die XYZ.jpg zum Verr... nicht:frown:. Ich will auch nicht mehr danach suchen!


Gruß
Searcher

Bernd_Stein
05.05.2020, 10:21
Ich finde die XYZ.jpg zum Verr... nicht:frown:. Ich will auch nicht mehr danach suchen!
Sorry, XYZ sollte als Platzhalter für die richtigen Namen der zwei Screenshots stehen :

https://www.edv-dompteur.de/forum/index.php?page=Thread&postID=4113#post4113

(https://www.edv-dompteur.de/forum/index.php?page=Thread&postID=4113#post4113)

Im Unterprogramm _loeschen wird der 4,8MHz Systemtakt durch 8 geteilt und OCR0A mit 66 beschrieben.
Da der Timer mit prescaler 1:1 läuft, bedeutet das zu diesem Zeitpunkt ein Timer0 Comparematch nach 111µs wenn er bei 0 beginnt ( 4,8MHz/ 8 =600kHz. (1/600kHz)*(66+1) = 111µs )
Ich freue mich, dass du da durchblickst. Ja, soweit stimmt alles.
Nur ist der interne RC-Oszillator bei mir dermaßen ungenau, dass er statt mit den 600kHz mit ca. 410kHz läuft, wie man im Scrennshot zum 1ten Bit sehen kann ( 550µs ).




In der INT0 ISR wird mit CLKPS2 der 4,8MHz Systemtakt durch 16 geteilt (SYSCLK=300kHz), daß dann ein Comparematch in Timer0 nach der doppelten Zeit, also nach 222µs auslösen würde.
In der PCINT ISR wird Timer0 im CTC gestartet aber OCR0A nicht neu gesetzt; Inhalt immer noch 66. Der erste Comparematch findet demnach nach 222µs statt, nicht nach 550µs!?Jaaa... nicht ganz, aber auch hier wieder den ungenauen RC-Oszillator beachten. Die 300kHz werden bereits in der INT0-ISR eingestellt und gelten somit für die darauf folgende PCI0-IRQ und schließlich immer für die OC0A-IRQ.
Hier kommt der Trick, denn dass 1te Bit wird wirklich noch mit OCR0A=66 bei 300kHz in der OC0A-ISR erfasst, aber für die restlichen 23 Bits wird OCR0A=192 am Ende der OC0A-ISR gesetzt, so dass diese dann alle 1100µs erfasst werden ( siehe anderen Screenshot ).

Nur eben nicht immer genau im gleichen Abstand, obwohl immer Haargenau die gleichen Codeabläufe stattfinden, was mich ja verwundert.
Diese Werte für OCR0A wurden experimentell ermittelt, so dass es mit den 550µs und 1100µs passte.


Bernd_Stein

Searcher
05.05.2020, 19:47
Nur ist der interne RC-Oszillator bei mir dermaßen ungenau, dass er statt mit den 600kHz mit ca. 410kHz läuft, wie man im Scrennshot zum 1ten Bit sehen kann ( 550µs ).

.....

Jaaa... nicht ganz, aber auch hier wieder den ungenauen RC-Oszillator beachten. Die 300kHz werden bereits in der INT0-ISR eingestellt und gelten somit für die darauf folgende PCI0-IRQ und schließlich immer für die OC0A-IRQ.


Hallo Bernd,

irgendetwas stimmt da nicht. Der PCINT tritt auf, wenn sich an Data was tut. Zu dem Zeitpunkt ist OCR0A mit dem Wert 66 geladen und der Systemtakt auf 1/16 in INT0 mit CLKPS2 gestellt (die theoretischen 300kHz). In der PCINT ISR wird dann der TIMER0 gestartet und soll damit eine Zeit von 550µs bis CTC Comparematch machen? oder wo soll man die 410kHz im Screenshot ablesen?

550µs/(66+1) = 8,2µs für einen Timerstep. Der Timer wird also mit 1/8,2µs=121,951kHz getaktet.
Wegen 1/16 ist der Systemtakt = 16*121,951kHz= 1,951219MHz und nicht die theoretischen 4,8MHz. (Dann komme ich aber statt 1100µs aber auf über 1500µs bei OCR0A = 192 und 1/16 SYSCLK)

Läuft der Timer mit 1/8 SYSCLK wären das 1,951219MHz/8 = 243,902kHz und nicht 410kHz.

Bitte überprüfen und/oder Korrekturrechnung bzw jetzt genau mal den SYSCLK explizit über zB OC0A toggle messen. Ist der Systemtakt stabil? Ist die Stromversorgung stabil und sauber?

Der µC geht zwischen den Comparematch Interrups immer wieder in den Idle Sleep. Laß ihn doch mal durchlaufen ohne Sleep. Sind die Zeiten dann konstanter?

Die Diskrepanz von 4,8Mhz zu 1,9Mhz ist arg. Vielleicht mal einen neuen µC probieren?

Gruß
Searcher

PS und das auf 0 Setzen des TCNT0 in der Comparematch ISR ist doch eigentlich nicht nötig. Der Timer ist doch auf Comparematch eingestellt. Es reicht das OCR0A beim ersten Mal auf 192 zu stellen und von mir aus jedes Mal. Rücksetzen von TCNT0 an der Stelle verkompliziert die Berechnung, da ja die Zeit von Aufruf der ISR bis Rücksetzten des Timers ja uach noch verrechnet werden muß.

Bernd_Stein
05.05.2020, 23:00
...
In der PCINT ISR wird dann der TIMER0 gestartet und soll damit eine Zeit von 550µs bis CTC Comparematch machen? oder wo soll man die 410kHz im Screenshot ablesen?

Die 410kHz hatte ich mal mit dieser Codesequenz und dem DSO ermittelt und den SYS-Takt dann ausgerechnet :


sbi PINB,led.pla ;Systemtakt -> Gemessene Frequenz..
rjmp pc-1 ;..mal 8 nehmen

Jetzt nicht verzagen, der Screenshot wird ja im Detail erklärt :

https://www.edv-dompteur.de/forum/index.php?page=Thread&postID=4148#post4148

Ab ca. 420µs ( blauer senkrechter Strich ) geht die Aufzeichnung mit der fallenden Flanke des Monoflops los ( 1% davor wird auch noch erfasst ).


Irgendwann wird dann die INT0 Low-Level IRQ erzeugt.
Am Anfang der INT0-ISR wird der erste Impuls mit LED-Gelb erzeugt. Dieser ist 4,958µs lang und entspricht somit einer Frequenz von 403,388kHz, was eigentlich die nominalen 600kHz sind ( 4,958µs:2 wegen sbi, cbi ).

Am Ende der INT0-ISR ist der SYS-Takt ja bereits auf nominal 300kHz umgestellt und somit der 2te Impuls bei LED-Gelb 9,875µs lang, was der wahren Frequenz von 202,532kHz entspricht.

Die Pulse an LED-Orange lass ich jetzt erstmal raus damit es nicht zu umfangreich wird.


Dann kommt es an IN/Data ( PB0 bzw. PCINT0 ) zu der steigenden Flanke. Hier wird leider durch dass Schattenmessfenster der Marker für Bit 1 bei +1310µs überblendet, deshalb habe ich dies selbst beschriftet. Der Messwert zeigt 549,375µs an. Die 1,098ms sind der Abstand zu Bit 2.

Die PCI0-ISR habe ich zu Anfang und zu Ende durch zwei Impulse kenntlich gemacht.

Meine ganzen Zeitangaben beziehen sich also auf Messungen im Logic Analyser Programm.




...
Ist der Systemtakt stabil? Ist die Stromversorgung stabil und sauber?

Der µC geht zwischen den Comparematch Interrups immer wieder in den Idle Sleep. Laß ihn doch mal durchlaufen ohne Sleep. Sind die Zeiten dann konstanter?


Die Diskrepanz von 4,8Mhz zu 1,9Mhz ist arg. Vielleicht mal einen neuen µC probieren?


Ok, wird aber dauern bis ich davon berichte.



PS und das auf 0 Setzen des TCNT0 in der Comparematch ISR ist doch eigentlich nicht nötig. Der Timer ist doch auf Comparematch eingestellt. Es reicht das OCR0A beim ersten Mal auf 192 zu stellen und von mir aus jedes Mal. Rücksetzen von TCNT0 an der Stelle verkompliziert die Berechnung, da ja die Zeit von Aufruf der ISR bis Rücksetzten des Timers ja uach noch verrechnet werden muß.

Hatte ich mal gemacht, da aber das Timming wieder nicht stimmte habe ich es wieder reingenommen und die zwei Takte stören bisher auch nicht.
Und wie bereits geschrieben, rechne ich da gar nichts aus, sondern habe die Werte für das OCR0A-Register durch experimentieren gefunden, da sämtliche Rechnungen irgendwie nicht hinhauten.


Bernd_Stein

Searcher
06.05.2020, 08:08
Irgendwann wird dann die INT0 Low-Level IRQ erzeugt.
Am Anfang der INT0-ISR wird der erste Impuls mit LED-Gelb erzeugt. Dieser ist 4,958µs lang und entspricht somit einer Frequenz von 403,388kHz, was eigentlich die nominalen 600kHz sind ( 4,958µs:2 wegen sbi, cbi ).

Am Ende der INT0-ISR ist der SYS-Takt ja bereits auf nominal 300kHz umgestellt und somit der 2te Impuls bei LED-Gelb 9,875µs lang, was der wahren Frequenz von 202,532kHz entspricht.


Klingt plausibel. Vielleicht bringt der idle mode meine Rechnung so durcheinander. Damit hab ich kaum Erfahrung. Wer weiß, was der für Zeiten auch beim Aufwachen braucht. Im DB finde ich dazu nicht wirklich was Konkretes. Am Einfachsten mal den Sleep überhaupt nicht verwenden und das Timing (OCR0A Werte) entsprechend anpassen.

Hab sonst keine Idee mehr. In Assembler sollte der Programmablauf schon taktgenau nachvollzogen werden können :confused:

Gruß
Searcher

PS: Trotzdem könnte man den Takt nachmessen und mit Oszi schauen, ob er nicht jittert oder schwankt. Hab das kürzlich bei einem Tiny45 über den OC0A gemacht. Man mißt mit folgendem Programm den halben Systemtakt:

Bascom file zum Takt messen. Sollte leicht auf Deine IDE für Tiny13 anpaßbar sein.


$regfile = "attiny45.dat"
$framesize = 10
$swstack = 10
$hwstack = 10
$crystal = 1000000


$asm
;OCR0A vom System auf 0
sbi ddrb , 0 ;PB0 (OC0A) auf Ausgang stellen
ldi r16 , &B0100_0010 ;COM0A0 (toggle OC0A), WGM01 (CTC mit OCR0A als top)
out tccr0a , r16 ; ...
ldi r16 , &b0000_0001 ;CS00 (no Timer prescaling)
out tccr0b , r16 ;timer0 einschalten
$end Asm

Bernd_Stein
20.05.2020, 13:04
Hallo,

möchte nur mal wieder eine kleine Rückmeldung geben, da der Code jetzt geändert wurde und funktioniert. Genaueres werde ich zu einem späteren Zeitpunkt bekannt geben.




Klingt plausibel. Vielleicht bringt der idle mode meine Rechnung so durcheinander. Damit hab ich kaum Erfahrung. Wer weiß, was der für Zeiten auch beim Aufwachen braucht. Im DB finde ich dazu nicht wirklich was Konkretes...


Evtl. habe ich den Grund für die unregelmäßigen Aufrufe der OC0A-ISR gefunden, bin mir aber nicht sicher, da ich dies wiedermal nicht verstehe. Leider ist dieser Teil nicht übersetzt worden und gilt für den ATmega8, was aber nicht das Problem ist ( Siehe dort Systemtakt und Takteinstellungen -> Systemtakt-Vorteiler ) :

https://www-user.tu-chemnitz.de/~heha/viewchm.php/hs/ATmegaX8.chm/

" The ripple counter that implements the prescaler runs at the frequency of the undivided clock, which may be faster than the CPU's clock frequency. Hence, it is not possible to determine the state of the prescaler - even if it were readable, and the exact time it takes to switch from one clock division to the other cannot be exactly predicted. From the time the CLKPS values are written, it takes between T1 + T2 and T1 + 2 * T2 before the new clock frequency is active. In this interval, 2 active clock edges are produced. Here, T1 is the previous clock period, and T2 is the period corresponding to the new prescaler setting. "

" Der Welligkeitszähler, der den Vorteiler implementiert, läuft mit der Frequenz des ungeteilten Takts, die möglicherweise schneller als die Taktfrequenz der CPU ist.
Daher ist es nicht möglich, den Zustand des Vorteilers zu bestimmen - selbst wenn er lesbar wäre, und die genaue Zeit, die zum Umschalten von einer Taktteilung zur
anderen benötigt wird, kann nicht genau vorhergesagt werden. Ab dem Zeitpunkt, an dem die CLKPS-Werte geschrieben werden, dauert es zwischen T1 + T2 und T1 + 2 * T2,
bis die neue Taktfrequenz aktiv ist. In diesem Intervall werden 2 aktive Taktflanken erzeugt. Hier ist T1 die vorherige Taktperiode und T2 die Periode, die der neuen
Prescaler-Einstellung entspricht. "

Ist jetzt aber nicht mehr wichtig, da die Periodendauern der einzelnen Elemente ( 0, 1, f, Sync ) auch nicht konstant sind.
Deshalb war es keine gute Idee immer den gleichen Abstand von Bit zu Bit zu wählen. Hier sieht man dass es bei Bit13 & 19 schon recht knapp wird mit der
Erkennung des richtigen Pegels.

https://www.edv-dompteur.de/forum/index.php?page=Attachment&attachmentID=817

Deshalb habe ich eine neue Strategie ausgearbeitet und bei jeder steigenden Flanke eines Datenelementes einen INT0-IRQ ausgelöst, wo jedesmal der TCNT0 neu geladen wurde.
Beim Testen habe ich festgestellt, dass Taste B+C gleichzeitig gedrückt, den Code der Taste A wiedergibt. Dies sei nur am Rande erwähnt.


Bernd_Stein

Bernd_Stein
25.05.2020, 13:50
Ich habe mir überlegt, die Sache hier fortzuführen, da ich dort einfach die visuell besseren Möglichkeiten habe :

https://www.edv-dompteur.de/forum/index.php?page=Thread&postID=4200#post4200


Bernd_Stein