Liste der Anhänge anzeigen (Anzahl: 1)
ATtiny13A: Funksteckdosen-Protokoll auswerten ( CY800 -> HESUNSE )
@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
Code:
;
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
; Headerdatei
;HHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHHH
;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.
;
;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 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
;
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
; Konstanten als Symbole
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;KKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKKK
;
.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
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/in...=4015#post4015
Hauptprogrammschleife :
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:
;
;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
;
;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<<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
;
;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 )
.EXIT ;Ende des Quelltextes
Hardware.inc :
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 = 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 :
Code:
;
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
; Interruptvektortabelle des ATtiny13 Mikrocontrollers
;VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
;
; ***** 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 ):
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 #############################
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
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
; PIN CHANGE INTERRUPT 0
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
_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
;
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
; Timer0 Overflow ISR ( Interrupt Service Routine )
;QQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQQ
;
_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 :
Anhang 34946
Bernd_Stein
CY800-Funksteckdosenempfänger -> Programmablaufpläne ( PAP )
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/in...=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
Mein Programmierstil und OC0A Interrupt
Zitat:
Zitat von
avr_racer
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
Code:
.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...l=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 ) :
Code:
;
;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/in...=4034#post4034
Bernd_Stein
Nur eine kurze Rückmeldung
Zitat:
Zitat von
Searcher
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...l=1#post659423
Ja, hast recht, werde ich tun. Werde dann auch hier dorthin verlinken.
Zitat:
Zitat von
avr_racer
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
Weiter gehts mit HENSUNSE (CY800) Funksteckdosenprotokoll auswerten
So, hiermit dürfte das Thema erledigt sein, was zum Nächsten führt :-) :
https://www.roboternetz.de/community...l=1#post659655
Bernd_Stein