LIST P=PIC16F876a #INCLUDE P16F876a.INC errorlevel -302 ;suppress "not in bank 0" message __CONFIG _CP_OFF & _DEBUG_OFF & _LVP_OFF & _PWRTE_ON & _WDT_OFF & _BODEN_OFF & _HS_OSC #define FOSC D'8000000' ; define FOSC to PICmicro #define I2CClock D'100000' ; define I2C bite rate #define ClockValue (((FOSC/I2CClock)/4) -1) ; CBLOCK 0x70 WREG_TEMP ;storage for WREG during interrupt STATUS_TEMP ;storage for STATUS during interrupt PCLATH_TEMP ;storage for PCLATH during interrupt FSR_TEMP ;storage for FSR during interrupt COUNT1 ;Timer 1, Used for general delay. COUNT2 ;Timer 2, Used for general delay. PcToMcPointer ;Gives the adress where to write the data to master McToPcPointer ;Gives the adress what to write to pc TempBuf1 TempBuf2 TempBuf3 TempBuf4 USReady ;Flags for every USState (up to 8 US driven) now : 0 / 0 / 0 / 0 / 0 / US3 / US2 / US1 ENDC CBLOCK 0x20 WhatToDo ;Defines the general module actions St / RST / 0 / Ground / SRM / OV / US / IR WhatToSay1 ;Defines the specific module behaviour WhatToSay2 ;Defines the specific module behaviour WhatToSay3 ;Defines the specific module behaviour WhatToSay4 ;Defines the specific module behaviour ENDC CBLOCK 0x30 CNT1 CNT2 CONT1 CONT2 ENDC CBLOCK 0x40 McToPcBuff01 ;Data To Send, IRMeasure 1H McToPcBuff02 ;Data To Send, IRMeasure 1L McToPcBuff03 ;Data To Send, USMeasure 1H McToPcBuff04 ;Data To Send, USMeasure 1L McToPcBuff05 ;Data To Send, IRMeasure 2H McToPcBuff06 ;Data To Send, IRMeasure 2L McToPcBuff07 ;Data To Send, USMeasure 2H McToPcBuff08 ;Data To Send, USMeasure 2L McToPcBuff09 ;Data To Send, IRMeasure 3H McToPcBuff10 ;Data To Send, IRMeasure 3L McToPcBuff11 ;Data To Send, USMeasure 4H McToPcBuff12 ;Data To Send, USMeasure 4L McToPcBuff13 ;Data To Send, IRMeasure 5H McToPcBuff14 ;Data To Send, IRMeasure 5L McToPcBuff15 ;Data To Send, IRMeasure 6H McToPcBuff16 ;Data To Send, IRMeasure 6L McToPcBuff17 ;Data To Send, synchronise byte: 0 ENDC CBLOCK 0x5A McToPcBuff01Bis ;Data To Send, IRMeasure 1H McToPcBuff02Bis ;Data To Send, IRMeasure 1L McToPcBuff03Bis ;Data To Send, USMeasure 1H McToPcBuff04Bis ;Data To Send, USMeasure 1L McToPcBuff05Bis ;Data To Send, IRMeasure 2H McToPcBuff06Bis ;Data To Send, IRMeasure 2L McToPcBuff07Bis ;Data To Send, USMeasure 2H McToPcBuff08Bis ;Data To Send, USMeasure 2L McToPcBuff09Bis ;Data To Send, IRMeasure 3H McToPcBuff10Bis ;Data To Send, IRMeasure 3L McToPcBuff11Bis ;Data To Send, USMeasure 4H McToPcBuff12Bis ;Data To Send, USMeasure 4L McToPcBuff13Bis ;Data To Send, IRMeasure 5H McToPcBuff14Bis ;Data To Send, IRMeasure 5L McToPcBuff15Bis ;Data To Send, IRMeasure 6H McToPcBuff16Bis ;Data To Send, IRMeasure 6L ENDC ORG 0x0000 ;reset vector GOTO MainProg ORG 0x0004 ;interrupt vector GOTO Interrupt ; **************************************************** ; * Main Prog * ; **************************************************** MainProg: BSF STATUS,RP0 CLRF TRISA CLRF TRISB CLRF TRISC BCF STATUS,RP0 CLRF PORTA CLRF PORTB CLRF PORTC clrf McToPcBuff01Bis clrf McToPcBuff02Bis clrf McToPcBuff03Bis clrf McToPcBuff04Bis clrf McToPcBuff05Bis clrf McToPcBuff06Bis clrf McToPcBuff07Bis clrf McToPcBuff08Bis clrf McToPcBuff09Bis clrf McToPcBuff10Bis clrf McToPcBuff11Bis clrf McToPcBuff12Bis clrf McToPcBuff13Bis clrf McToPcBuff14Bis clrf McToPcBuff15Bis clrf McToPcBuff16Bis ; Modules' initial conditions MOVLW B'00010011' MOVWF WhatToDo ; STOP signal, ALL measuring, MOVLW B'00000111' MOVWF USReady ; US permission to fire. CALL SetupSerial ;initialise usart-port to pc CALL SetupSSP ;initialiseI2C communication CALL EnableAllInterrupts ;initialise interrupts ; Buffers' first positions BCF STATUS,RP0 MOVLW H'20' ; Begin PC to MC buffer MOVWF PcToMcPointer MOVLW H'40' MOVWF McToPcPointer ; Begin MC to PC buffer MOVLW D'0' MOVWF McToPcBuff13 ; Sync byte: 0 MOVLW D'0' ;Transmit 0 to start interrupt routines MOVWF TXREG ;and reset PC pointer CALL DEL_50 ;delay 50 ms MAINLOOP ; COMMUNICATE WITH MODULE 1, FIRST SEND, THEN READ call DEL_3 BSF PORTB,0 ;Switch led 1 on BCF PORTB,1 ;switch led 2 off BCF PORTB,2 ;switch led 3 off BCF PORTB,3 ;switch led 4 off MOVF WhatToDo,W MOVWF WhatToSay1 ;information for slave ; ********SEQUENTIAL firing******** ; btfsc USReady,1 ; bsf WhatToSay1,2 ; ********ASAP firing******** ??????moet nog aangepast worden movf USReady,W ; Check if "air is free" andlw b'00000111' xorlw b'00000111' ; Fire only if the rest arenīt busy btfsc STATUS,Z BSF WhatToSay1,2 ; *************************** CALL i2c_on ; Start I2C Bus MOVLW B'01000010' ; Slave Adress Contr 2 Send Operation CALL i2c_tx MOVF WhatToSay1,W ; Send Data to slave what to do CALL i2c_tx CALL i2c_off ; Release Bus bcf USReady,0 ; After sending Op Info, the US might be busy. CALL i2c_on ; Start I2C Bus MOVLW B'01000011' ; Slave Adress Contr 2 Read Operation CALL i2c_tx ; transmit CALL i2c_rx ; receive MOVF SSPBUF,W MOVWF TempBuf1 ; Read Data 1 IR1H CALL i2c_ACK ; aknowledge CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf2 ; Read Data 2 IR1L CALL i2c_ACK CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf3 ; Read Data 3 US1H CALL i2c_ACK CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf4 ; Read Data 4 US1L CALL i2c_off ; Release Bus BSF STATUS,RP0 BCF INTCON,GIE ; Disable all interrupts BCF STATUS,RP0 ; Store data without corruption caused by an interupt MOVF TempBuf1,W MOVWF McToPcBuff01Bis MOVF TempBuf2,W MOVWF McToPcBuff02Bis MOVF TempBuf3,W MOVWF McToPcBuff03Bis MOVF TempBuf4,W MOVWF McToPcBuff04Bis BSF STATUS,RP0 BSF INTCON,GIE ; Enable global interrupts BCF STATUS,RP0 btfsc TempBuf1,6 ;If US finished --> air is free bsf USReady,0 ; COMMUNICATE WITH MODULE 2, FIRST SEND, THEN READ call DEL_3 BCF PORTB,0 ; Switch led 2 on and rest off BSF PORTB,1 BCF PORTB,2 BCF PORTB,3 MOVF WhatToDo,W MOVWF WhatToSay2 ; ********SEQUENTIAL firing******** ; btfsc USReady,0 ; bsf WhatToSay2,2 ; ********ASAP firing******** movf USReady,W ; Check if "air is free" andlw b'00000111' xorlw b'00000111' ; Fire only if the rest arenīt busy btfsc STATUS,Z BSF WhatToSay2,2 ; *************************** CALL i2c_on ; Start I2C Bus MOVLW B'01000100' ; Slave Adress Contr 3 Send Operation CALL i2c_tx MOVF WhatToSay2,W ; Send Data 2 CALL i2c_tx CALL i2c_off ; Release Bus bcf USReady,1 ; After sending Op Info, the US might be busy. CALL i2c_on ; Start I2C Bus MOVLW B'01000101' ; Slave Adress Contr 3 Read Operation CALL i2c_tx CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf1 ; Read Data 1 CALL i2c_ACK CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf2 ; Read Data 2 CALL i2c_ACK CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf3 ; Read Data 3 CALL i2c_ACK CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf4 ; Read Data 4 CALL i2c_off ; Release Bus BSF STATUS,RP0 BCF INTCON,GIE ; Disable all interrupts BCF STATUS,RP0 MOVF TempBuf1,W MOVWF McToPcBuff05Bis MOVF TempBuf2,W MOVWF McToPcBuff06Bis MOVF TempBuf3,W MOVWF McToPcBuff07Bis MOVF TempBuf4,W MOVWF McToPcBuff08Bis BSF STATUS,RP0 BSF INTCON,GIE ; Enable global interrupts BCF STATUS,RP0 btfsc TempBuf1,6 bsf USReady,1 ; COMMUNICATE WITH MODULE 3, FIRST SEND, THEN READ call DEL_3 BCF PORTB,0 BCF PORTB,1 BSF PORTB,2 BCF PORTB,3 MOVF WhatToDo,W MOVWF WhatToSay3 ; ********SEQUENTIAL firing******** ; btfsc USReady,0 ; bsf WhatToSay3,2 ; ********ASAP firing******** movf USReady,W ; Check if "air is free" andlw b'00000111' xorlw b'00000111' ; Fire only if the rest arenīt busy btfsc STATUS,Z BSF WhatToSay3,2 ; *************************** CALL i2c_on ; Start I2C Bus MOVLW B'01000110' ; Slave Adress Contr 3 Send Operation CALL i2c_tx MOVF WhatToSay3,W ; Send Data 2 CALL i2c_tx CALL i2c_off ; Release Bus bcf USReady,2 ; After sending Op Info, the US might be busy. CALL i2c_on ; Start I2C Bus MOVLW B'01000111' ; Slave Adress Contr 3 Read Operation CALL i2c_tx CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf1 ; Read Data 1 CALL i2c_ACK CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf2 ; Read Data 2 CALL i2c_ACK CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf3 ; Read Data 3 CALL i2c_ACK CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf4 ; Read Data 4 CALL i2c_off ; Release Bus BSF STATUS,RP0 BCF INTCON,GIE ; Disable all interrupts BCF STATUS,RP0 MOVF TempBuf1,W MOVWF McToPcBuff09Bis MOVF TempBuf2,W MOVWF McToPcBuff10Bis MOVF TempBuf3,W MOVWF McToPcBuff11Bis MOVF TempBuf4,W MOVWF McToPcBuff12Bis BSF STATUS,RP0 BSF INTCON,GIE ; Enable global interrupts BCF STATUS,RP0 btfsc TempBuf1,6 bsf USReady,2 ; COMMUNICATE WITH GROUND MODULE, FIRST SEND, THEN READ call DEL_3 BCF PORTB,0 BCF PORTB,1 BCF PORTB,2 BSF PORTB,3 ; switch led 4 on MOVF WhatToDo,W MOVWF WhatToSay4 ; information for slave CALL i2c_on ; Start I2C Bus MOVLW B'01001010' ; Slave Adress Contr 4 Send Operation CALL i2c_tx MOVF WhatToSay4,W ; Send Data CALL i2c_tx CALL i2c_off ; Release Bus CALL i2c_on ; Start I2C Bus MOVLW B'01001011' ; Slave Adress Contr 4 Read Operation CALL i2c_tx CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf1 ; Read Data 1 IR5H CALL i2c_ACK CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf2 ; Read Data 2 IR5L CALL i2c_ACK CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf3 ; Read Data 3 IR6H CALL i2c_ACK CALL i2c_rx MOVF SSPBUF,W MOVWF TempBuf4 ; Read Data 4 IR6L CALL i2c_off ; Release Bus BSF STATUS,RP0 BCF INTCON,GIE ; Disable all interrupts BCF STATUS,RP0 MOVF TempBuf1,W MOVWF McToPcBuff13Bis ; Store information MOVF TempBuf2,W MOVWF McToPcBuff14Bis MOVF TempBuf3,W MOVWF McToPcBuff15Bis MOVF TempBuf4,W MOVWF McToPcBuff16Bis BSF STATUS,RP0 BSF INTCON,GIE ; Enable global interrupts BCF STATUS,RP0 GOTO MAINLOOP ; **************************************************** ; * I2C Bus Subroutines * ; **************************************************** i2c_on ; Enable I2C Bus bcf STATUS, RP0 bcf PIR1, SSPIF ; Clear SSPIF bsf STATUS, RP0 bsf SSPCON2, SEN ; enable bus bcf STATUS, RP0 goto i2c_wait i2c_tx ; Send Byte bcf STATUS, RP0 movwf SSPBUF ; Send data in SSPBUF goto i2c_wait i2c_rx ;Receive Byte bsf STATUS, RP0 bsf SSPCON2, RCEN ; Enable Receive bcf STATUS, RP0 goto i2c_wait i2c_ACK ; Send Aknowledge bsf STATUS, RP0 bsf SSPCON2, ACKEN ; Send ACK bcf STATUS, RP0 goto i2c_wait i2c_off ; Release bus bsf STATUS, RP0 bsf SSPCON2, PEN ; Release I2C Bus bcf STATUS, RP0 i2c_wait ; Wait until last command is finished bcf STATUS, RP0 btfss PIR1, SSPIF ; Ready? Stays in loop untill information is received or transmitted goto $-1 ; bcf PIR1, SSPIF ; Yes, clear SSPIF return ; **************************************************** ; * Setup Serial Port in 19200 Baud mode * ; **************************************************** SetupSerial: BSF STATUS,RP0 ; select bank 1 BCF TRISC,6 ; Make RC6 - TX pin an output BSF TRISC,7 ; Make RC7 - RX pin an input BSF TXSTA,BRGH ; Select High Speed mode MOVLW D'25' MOVWF SPBRG ; Select baud rate 19200 in High Speed BCF TXSTA,SYNC ; Select async mode BSF TXSTA,TXEN ; Enable Transmit BCF STATUS,RP0 ; select bank0 movlw 0x90 ; enable serial port and reception movwf RCSTA BSF STATUS,RP0 ; select bank1 movlw 0x30 ; Enable TX and RX interrupts movwf PIE1 BCF STATUS,RP0 return ; **************************************************** ; * Setup SSP Master mode * ; **************************************************** SetupSSP bsf STATUS, RP0 ; Bank 1 BSF TRISC,3 BSF TRISC,4 ; RC3,4 inputs movlw ClockValue movwf SSPADD ; Clockvalue I2C bcf STATUS, RP0 ; Bank 0 movlw B'00001000' ; master mode, clock=Fosc/(4*(SSPADD+1)) movwf SSPCON bsf SSPCON, SSPEN ; MSSP-Module enable RETURN ; **************************************************** ; * enable all interrupts * ; **************************************************** EnableAllInterrupts BSF STATUS,RP0 BSF INTCON,PEIE ; Enable all peripheral interrupts BSF INTCON,GIE ; Enable global interrupts BCF STATUS,RP0 ; **************************************************** ; * Interrupt Routines * ; **************************************************** Interrupt: movwf WREG_TEMP ;save WREG movf STATUS,W ;store STATUS in WREG clrf STATUS ;select file register bank0 movwf STATUS_TEMP ;save STATUS value movf PCLATH,W ;store PCLATH in WREG movwf PCLATH_TEMP ;save PCLATH value clrf PCLATH ;select program memory page0 BCF STATUS,RP0 ;select bank0 btfsc PIR1,RCIF ;test RCIF receive interrupt CALL GetDataFromPC ;if RCIF and RCIE set, do receive BCF STATUS,RP0 btfsc PIR1,TXIF ;test for TXIF transmit interrupt CALL SendDataToPC ;if TXIF and TCIE set, do transmit BCF STATUS,RP0 ;select bank 0 movf PCLATH_TEMP,W ;get saved PCLATH value movwf PCLATH ;restore PCLATH movf STATUS_TEMP,W ;get saved STATUS value movwf STATUS ;restore STATUS swapf WREG_TEMP,F ;prepare WREG to be restored swapf WREG_TEMP,W ;restore WREG without affecting STATUS retfie ;return from interrupt ; **************************************************** ; * Get data from PC and store in PcToMcBuffer * ; **************************************************** GetDataFromPC: BCF STATUS,RP0 btfsc RCSTA,OERR ;test overrun error flag goto ErrOERR ;handle it if error btfsc RCSTA,FERR ;test framing error flag goto ErrFERR ;handle it if error BCF STATUS,IRP ; Clear IRP , choose bank 0 or 1 MOVF PcToMcPointer,W MOVWF FSR ; put the byte-adress in FSR movf RCREG,W ; Get received data BTFSC STATUS,Z ; Is last byte 0 = sync byte GOTO SyncByte MOVWF INDF ; put the information in byte INCF PcToMcPointer,F ; move pointer 1 place MOVF PcToMcPointer,W SUBLW H'21' BTFSS STATUS,Z ; skip if zero, thus McToPcPointer = 21 RETURN SyncByte: MOVLW H'20' MOVWF PcToMcPointer RETURN ErrOERR: bcf RCSTA,CREN ;reset the receiver logic bsf RCSTA,CREN ;enable reception again RETURN ErrFERR: movf RCREG,W ;discard received data that has error RETURN ; **************************************************** ; * Read data from McToPc Buffer and transmit to PC * ; **************************************************** SendDataToPC: BCF STATUS,RP0 BCF STATUS,IRP ; Clear IRP , choose bank 0 or 1 MOVF McToPcPointer,W SUBLW H'50' BTFSC STATUS,Z ; skip if zero, thus McToPcPointer = 50 GOTO SendSyncByte MOVF McToPcPointer,W SUBLW H'40' BTFSS STATUS,Z ; continue if zero, thus McToPcPointer = 40 GOTO NotCopyBlock1AtOnce ; this copies the information in blocks MOVF McToPcBuff01Bis,W MOVWF McToPcBuff01 MOVF McToPcBuff02Bis,W MOVWF McToPcBuff02 MOVF McToPcBuff03Bis,W MOVWF McToPcBuff03 MOVF McToPcBuff04Bis,W MOVWF McToPcBuff04 NotCopyBlock1AtOnce MOVF McToPcPointer,W SUBLW H'44' BTFSS STATUS,Z ; continue if zero, thus McToPcPointer = 44 GOTO NotCopyBlock2AtOnce MOVF McToPcBuff05Bis,W MOVWF McToPcBuff05 MOVF McToPcBuff06Bis,W MOVWF McToPcBuff06 MOVF McToPcBuff07Bis,W MOVWF McToPcBuff07 MOVF McToPcBuff08Bis,W MOVWF McToPcBuff08 NotCopyBlock2AtOnce MOVF McToPcPointer,W SUBLW H'48' BTFSS STATUS,Z ; continue if zero, thus McToPcPointer = 48 GOTO NotCopyBlock3AtOnce MOVF McToPcBuff09Bis,W MOVWF McToPcBuff09 MOVF McToPcBuff10Bis,W MOVWF McToPcBuff10 MOVF McToPcBuff11Bis,W MOVWF McToPcBuff11 MOVF McToPcBuff12Bis,W MOVWF McToPcBuff12 NotCopyBlock3AtOnce MOVF McToPcPointer,W SUBLW H'4C' BTFSS STATUS,Z ; continue if zero, thus McToPcPointer = 4C GOTO NotCopyBlock4AtOnce MOVF McToPcBuff13Bis,W MOVWF McToPcBuff13 MOVF McToPcBuff14Bis,W MOVWF McToPcBuff14 MOVF McToPcBuff15Bis,W MOVWF McToPcBuff15 MOVF McToPcBuff16Bis,W MOVWF McToPcBuff16 NotCopyBlock4AtOnce MOVF McToPcPointer,W MOVWF FSR ; gives the adress MOVF INDF,W ; puts the information in workregister BTFSC STATUS,Z ADDLW D'01' MOVWF TXREG ;Transmit data in W to PC INCF McToPcPointer,F RETURN SendSyncByte MOVLW D'0' MOVWF TXREG ;Transmit data in W to PC MOVLW H'40' MOVWF McToPcPointer RETURN DEL_25: movlw 0x41 ; Set Count2,Count1 for 25 msec delay movwf COUNT2 clrf COUNT1 del_ag incfsz COUNT1, F goto del_ag decfsz COUNT2, F goto del_ag nop return DEL_50: movlw 0x82 ; Set Count2,Count1 for 50 msec delay movwf CNT2 clrf CNT1 del_low incfsz CNT1, F goto del_low decfsz CNT2, F goto del_low nop return DEL_3: movlw 0x05 ; Set Count2,Count1 for 3 msec delay movwf CONT2 clrf CONT1 del_ay incfsz CONT1, F goto del_ay decfsz CONT2, F goto del_ay nop return END ; End of file