;LIST F=INHX8M,P=16F876,R=HEX ;******************************************************************* ; DectTelefon als Funkfernsteuerung ; Pic : 16F876 Taktrate 4 MHz ; ; 05-01-2013 ; ;******************************************************************* ; ; ConfigByte : 0x3F79 ; ;******************************************************************* #include p16f876.inc ; Special Function Register Bank0 INDF EQU 0x00 ; TMR0 EQU 0x01 ; Timer0 ModulRegister PCL EQU 0x02 ; ProgrammCounter STATUS EQU 0x03 ; StatusRegister IRP RP1 RP0 TO PD Z DC C FSR equ 0x04 ; inirect memmory adresspointer GPIO equ 0x05 ; PCLATH equ 0x0A ; Write Buffer for Upper 5 bits of Program Counter INTCON equ 0x0B ; Interrupt-control-register GIE PEIE T0IE INTE GPIE T0IF INTF GPIF CMCON equ 0x19 ; ADRESH equ 0x1E ; ADCON0 equ 0x1F ; PIR1 equ 0x0C ; ; Spezial FunktionRegister Bank1 OPTION_REG equ 0x81 ; TRISIO equ 0x85 ; PIE1 equ 0x8C ; PCON equ 0x8E ; OSCCAL equ 0x90 ; WPU equ 0x95 ; IOC equ 0x96 ; VRCON equ 0x99 ; ; ; ;************************** Status REG. Bits ***************************** ; CARRY equ 0 ; Carry Bit is Bit.0 of F3 C equ 0 ; DCARRY equ 1 ; DC equ 1 ; Z_bit equ 2 ; Bit 2 of F3 is Zero Bit Z equ 2 ; P_DOWN equ 3 ; Power down bit PD equ 3 ; T_OUT equ 4 ; TimeoutBit TO equ 4 ; RP0 equ 5 ; Pageadresse fr direkte Adressierung RP1 equ 6 ; " IRP equ 7 ; Pageadresse fr indirekte Adressierung ; ;************************** Interupt REG. Bits *************************** ; GIE equ 7 ; global interrupt enable/disable PEIE equ 6 ; TOIE equ 5 ; INTE equ 4 ; GPIE equ 3 ; T0IF equ 2 ; INTF equ 1 ; GPIF equ 0 ; TMR1IF equ 0 ; ; ;************************** OPTION REG. Bits ***************************** ; GPPU equ 7 ; H = turn off all Pullups INTEDG equ 6 ; H = RB/int risin edge L = falling TOCS equ 5 ; L = Timermode H = Countermode TOSE equ 4 ; RA/RTCC rising = 0 or falling = 1 edge PSA equ 3 ; PS2 equ 2 ; PS1 equ 1 ; PS0 equ 0 ; ;*************************** Register für das Programm ******************* ; Speicherbereich 0x20 - 0x5F Stat1 EQU 0x20 ; Statusregister W_TEMP EQU 0x21 ; ZwischenSpeicher für Akku STATUS_TEMP EQU 0x22 ; ZwischenSpeicher für StatusRegister TimeCount0 EQU 0x2B ; ZeitZählerregister0 für Timer 1 TimeCount1 EQU 0x2C ; ZeitZählerregister0 für Timer 1 TimeCount2 EQU 0x2D ; ZeitZählerregister0 für Timer 1 W_TMPI EQU 0x2E ; ZwischenSpeicher für Akku in der Interruptroutine TonCount EQU 0x2F ; zu erzeugen eines Tones MsgCount EQU 0x30 ; Counter für die Ausgabe von Text CharIndex EQU 0x31 ; RXByte EQU 0x32 ; EmpfangsByte DtmfData EQU 0x33 ; DtmfDaten MTime0 EQU 0x36 ; MessZeit0 für Timer 1 MTime1 EQU 0x37 ; MessZeit1 für Timer 1 MTime2 EQU 0x38 ; MessZeit2 für Timer 1 Hz50Count EQU 0x39 ; Zählt 50Hz Perioden RXByte0 EQU 0x3A ; EmpfangsByte0 RXByte1 EQU 0x3B ; EmpfangsByte1 RXByte2 EQU 0x3C ; EmpfangsByte2 DtmfStat EQU 0x3D ; DTMF Status RXIndex EQU 0x3F ; PauseCount0 EQU 0x40 ; Zähler für PauseTimer PauseCount1 EQU 0x41 ; Zähler für PauseTimer PauseCount2 EQU 0x42 ; Zähler für PauseTimer DtmfCode0 EQU 0x43 ; erster Teil des DTMFCodes DtmfCode1 EQU 0x44 ; zweiter Teil des DTMFCodes DtmfCodeIndex EQU 0x45 ; Zählen wieviele Tasten vom Code bereits angekommen RXByte3 EQU 0x46 ; EmpfangsByte3 TXIndex EQU 0x48 ; ms10Count EQU 0x50 ; 50Hz-Periode ms1Count EQU 0x51 ; PWM LowTimeZähler ;********** Allgemeine Bits ************ LED EQU 1 ; LED - PortC TXPin EQU 5 ; Funk-TXT Port C 5 ;********** Bits in Stat1-Register ************ TimeOut0 EQU 0 ; TimeOutBit - Timer0 TimeOut1 EQU 1 ; TimeOutBit - Timer1 BlinkEn EQU 2 ; Blinken enabel in Stat1 TimeOut2 EQU 6 ; TimOutBit -Timer2 PumpUp EQU 3 ; bei Rufsignal PumpupFase ; *************** I/O Steuerleitungen ********************* ; DTMF DatenBus ; Port B 0-3 ; DTMFSignale Port A 0-3 RW EQU 3 ; R/W Signal RS0 EQU 1 ; RS0 Signal CS EQU 2 ; CS Signal PHI2 EQU 0 ; PHI2 Signal Audio EQU 4 ; Audio-Out an PortC PWM EQU 4 ; PWM signal an Port A 4 Hz50 EQU 5 ; 50Herz Signal an Port A 5 En12V EQU 4 ; 12V Enable an Port C 4 HOOK EQU 2 ; abgehoben an Port C 2 RUFEN EQU 0 ; Ruftaste PORTC 0 ; ;************************************************************************** ;*************************** Programmstart ******************************** ;************************************************************************** ; ; org 0x0000 ; goto Start ; Resetvektor data H'0000' data H'0000' data H'0000' goto Inter ; Interruptvektor Start org 0x0005 ; call S_Init ; Initroutine bsf INTCON,GIE ; Globaler Interruptenable ;************************ ; Programmstart ;************************ bcf PORTC,LED ; Led leuchtet bcf Stat1, BlinkEn ; Blinken der Led stoppen bsf PORTC,LED ; LED blinkt mit Timer 1 im 500 ms Takt ; 12V einschalten bsf PORTC, En12V ; ; PWM Off bcf PORTA, PWM ; ; MainLoop : warten auf DTMF-Befehle IsDTMF bsf PORTC, LED ; btfsc PORTC, HOOK ; ist abgehoben ? wird mit LED angezeigt bcf PORTC, LED ; call R_Sta ; Warten ob DTMFTon empfangen wird btfsc DtmfData,2 ; call TxDFData ; btfss PORTC,RUFEN ; wenn Call-Taste dann Rufspannung erzeugen call MakeCall ; goto IsDTMF ; ;************************************************ ; ; DTMF-Befehle auswerten ; ; TxDFData ; ///// wenn DTMFDaten erkannt wurden dann über RB4-RB7 parallel ausgeben ; //// und über serielle schnittstelle schicken call R_Dat ; DTMF Daten auslesen movf DtmfData,w ; movwf DtmfCode0 ; rlf DtmfCode0, f ; rlf DtmfCode0, f ; rlf DtmfCode0, f ; rlf DtmfCode0, f ; movlw B'11110000' ; andwf DtmfCode0, f ; movf DtmfCode0, w ; Daten parallel ausgeben movwf PORTB ; movf DtmfData, w ; Daten seriell ausgeben call TX_Byte ; return ; ;************************************************ ; Byte im Akku seriell senden ;************************************************ TX_Byte: btfss PIR1,TXIF ; warten bis SendeBuffer leer goto TX_Byte ; movwf TXREG ; return ; ;******************************************************** ; Rufspannung generieren : 25 Hz Rechteckspannung 24-30 V ; Steuerspannung für StepUp Regler: Low 990us High 10 us ;******************************************************** MakeCall: btfsc PORTC, HOOK ; ist abgehoben ? dann nicht rufen return ; bcf PORTC, En12V ; 12V Spannung ausschalten bsf Stat1, PumpUp ; im der PumpUp-Phase die Spannung auf 30V pumpen RufSigLoop movlw .200 ; zweihundert 25 Hz Perioden erzeugen movwf Hz50Count ; movlw .20 ; 20ms Halbperiode von 25Hz movwf ms10Count ; bcf PORTA,Hz50 ; Hz25Loop ; bsf PORTA, PWM ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; NOP ; bcf PORTA, PWM ; movlw .10 ; 1ms PWM Low movwf ms1Count ; PWMLow movlw .250 ; 1ms PWM OFF movwf TMR0 ; call WaitTime0 ; movlw .250 ; movwf TMR0 ; call WaitTime0 ; decfsz ms1Count ; ist PWM 1 ms abgeschlossen goto PWMLow ; decfsz ms10Count,1 ; 10ms 28V aktiviert/deaktiviert goto Hz25Loop ; btfsc Stat1, PumpUp ; in der AufpumpFase werden keine 25Hz erzeugt goto RufNext ; movlw B'00100000' ; 25Hz Signal PortA toggeln xorwf PORTA,1 ; RufNext movlw .20 ; 20ms Halbperiode von 25Hz movwf ms10Count ; decfsz Hz50Count,1 ; goto Hz25Loop ; btfss Stat1, PumpUp ; goto RufEnde ; bcf Stat1, PumpUp ; jetzt wird auch 25Hz RufSignal erzeugt goto RufSigLoop ; RufEnde bsf PORTA, Hz50 ; 24V Spannung ausschalten bsf PORTC, En12V ; 12V Spannung einschalten return ; ;***************************************************** ; ; Wartezeiten die mit - Timer 0 - erzeugt werden ; wird beim erzeugen der Signale und beim Tonerzeugen benutzt ; bei 4MHz/4 OsillatorFrq Tick = 1us; WaitTime0 ;************************* bsf STATUS,RP0 ; Bank 1 ; RBPU INTEDG T0CS T0SE PSA PS2 PS1 PS0 movlw B'00000000' ; internalClock Prescaler Timer0 1:2 movwf OPTION_REG ; bsf INTCON, T0CS ; Timer freigeben bcf STATUS,RP0 ; Bank 0 bcf INTCON, T0IF ; Timer1-ÜberlaufBit löschen bsf INTCON, T0IE ; TIMER1-Iterrupt enable bcf Stat1, TimeOut0 ; Wait_Timeout0 btfss Stat1, TimeOut0 ; Warten bis der Timer überläuft goto Wait_Timeout0 ; bcf INTCON, T0CS ; Timer stoppen bcf INTCON, T0IE ; TIMER1-Iterrupt disable return ; ;****************************************************** ; Ton erzeugen 1900 Hz ; ; nach dem ton wird die gleiche Zeit als Stille erzeugt ;****************************************************** MakeTon movlw 0xFF ; Länge des Tones movwf TonCount ; TonLoop movlw .142 ; Zeit für 1900 Hz = 263 us halbe Periode movwf TMR0 ; bsf PORTC,Audio ; call WaitTime0 ; movlw .142 ; Zeit für 1900 Hz = 263 us halbe Periode movwf TMR0 ; bcf PORTC, Audio ; call WaitTime0 ; decfsz TonCount,1 ; goto TonLoop ; ; gleiche Zeit als Stille erzeugen um IntervallTon zu ermöglichen movlw 0xFF ; Länge des Tones movwf TonCount ; TonStill movlw 0x20 ; Zeit für 1900 Hz = 263 us halbe Periode movwf TMR1L ; movlw 0xFF ; movwf TMR1H ; call WaitTime0 ; movlw 0x20 ; Zeit für 1900 Hz = 263 us halbe Periode movwf TMR1L ; movlw 0xFF ; movwf TMR1H ; call WaitTime0 ; decfsz TonCount,1 ; goto TonStill ; return ; ;++++++++++++++++++++++++++++++++++ ;******* Initialisierung ******** ;++++++++++++++++++++++++++++++++++ S_Init ; DatenPortA initialisieren ;RA0/AN0 bit0 TTL Input/output or analog input. ;RA1/AN1 bit1 TTL Input/output or analog input. ;RA2/AN2 bit2 TTL Input/output or analog input. ;RA3/AN3/VREF bit3 TTL Input/output or analog input or VREF. ;RA4/T0CKI bit4 ST Input/output or external clock input for Timer0. Output is open drain type. ;RA5/SS/AN4 bit5 TTL Input/output or slave select input for synchronous serial port or analog input. ;05h PORTA — — RA5 RA4 RA3 RA2 RA1 RA0 --0x 0000 --0u 0000 ;85h TRISA — — PORTA Data Direction Register --11 1111 --11 1111 (0=Output 1=Input) ;9Fh ADCON1 ADFM — — — PCFG3 PCFG2 PCFG1 PCFG0 --0- 0000 --0- 0000 BCF STATUS, RP0 ; BCF STATUS, RP1 ; Bank0 ;CLRF PORTA ; Initialize PORTA by clearing output data latches BSF STATUS, RP0 ; Select Bank 1 MOVLW B'00000110' ; Configure all pins MOVWF ADCON1 ; as digital inputs/outputs and not AD-Inputs BSF STATUS, RP0 ; Bank1 movlw B'00000000' ; Value used to initialize data direction MOVWF TRISA ; RA0-RA5 as outputs TRISA<7:6>are always read as ’0’. BCF STATUS, RP0 ; Bank0 ; DatenPortB initialisieren ; RB0/INT bit0 TTL/ST(1) Input/output pin or external interrupt input. Internal softwareprogrammable weak pull-up. ; RB1 bit1 TTL Input/output pin. Internal software programmable weak pull-up. ; RB2 bit2 TTL Input/output pin. Internal software programmable weak pull-up. ; RB3/PGM(3) bit3 TTL Input/output pin or programming pin in LVP mode. Internal software programmable weak pull-up. ; RB4 bit4 TTL Input/output pin (with interrupt-on-change). Internal software programmable weak pull-up. ; RB5 bit5 TTL Input/output pin (with interrupt-on-change). Internal software programmable weak pull-up. ; RB6/PGC bit6 TTL/ST(2) Input/output pin (with interrupt-on-change) or In-Circuit Debugger pin.Internal software programmable weak pull-up. Serial programming clock. ; RB7/PGD bit7 TTL/ST(2) Input/output pin (with interrupt-on-change) or In-Circuit Debugger pin.Internal software programmable weak pull-up. Serial programming data. ; 06h, 106h PORTB RB7 RB6 RB5 RB4 RB3 RB2 RB1 RB0 xxxx xxxx uuuu uuuu ; 86h, 186h TRISB PORTB Data Direction Register 1111 1111 1111 1111 ; 81h, 181h OPTION_REG RBPU INTEDG T0CS T0SE PSA PS2 PS1 PS0 1111 1111 1111 1111 BCF STATUS, RP0 ; BCF STATUS, RP1 ; Bank0 CLRF PORTB ; Initialize PORTB by clearing output data latches BSF STATUS, RP0 ; Bank1 ; movlw B'00000000' ; Value used to initialize data direction movlw B'00001111' ; Init für DTMF-DATENPORT RB0-RB3 D0-D3 Dtmf alles INPUT ; ACHTUNG in der DtmfRoutine werden auch die oberen D4-D7 verändert !!!! MOVWF TRISB ; BCF STATUS, RP0 ; Bank0 ; DaRC0/T1OSO/T1CKI bit0 ST Input/output port pin or Timer1 oscillator output/Timer1 clock input. ; RC1/T1OSI/CCP2 bit1 ST Input/output port pin or Timer1 oscillator input or Capture2 input/Compare2 output/PWM2 output. ; RC2/CCP1 bit2 ST Input/output port pin or Capture1 input/Compare1 output/PWM1 output. ; RC3/SCK/SCL bit3 ST RC3 can also be the synchronous serial clock for both SPI and I2C modes. ; RC4/SDI/SDA bit4 ST RC4 can also be the SPI Data In (SPI mode) or data I/O (I2C mode). ; RC5/SDO bit5 ST Input/output port pin or Synchronous Serial Port data output. ; RC6/TX/CK bit6 ST Input/output port pin or USART Asynchronous Transmit or Synchronous Clock. ; RC7/RX/DT bit7 ST Input/output port pin or USART Asynchronous Receive or Synchronous Data.tenPortC initialisieren ;07h PORTC RC7 RC6 RC5 RC4 RC3 RC2 RC1 RC0 xxxx xxxx uuuu uuuu ;87h TRISC PORTC Data Direction Register 1111 1111 1111 1111 BCF STATUS, RP0 ; BCF STATUS, RP1 ; Bank0 ;CLRF PORTC ; Initialize PORTC by clearing output data latches BSF STATUS, RP0 ; Bank1 movlw B'00000101' ; Value used to initialize data direction MOVWF TRISC ; BCF STATUS, RP0 ; Bank0 ; ******** UART settings ***************************** ; RCSTA: RECEIVE STATUS AND CONTROL REGISTER (ADDRESS 18h) ; SPEN RX9 SREN CREN ADDEN FERR OERR RX9D movlw B'10010000' ; serialPort enabeld - continuos receive - 8Bit - no overrun - no Frameerror movwf RCSTA ; ; TXSTA: TRANSMIT STATUS AND CONTROL REGISTER (ADDRESS 98h) ; CSRC TX9 TXEN SYNC — BRGH TRMT TX9D BSF STATUS, RP0 ; BCF STATUS, RP1 ; Bank1 movlw B'00100100' ; TX8Bit BRGH HighSpeed und TX enable movwf TXSTA ; ; Baudratengenerator für 9600 Baud bei 4mHz Oszfrq festlegen ; .25 SPBRG Baud Rate Generator Register ; Baudratengenerator für 9600 Baud bei 2mHz Oszfrq festlegen ; .12 SPBRG Baud Rate Generator Register movlw .25 ; movwf SPBRG ; BCF STATUS, RP0 ; BCF STATUS, RP1 ; Bank0 ;***************************************************** ; Timer1 gibt einen SystemTakt von 500 ms vor ; wird zum Blinken der Led benutzt ; TimeCount0 1 2 wird für lange Abstände benutzt ; bei 4MHz OsillatorFrq Tick = 1us; bsf STATUS,RP0 ; Bank 1 bsf PIR1, TMR1IE ; Timer1-Interrupt enable bcf STATUS,RP0 ; Bank 0 bsf INTCON, PEIE ; TIMER1-Iterrupt aktivieren bsf INTCON, GIE ; Globalen Iterrupt Enable bcf PIR1, TMR1IF ; Timer1-ÜberlaufBit löschen bsf T1CON, T1CKPS0 ; Prescaler Teilung durch 1:8 bsf T1CON, T1CKPS1 ; Prescaler Teilung durch 1:8 movlw 0x01 ; movwf MTime0 ; movwf TimeCount0 ; movlw 0x01 ; movwf MTime1 ; movwf TimeCount1 ; movlw 0x01 ; movwf MTime2 ; movwf TimeCount2 ; movlw 0x8C ; 500ms bei 1us Tick und Teilung 1:8 movwf TMR1L ; Zählerregister neu füllen movlw 0x0A ; movwf TMR1H ; bsf T1CON, TMR1ON ; Timer freigeben bcf Stat1, TimeOut1 ; ;*********************************** ; ADConverter ; ADCON0 REGISTER (ADDRESS: 1Fh) Bank0 ;ADCS1 ADCS0 CHS2 CHS1 CHS0 GO/DONE — ADON ;movlw B'01010001' ; FRQ/8 AD3 selected AD=ON ;movwf ADCON0 ; ;ADCON1 REGISTER (ADDRESS 9Fh) Bank1 ;ADFM — — — PCFG3 PCFG2 PCFG1 PCFG0 ;BSF STATUS, RP0 ; ;BCF STATUS, RP1 ; Bank1 ;movlw B'10000010' ; ;movwf ADCON1 ; ;BcF STATUS, RP0 ; ;BCF STATUS, RP1 ; Bank0 ;******************************************** ; ; DTMF-8088 INIT ; ; ;********************************************* Dtmf_Init movlw 0x00 ; movwf DtmfStat ; BSF STATUS, RP0 ; Bank1 movlw B'00001111' ; DTMF-DATENPORT RB0-RB3 D0-D3 auf INput + PullupFunktion MOVWF TRISB ; RB0-RB3 as Inputs . bcf OPTION_REG,7 ; RBPU BCF STATUS, RP0 ; Bank0 bsf PORTA,CS ; CS H call wait120ms ; ca. 120 ms warten call R_Sta ; MT8880 initialisierungsfolge movlw 0x00 ; Daten 0000 B 00000000 ACHTUNG komplettes Port B wird verändert ! movwf DtmfData ; call W_CRA ; movlw 0x00 ; Daten 0000 B 00000000 ACHTUNG komplettes Port B wird verändert ! movwf DtmfData ; call W_CRA ; movlw 0x08 ; Daten 1000 B 00001000 ACHTUNG komplettes Port B wird verändert ! movwf DtmfData ; call W_CRA ; movlw 0x00 ; Daten 0000 B 00000000 ACHTUNG komplettes Port B wird verändert ! movwf DtmfData ; call W_CRA ; call R_Sta ; movlw 0x09 ; Daten 0000 B 0001011 (tone out, DTMF, Select Control Reg. B) movwf DtmfData ; call W_CRA ; movlw 0x00 ; Daten 0000 B 00000000 (burst, test, dualtone, -) movwf DtmfData ; call W_CRA ; ; movlw 0x03 ; Daten 0000 B 00000011 (tone out, CP, Select Control Reg. B) movwf DtmfData ; call W_CRA ; call wait120ms ; ;movlw 0x0C ; ;movwf DtmfData ; TestTonLoop ; alle möglichen DTMFTestTöne beim initialisieren ausgeben ;call W_Dat ; damit kann festgestellt werden ob die Ansteuerung funktioniert ;call wait300ms ; ;decfsz DtmfData,f ; ;goto TestTonLoop ; call R_Sta ; call R_Dat ; call wait120ms ; movlw 0x01 ; Daten 0000 B 00000001 (tone out, DTMF, Select Control Reg. B) movwf DtmfData ; call W_CRA ; ;******************************************************* ;** ;** Routinen für den Betrieb von DTMF MT8880 ;** W_CRA: ; in Statusregister A schreiben BSF STATUS, RP0 ; Bank1 movlw B'00000000' ; DTMF-DATENPORT RB0-RB3 D0-D3 auf OUTput MOVWF TRISB ; RB0-RB3 as Inputs . bsf OPTION_REG,7 ; RBPU BCF STATUS, RP0 ; Bank0 movf DtmfData,w ; Daten ausgeben movwf PORTB ; ACHTUNG hier werden auch die oberen PortLeitungen verändert !!! call wait300us ; bsf PORTA,RS0 ; RS0 = 1 bcf PORTA,RW ; R_W = 0 bcf PORTA,CS ; CS = 0 call wait300us ; bsf PORTA,PHI2 ; PHI2= 1 call wait300us ; bcf PORTA, PHI2 ; PHI2= 0 call wait300us ; bsf PORTA, CS ; CS = 1 call wait300us ; ; Datenleitunngen wieder auf Input BSF STATUS, RP0 ; Bank1 movlw B'00001111' ; DTMF-DATENPORT RB0-RB3 D0-D3 auf INput + PullupFunktion MOVWF TRISB ; RB0-RB3 as Inputs . bcf OPTION_REG,7 ; RBPU BCF STATUS, RP0 ; Bank0 return ; W_Dat: ; Daten schreiben BSF STATUS, RP0 ; Bank1 movlw B'00000000' ; DTMF-DATENPORT RB0-RB3 D0-D3 auf OUTput MOVWF TRISB ; RB0-RB3 as Inputs . bsf OPTION_REG,7 ; RBPU BCF STATUS, RP0 ; Bank0 movf DtmfData,w ; Daten ausgeben movwf PORTB ; ACHTUNG hier werden auch die oberen PortLeitungen verändert !!! call wait300us ; bcf PORTA,RS0 ; RS0 = 0 bcf PORTA,RW ; R_W = 0 bcf PORTA,CS ; CS = 0 call wait300us ; bsf PORTA,PHI2 ; PHI2= 1 call wait300us ; bcf PORTA, PHI2 ; PHI2= 0 call wait300us ; bsf PORTA, CS ; CS = 1 call wait300us ; ; Datenleitunngen wieder auf Input BSF STATUS, RP0 ; Bank1 movlw B'00001111' ; DTMF-DATENPORT RB0-RB3 D0-D3 auf INput + PullupFunktion MOVWF TRISB ; RB0-RB3 as Inputs . bcf OPTION_REG,7 ; RBPU BCF STATUS, RP0 ; Bank0 return ; R_Sta: ; Statusregister lesen BSF STATUS, RP0 ; Bank1 movlw B'00001111' ; DTMF-DATENPORT RB0-RB3 D0-D3 auf INput + PullupFunktion MOVWF TRISB ; RB0-RB3 as Inputs . bcf OPTION_REG,7 ; RBPU BCF STATUS, RP0 ; Bank0 call wait300us ; bsf PORTA,RS0 ; RS0 = 1 bsf PORTA,RW ; RW = 1 bcf PORTA,CS ; CS = 0 call wait300us ; bsf PORTA,PHI2 ; PHI2 = 1 call wait300us ; movf PORTB,w ; andlw 0x0F ; oberen 4 Bit löschen movwf DtmfData ; und in DTMF-Daten Byte bereitstellen bcf PORTA,PHI2 ; PHI2 = 0 call wait300us ; bsf PORTA,CS ; CS = 1 call wait300us ; return ; R_Dat: ; Datenregister lesen BSF STATUS, RP0 ; Bank1 movlw B'00001111' ; DTMF-DATENPORT RB0-RB3 D0-D3 auf INput + PullupFunktion MOVWF TRISB ; RB0-RB3 as Inputs . bcf OPTION_REG,7 ; RBPU BCF STATUS, RP0 ; Bank0 call wait300us ; bcf PORTA,RS0 ; RS0 = 0 bsf PORTA,RW ; RW = 1 bcf PORTA,CS ; CS = 0 call wait300us ; bsf PORTA,PHI2 ; PHI2 = 1 call wait300us ; movf PORTB,w ; andlw 0x0F ; oberen 4 Bit löschen movwf DtmfData ; und in DTMF-Daten Byte bereitstellen bcf PORTA,PHI2 ; PHI2 = 0 call wait300us ; bsf PORTA,CS ; CS = 1 call wait300us ; return ; SendDTMF ; DTMFTonSignal senden - TastenCode muss im AKKU stehen movwf DtmfData ; DTMFTon call W_Dat ; call wait300ms ; return ; DTMF100msON ; BurstLänge 100 ms einschalten (in der Phase ist kein Empfang möglich! movlw 0x03 ; Daten 0000 B 00000011 (tone out, CP, Select Control Reg. B) movwf DtmfData ; call W_CRA ; call wait120ms ; return ; DTMF100msOFF ; BurstLänge 100 ms ausgeschalten (50 ms ist Default und Epfang ist gleichzeitig möglich) movlw 0x01 ; Daten 0000 B 00000001 (tone out, DTMF, Select Control Reg. B) movwf DtmfData ; call W_CRA ; call wait120ms ; return ; ;*************************************************** ; ; WartePausen ; ; gültig nur bei 4 MHz Takt 1 Tick im PauseCount0 = 4,5us wait120ms movlw .255 ; movwf PauseCount0 ; movlw .160 ; movwf PauseCount1 ; movlw .1 ; movwf PauseCount2 ; goto Wait_Time ; wait1ms movlw .255 ; movwf PauseCount0 ; movlw .1 ; movwf PauseCount1 ; movlw .1 ; movwf PauseCount2 ; goto Wait_Time ; wait300us movlw .95 ; movwf PauseCount0 ; movlw .1 ; movwf PauseCount1 ; movlw .1 ; movwf PauseCount2 ; goto Wait_Time ; wait300ms movlw .255 ; movwf PauseCount0 ; movlw .130 ; movwf PauseCount1 ; movlw .2 ; movwf PauseCount2 ; goto Wait_Time ; Wait_Time decfsz PauseCount0,1 ; achtung - Druchläufe sind immer um einen TimeCount0 Durchlauf weniger goto Wait_Time ; decfsz PauseCount1,1 ; Kleinste Zahl bei TimeCount 1 muß immer 1 sein !!!! goto Wait_Time ; decfsz PauseCount2,1 ; Kleinste Zahl bei TimeCount 2 muß immer 1 sein !!!! goto Wait_Time ; return; ;******************************** ;***** Interruptbehandlung ****** ;******************************** ; ; es werden auch Interrupts ausgewertet die im vorliegenden Programm nicht verwendet werden ; z.B. I2C Interrupt ; Inter bcf INTCON,GIE; MOVWF W_TMPI ;copy W to temp register,could be in either bank SWAPF STATUS,W ;swap status to be saved into W BCF STATUS,RP0 ;change to bank 0 regardless of current bank MOVWF STATUS_TEMP ;save status to bank 0 register ;GIE PEIE T0IE INTE GPIE T0IF INTF GPIF btfsc PIR1,TMR1IF ; wenn Timeroverflow bei Timer1 goto Timout1 ; btfsc PIR1,TMR2IF ; wenn TimeroverFlow bei Timer2 goto Timeout2; btfsc INTCON,T0IF ; wenn Timeroverflow bei Timer0 goto Timout0 ; btfsc PIR1,SSPIF ; wenn I2C-Interrupt goto I2C_Int ; IR_Back SWAPF STATUS_TEMP,W ;swap STATUS_TEMP register into W, sets bank to original state MOVWF STATUS ;move W into STATUS register SWAPF W_TMPI,F ;swap W_TEMP SWAPF W_TMPI,W ;swap W_TEMP into W bsf INTCON,GIE ; retfie ; ;++++++++++++++++++++++++++++++++++ ;******* Timerinterrupts ******** ;++++++++++++++++++++++++++++++++++ ; ; Timer0 Interruptbehandlung Timout0 bsf Stat1, TimeOut0 ; Timeout0 Bit setzen bcf INTCON,T0IF ; Interruptflag l”schen goto IR_Back ; ;Timer1 Interreptbehandlung (Grundtakt = 500 ms) ; Timout1 bcf Stat1, TimeOut1 ; Timeout1 Bit löschen btfss Stat1, BlinkEn ; wenn Blinken freigeschalten dann Led blinken goto Timout1_1 ; movlw B'00000010' ; LED PORT A0 toggeln (alle 500ms) xorwf PORTC,1 ; Timout1_1 ; decfsz TimeCount0,1 ; Achtung - Druchläufe sind immer um einen TimeCount0 Durchlauf weniger goto Timeout1_2 ; decfsz TimeCount1,1 ; Kleinste Zahl bei TimeCount 1 muß immer 1 sein !!!! goto Timeout1_2 ; decfsz TimeCount2,1 ; Kleinste Zahl bei TimeCount 2 muß immer 1 sein !!!! goto Timeout1_2 ; bsf Stat1, TimeOut1 ; Timeout Bit setzen weil alle 4 voreingestellten Zeiten durch sind movf MTime0,W ; TimerCounter wieder Rücksetzen movwf TimeCount0 ; movf MTime1,W ; movwf TimeCount1 ; movf MTime2,W ; movwf TimeCount2 ; Timeout1_2 movlw 0x8C ; 500ms bei 1us Tick und Teilung 1:8 movwf TMR1L ; Zählerregister neu füllen movlw 0x0A ; movwf TMR1H ; bcf PIR1,TMR1IF ; Interruptflag l”schen wird gelöscht goto IR_Back ; ; TIMER2 - Interruptbehandlung (PWM Duty-Cylce Erzeugung) Timeout2 bsf Stat1, TimeOut2 ; bcf PIR1,TMR2IF ; Interruptflag l”schen wird gelöscht goto IR_Back ; ;++++++++++++++++++++++++++++++++++ ;******* I2C-Interrupt ******** ;++++++++++++++++++++++++++++++++++ I2C_Int bcf PIR1,SSPIF ; Interruptflag l”schen wird gelöscht goto IR_Back ; ;++++++++++++++++++++++++++++++++++ ;******* Flankeninterrupt ******** ;++++++++++++++++++++++++++++++++++ Flanke movf GPIO,w ; aktuellen PortStatus einlesen damit nicht wieder ein Interrupt ausgelöst wird bcf INTCON,GPIF ; Interruptflag l”schen goto IR_Back ; end