ATtiny13A: HESUNSE (CY800) Funksteckdosenprotokoll auswerten
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/in...=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:
Code:
;
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
; Headerdatei
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;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 ).
;
;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
; Einbinden der Controllerspezifischen Definitionsdatei
;CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
;
.NOLIST ;List-Output ausschalten
;.INCLUDE "tn13Adef.inc" ;AVR-Definitionsdatei einbinden
.LIST ;List-Output wieder einschalten
;
;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
; Arbeitsregister umbenennen
;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
;RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
;
.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
;
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
; Konstanten als Symbole
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;
.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:
Code:
;
.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
;
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
;I Erstinitialisierungen
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
;IIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII
;
_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
;
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;H Hauptprogrammschleife
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;
_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
;
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;U Beginn der verwendeten Unterprogramme
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;
.include "UP.inc";Unterprogramme
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;Q Beginn der verwendeten Interrupt Service Routinen ( ISR )
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
.include "ISR.inc" ;Interrupt Service Routinen
;
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;K Beginn der Programmkonstanten
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;
_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:
Code:
;
;*******************************************************************************
;* 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 ):
Code:
;
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
; Interruptvektortabelle des ATtiny13 Mikrocontrollers
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
; ***** 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 ):
Code:
;
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;U Beginn der verwendeten Unterprogramme
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;UUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUUU
;
_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 ):
Code:
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;Q Beginn der verwendeten Interrupt Service Routinen ( ISR )
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
; INTERRUPT REQUEST 0 INT0
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
_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
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
; PIN CHANGE INTERRUPT 0
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
_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
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
; Timer/Counter0 Compare Match A ISR ( Interrupt Service Routine )
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
_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
CY800-Funksteckdosenempfänger: Programmbesprechung
Zitat:
Zitat von
Searcher
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
Zitat:
Zitat von
Searcher
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 ).
Zitat:
Zitat von
Searcher
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
LA Screenshot : Anfang erklärt
Zitat:
Zitat von
Searcher
...
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 :
Code:
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/in...=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.
Zitat:
Zitat von
Searcher
...
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?
Zitat:
Zitat von
Searcher
Die Diskrepanz von 4,8Mhz zu 1,9Mhz ist arg. Vielleicht mal einen neuen µC probieren?
Ok, wird aber dauern bis ich davon berichte.
Zitat:
Zitat von
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ß.
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