; Programm TELEMET1.asm: Telemetrie: Senden eines Messwertes ; PIC16F84, f = 4,000 MHz, Sendeausgang RA2, ADW: OUT an RA3, CLOCK an RA1, CS an RA4 , ; Dieter Kohtz, November 2001 ; Registerzuweisung RTCC equ 1 PC equ 2 STAT equ 3 FSR equ 4 PORTA equ 5 PORTB equ 6 INTCON equ 0B DATAUS equ 0C ZAEHL equ 0D ADRES equ 0E BIT equ 0F A0 equ 10 A1 equ 11 AS equ 12 ; auf Registerseite 1: TRISA equ 05 ; Richtungsregister fuer Port A TRISB equ 06 ; Richtungsregister fuer Port B OPTREG equ 01 ; OPTION-Register ;Ziele: w equ 0 f equ 1 ;Bits Z equ 02 ; Null-Bit im Statuswort-Register C equ 00 ; Carry-Bit im Statuswort-Register TO equ 04 ; Timeout-Bit im Statuswort-Register RP0 equ 05 ; Seitenauswahlbit im Statuswort-Register T0IF equ 02 ; RTCC-Interruptflag im INTCON-Register cl equ 01 ; Takt-Bit (clock) an PORTA da equ 03 ; Daten-Bit an PORTA cs equ 04 ; Chip-Select-Bit an PORTA ;********************************************************************************* ;Makrodefinitionen bank0 macro bcf STAT,RP0 endm bank1 macro bsf STAT,RP0 endm ;********************************************************************************* org 0 goto beginn ;********************************************************************************** ; Initialisierung: RTCC voreinstellen und starten; Vorteiler = 4, SC = 1 us: alle 4 us wird RTCC erhoeht ; Bei RTCC-Ueberlauf wird Interruptflag im INTCON-Register gesetzt ;********************************************************************************** init clrf RTCC ; RTCC auf 0 voreingestellt bank1 ; Registerseite 1 movlw b'01000001' ; interner Takt, Vorteiler = 4 an RTCC, steigende Flanke movwf OPTREG ; und Start des RTCC movlw b'01001' movwf TRISA ; RA0/3 = Eingang, RA1/2/4 = Ausgang movlw b'11111111' movwf TRISB ; PORTB = Eingang (unbenutzt) bank0 ; Registerseite 0 return ;********************************************************************************** ; Halbe Bitdauer von 0,42 ms (1200 Baud) und adw-Pause von 20 us ;********************************************************************************** adwpaus movlw .251 ; RTCC fuer ca. 20 us vorbereiten goto $+2 bitpaus movlw .157 ; 256 - 157 = 99; 99 x 4us = 396us (codier = 840us) movwf RTCC ; RTCC fuer 0,396 ms vorbereiten btfss INTCON,T0IF ; Abfrage des T0-Interrupt-Flags goto $-1 ; 0,396 ms Warten auf T0IF bcf INTCON,T0IF ; Bitdauer verstrichen return ;********************************************************************************** adw clrf ADRES ; ADRES loeschen bcf PORTA,cs ; CS = 0: ADW gibt Daten aus call adwpaus ; ca. 20 us Pause movlw 08 ; BIT mit 8 laden movwf BIT ; fuer 8-maligen Schleifendurchlauf bcf STAT,C ; Carrybit loeschen (meist vor Schiebebefehl noetig) bsf PORTA,cl ; CLOCK = 1, hoechstwertiges Bit liegt an PORTA,da btfsc PORTA,da ; DATA = 0/1? goto setzen1 ; DATA = 1 bcf ADRES,7 ; DATA = 0: Bit 7 in ADRES loeschen goto $+2 ; setzen ueberspringen setzen1 bsf ADRES,7 ; Bit 7 in ADRES setzen rlf ADRES,f ; ADRES links schieben durch Carry! bcf PORTA,cl ; CLOCK = 0 decfsz BIT,f ; BIT herunterzaehlen und auf 0 testen goto $-9 ; BIT ist nicht 0: wiederholen rlf ADRES,f ; BIT = 0: noch einmal nachschieben! bsf PORTA,cs ; CS = 1: Ausgang hochohmig return ;********************************************************************************** ; Manchester-Codierung, Dauer des UP 0,840 ms = ca. 1 Bitdauer bei 1200 Baud ;********************************************************************************** codier btfss STAT,C ; Carrybit testen goto loesch ; Carrybit = 0: A1 = 0 movlw 01 ; Carrybit = 1: A1 = 1 movwf A1 goto weiter loesch clrf A1 weiter movf A1,w subwf A0,w btfss STAT,Z ; A1 = A0? goto ungleich ; nein: zu ungleich gleich movlw b'00100' ; ja: xorwf PORTA,f ; B sofort umschalten call bitpaus ; warten movlw b'00100' xorwf PORTA,f ; B noch mal umschalten goto $+4 ; ungleich ueberspringen ungleich nop nop call bitpaus ; warten movlw b'00100' xorwf PORTA,f ; B umschalten movf A1,w movwf A0 ; A1 = A0 call bitpaus clrwdt return ;********************************************************************************** ;Hauptprogramm ;********************************************************************************** beginn clrf DATAUS call init clrf INTCON ;keine Interrupts! call adw call adw ; zwei mal, um aktuelles Ergebnis zu erhalten ;********************************************************************************** ; Sendeankuendigung: ca. 100ms lang A0 = 1 mit Decodierung und Startbit = 0 ;********************************************************************************** bcf PORTA,2 ; RA2 = 0 movlw .240 movwf ZAEHL ; 240 mal 840us = ca. 200 ms movlw 01 movwf AS ; AS = 1 Dauerpegel movwf A0 ; A0 = 1 angenommen puls rrf AS,w ; Bit 0 wird zum Carrybit im Statuswortregister call codier decfsz ZAEHL,f goto puls clrf AS ; Startbit: AS = 0 rrf AS,w call codier ;********************************************************************************** ; Senden eines seriellen Bytes, das in ADRES steht ;********************************************************************************** send movlw 08 movwf BIT ; 8 Datenbits vorbereiten movf ADRES,w ; ADRES nach DATAUS movwf DATAUS wdh rrf DATAUS,f call codier clrwdt decfsz BIT,f goto wdh ; Schleife 8 mal durchlaufen movlw 01 ; Stoppbit : AS = 1 movwf AS rrf AS,w call codier clrwdt ; ein Byte uebertragen ;********************************************************************************** ;Vorbereiten einer Sleep-Phase durch Einrichten des WDT auf eine Basis-Pause von ca. 18ms x 128 = 2,3 s ;********************************************************************************** clrf RTCC clrf PORTA clrf PORTB bank1 bsf OPTREG,5 ; RTCC stopp nop nop movlw b'00001111' ; Vorteiler = 128 zu WDT movwf OPTREG movlw b'11111' movwf TRISA ; RA2 = Eingang bank0 movlw .10 movwf ZAEHL ; ZAEHL laden fuer ca. 23 Sekunden clrwdt sleep ; Sleepmodus bis WDT-Timeout nop ; Warten auf Timeout decfsz ZAEHL,f goto $-4 goto beginn ;********************************************************************************** end