📄 sonar_array_module.asm
字号:
; Sonars 1,3,5,7,9,11,13,15 movf CurrentChanM1,w ; Sonar number in range 0 to 15 movwf FSR rlf FSR,f rlf FSR,f ; Multiply by 4 movlw b'11111100' andwf FSR,f ; Make sure 2 LSbits clear movlw SonarDataTable addwf FSR,f ; Add to table start address movf CCPR2L,w movwf INDF incf FSR,f movf CCPR2H,w movwf INDF incf FSR,f movf Timer0,w movwf INDFFinishCCP2 return; ---------------------------------------------------------------------- nop ; Padding to prevent table crossing page boundary nop nop nop nop nop; ----------------------------------------------------------------------ProcessI2C btfsc SSPCON,SSPOV ; Check overflow bit bcf SSPCON,SSPOV ; Make sure overflow bit is clear bsf STATUS,RP0 ; Select Page 1 movf SSPSTAT^0x080,w ; Get I2C status (SSPSTAT register) bcf STATUS,RP0 ; Back to page 0 andlw b'00101101' ; Mask for interesting bits in SSPSTAT movwf SspStatSaved ; Save the result in a variable movlw b'00001001' subwf SspStatSaved,w btfss STATUS,Z ; Is it I2C State 1 (Write, last byte address)? goto I2CNotState1; Write, last byte is address (I2C State 1) movf SSPBUF,w ; Read receive buffer byte (clear BF) movwf I2CRxByte ; Save received byte clrf SMBusState ; Expecting SMBus command code next goto FinishI2C ; Nothing more to do in this stateI2CNotState1 movlw b'00101001' ; Is it I2C State 2 (Write, last byte data)? subwf SspStatSaved,w btfss STATUS,Z goto I2CNotState2 ; No; Write, last byte data (I2C State 2) movf SSPBUF,w ; Read receive buffer byte (clear BF) movwf I2CRxByte ; Save received byte movlw HIGH($+4) movwf PCLATH movf SMBusState,w addwf PCL,f ; Jump table for SMBus state goto I2CState2SMBusState0 goto I2CState2SMBusState1 goto I2CState2SMBusState2 goto I2CState2SMBusState3 goto I2CState2SMBusState4 goto I2CState2SMBusState5 IF ((HIGH($)) != (HIGH($-6))) ERROR("Table crosses page boundary!") ENDIFI2CState2SMBusState0 ; SMBus State 0 (expecting command byte next) movf I2CRxByte,w movwf SMBusCommand ; Save SMBus command code sublw SET_TIMER_ZERO_COMMAND btfss STATUS,Z goto NotSetTimerZeroCommand; Set Timer Zero command (Send Byte) clrf Timer0 movlw 256 - 125 movwf TMR0 clrf SMBusState goto FinishI2CNotSetTimerZeroCommand movf SMBusCommand,w sublw SET_SONAR_POWER_ON_COMMAND btfss STATUS,Z goto NotSetSonarPowerOnCommand; Set Sonar Power On Command (Send Byte) bsf SonarPowerState,0 clrf SMBusState goto FinishI2CNotSetSonarPowerOnCommand movf SMBusCommand,w sublw SET_SONAR_POWER_OFF_COMMAND btfss STATUS,Z goto NotSetSonarPowerOffCommand; Set Sonar Power Off Command (Send Byte) clrf SonarPowerState call ClearSonarDataTable clrf SMBusState goto FinishI2CNotSetSonarPowerOffCommand movf SMBusCommand,w sublw SET_NUM_SONARS_COMMAND btfss STATUS,Z goto NotSetNumSonarsCommand; Set Num Sonars Command movlw 1 movwf SMBusState ; Next SMBus state = 1 goto FinishI2CNotSetNumSonarsCommand movf SMBusCommand,w sublw GET_NUM_SONARS_COMMAND btfss STATUS,Z goto NotGetNumSonarsCommand; Get Num Sonars Command movlw 1 movwf SMBusState ; Next SMBus state = 1 goto FinishI2CNotGetNumSonarsCommand movf SMBusCommand,w sublw GET_SONAR_POWER_STATE_COMMAND btfss STATUS,Z goto NotGetSonarPowerStateCommand; Get Sonar Power State Command movlw 1 movwf SMBusState ; Next SMBus state = 1 goto FinishI2CNotGetSonarPowerStateCommand; Assume it's a GET_SONAR_READING_COMMAND movlw 2 movwf SMBusState ; Next SMBus state = 2 goto FinishI2CI2CState2SMBusState1 ; SMBus state 1 (transferring data byte) movf SMBusCommand,w sublw SET_NUM_SONARS_COMMAND btfss STATUS,Z goto NotSetNumSonarsCommand2; Set Num Sonars Command movf I2CRxByte,w movwf NumEnabledChans call WriteNumEnabledChansEEPROM clrf SMBusState goto FinishI2CNotSetNumSonarsCommand2 clrf SMBusState goto FinishI2CI2CState2SMBusState2 ; SMBus state 2 (transferring num data bytes) clrf SMBusState goto FinishI2CI2CState2SMBusState3 ; SMBus state 3 (1st data byte in block) clrf SMBusState goto FinishI2CI2CState2SMBusState4 ; SMBus state 4 (2nd data byte in block) clrf SMBusState goto FinishI2CI2CState2SMBusState5 ; SMBus state 5 (3rd data byte in block) clrf SMBusState goto FinishI2CI2CNotState2 movlw b'00001100' ; I2C state 3 (Read, last byte address)? subwf SspStatSaved,w btfss STATUS,Z goto I2CNotState3 ; No; Read, last byte address (I2C State 3) movlw HIGH($+4) movwf PCLATH movf SMBusState,w addwf PCL,f ; SMBus state jump table goto I2CState3SMBusState0 goto I2CState3SMBusState1 goto I2CState3SMBusState2 goto I2CState3SMBusState3 goto I2CState3SMBusState4 goto I2CState3SMBusState5 IF ((HIGH($)) != (HIGH($-6))) ERROR("Table crosses page boundary!") ENDIFI2CState3SMBusState0 movlw 0 ; Shouldn't be here, but the master is call WriteI2C ; expecting data, so we must oblige. goto FinishI2C I2CState3SMBusState1 ; SMBus state 1 (transferring data byte) movf SMBusCommand,w sublw GET_NUM_SONARS_COMMAND btfss STATUS,Z goto NotGetNumSonarsCommand3; Get Num Sonars Command movf NumEnabledChans,w call WriteI2C clrf SMBusState goto FinishI2CNotGetNumSonarsCommand3 movf SMBusCommand,w sublw GET_SONAR_POWER_STATE_COMMAND btfss STATUS,Z goto NotGetSonarPowerState3; Get Sonar Power State movf SonarPowerState,w call WriteI2C clrf SMBusState goto FinishI2CNotGetSonarPowerState3 movlw 0 ; Shouldn't be here, but the master is call WriteI2C ; expecting data, so we must oblige. goto FinishI2C I2CState3SMBusState2 ; SMBus state 2 (num bytes) movf SMBusCommand,w sublw GET_SONAR_READING_COMMAND_MAX btfss STATUS,C ; Skip if command <= maximum reading command goto I2CState3SMBusState2NotValid; SMBusCommand <= GET_SONAR_READING_COMMAND_MAX; Now check minimum movlw GET_SONAR_READING_COMMAND_MIN subwf SMBusCommand,w btfss STATUS,C ; Skip if command >= minimum reading command goto I2CState3SMBusState2NotValid; SMBusCommand >= GET_SONAR_READING_COMMAND_MIN; Sonar reading command is valid movlw 3 call WriteI2C movlw 3 movwf SMBusState ; Next byte to transfer should be data goto FinishI2C I2CState3SMBusState2NotValid movlw 0 ; Shouldn't be here, but the master is call WriteI2C ; expecting data, so we must oblige. goto FinishI2C I2CState3SMBusState3 ; SMBus state 3 (1st data - block read) movlw 0 ; Shouldn't be here, but the master is call WriteI2C ; expecting data, so we must oblige. goto FinishI2C I2CState3SMBusState4 ; SMBus state 4 (2nd data - block read) movlw 0 ; Shouldn't be here, but the master is call WriteI2C ; expecting data, so we must oblige. goto FinishI2C I2CState3SMBusState5 ; SMBus state 5 (3rd data - block read) movlw 0 ; Shouldn't be here, but the master is call WriteI2C ; expecting data, so we must oblige. goto FinishI2C I2CNotState3 movlw b'00101100' ; I2C state 4 (Read, last byte data)? subwf SspStatSaved,w btfss STATUS,Z goto I2CNotState4 ; No; Read, last byte data (I2C State 4) movlw HIGH($+4) movwf PCLATH movf SMBusState,w addwf PCL,f ; SMBus state jump table goto I2CState4SMBusState0 goto I2CState4SMBusState1 goto I2CState4SMBusState2 goto I2CState4SMBusState3 goto I2CState4SMBusState4 goto I2CState4SMBusState5 IF ((HIGH($)) != (HIGH($-6))) ERROR("Table crosses page boundary!") ENDIFI2CState4SMBusState0 movlw 0 ; Shouldn't be here, but the master is call WriteI2C ; expecting data, so we must oblige. goto FinishI2C I2CState4SMBusState1 movlw 0 ; Shouldn't be here, but the master is call WriteI2C ; expecting data, so we must oblige. goto FinishI2C I2CState4SMBusState2 movlw 0 ; Shouldn't be here, but the master is call WriteI2C ; expecting data, so we must oblige. goto FinishI2C I2CState4SMBusState3 ; SMBus state 3 (1st data - block read) btfss SonarPowerState,0 goto I2CState4SMBusState3PowerOff decf SMBusCommand,w ; Sonar number in range 0 to 15 movwf FSR rlf FSR,f rlf FSR,f ; Multiply by 4 movlw b'11111100' andwf FSR,f ; Make sure 2 LSbits clear movlw SonarDataTable addwf FSR,f ; Add to table start address movf INDF,w movwf SonarBuffer0 ; Capture current sonar reading incf FSR,f movf INDF,w movwf SonarBuffer1 incf FSR,f movf INDF,w movwf SonarBuffer2SendFirstDataByte movf SonarBuffer0,w call WriteI2C movlw 4 movwf SMBusState goto FinishI2C I2CState4SMBusState3PowerOff clrf SonarBuffer0 ; When power's off, send 0,0,0 clrf SonarBuffer1 clrf SonarBuffer2 goto SendFirstDataByteI2CState4SMBusState4 ; SMBus state 4 (2nd data - block read) movf SonarBuffer1,w call WriteI2C movlw 5 movwf SMBusState goto FinishI2C I2CState4SMBusState5 ; SMBus state 5 (3rd data - block read) movf SonarBuffer2,w call WriteI2C clrf SMBusState goto FinishI2C I2CNotState4 movlw b'00101000' ; Nack received from master after reading data? subwf SspStatSaved,w btfss STATUS,Z goto FinishI2C ; No. Impossible state.; Nack received from master (I2C State 5) clrf SMBusState ; SMBus state is expecting command nextFinishI2C return; ----------------------------------------------------------------------WriteI2C bsf STATUS,RP0 btfsc SSPSTAT^0x080,BF ; Buffer full? goto $-1 ; Spin until it isn't bcf STATUS,RP0 bcf SSPCON,WCOL ; Clear write collision flag movwf SSPBUF btfsc SSPCON,WCOL ; Did collision occur? goto $-3 bsf SSPCON,CKP ; Release clock return; ----------------------------------------------------------------------ClearSonarDataTable movlw SonarDataTable movwf FSR movlw 64 movwf CounterClearLoop clrf INDF incf FSR,f decfsz Counter,f goto ClearLoop return; ----------------------------------------------------------------------; Global interrupts are assumed to be disabled before this subroutine is calledWriteNumEnabledChansEEPROM bsf STATUS,RP1 bcf STATUS,RP0 movwf EEDATA^0x100 movlw NUM_ENABLED_CHANS_EE_ADDR movwf EEADR^0x100 bsf STATUS,RP0 bcf EECON1^0x180,EEPGD bsf EECON1^0x180,WREN movlw 0x055 movwf EECON2^0x180 movlw 0x0AA movwf EECON2^0x180 bsf EECON1^0x180,WR btfsc EECON1^0x180,WR goto $-1 bcf EECON1^0x180,WREN bcf STATUS,RP0 bcf STATUS,RP1 return; ----------------------------------------------------------------------GetNumEnabledChansEEPROM bsf STATUS,RP1 bcf STATUS,RP0 movlw NUM_ENABLED_CHANS_EE_ADDR movwf EEADR^0x100 bsf STATUS,RP0 bcf EECON1^0x180,EEPGD bsf EECON1^0x180,RD bcf STATUS,RP0 movf EEDATA^0x100,w bcf STATUS,RP1 return; ----------------------------------------------------------------------Delay10us nop nop nop nop nop nop nop nop nop nop return; ----------------------------------------------------------------------InitInterrupts; Enable interrupts. bsf STATUS,RP0 bcf STATUS,RP1 bsf PIE1^0x080,SSPIE ; Enable I2C interrupt bsf PIE1^0x080,CCP1IE ; Enable CCP1 interrupt bsf PIE2^0x080,CCP2IE ; Enable CCP2 interrupt bcf STATUS,RP0 clrf INTCON bsf INTCON,PEIE ; Enable unmasked peripheral interrupts bsf INTCON,T0IE ; Enable timer 0 interrupt bsf INTCON,GIE ; Global Interrupt Enable return; ----------------------------------------------------------------------InitCapture movlw b'00000101' ; Capture mode every rising edge. movwf CCP1CON movwf CCP2CON bcf PIR1,CCP1IF ; Clear any possible false interrupt. bcf PIR2,CCP2IF ; Clear any possible false interrupt. return; ----------------------------------------------------------------------InitTimer; Configure timer 0 bsf STATUS,RP0 bcf STATUS,RP1 bcf OPTION_REG^0x080,T0CS ; Select Timer 0 Mode bcf OPTION_REG^0x080,PSA ; Assign prescaler to Timer 0 bcf OPTION_REG^0x080,PS0 bsf OPTION_REG^0x080,PS1 bcf OPTION_REG^0x080,PS2 ; Set timer 0 prescaler bcf STATUS,RP0 movlw 256 - 125 movwf TMR0 movlw 25 movwf Timer0tmp; Set timer 1 to 1 microsecond period bcf T1CON,T1CKPS0 bcf T1CON,T1CKPS1 ; Set timer 1 prescaler bcf T1CON,T1OSCEN ; Disable built-in oscillator bcf T1CON,TMR1CS ; Use Fosc/4 as source for timer 1 bsf T1CON,TMR1ON ; Turn on timer 1 return; ----------------------------------------------------------------------InitIO; Initialize port A, B and C clrf PORTA clrf PORTB clrf PORTC bsf STATUS,RP0 bcf STATUS,RP1 movlw b'00000110' movwf ADCON1^0x80 ; Not using ADC - set to I/O clrf TRISA^0x080 clrf TRISB^0x080 movlw b'00011110' movwf TRISC^0x080 bcf STATUS,RP0 return; ----------------------------------------------------------------------InitI2C clrf SMBusState bcf SSPCON,SSPM3 ; SSPM<3:0> = 0110 bsf SSPCON,SSPM2 ; (7-bit address slave mode) bsf SSPCON,SSPM1 bcf SSPCON,SSPM0 bsf SSPCON,CKP ; SCK release control: Enable Clock bcf SSPCON,SSPOV ; Make sure overflow bit is clear movf SSPBUF,w ; Read SSPBUF to ensure buffer flag BF is clear movlw I2C_ADDRESS << 1 bsf STATUS,RP0 bcf STATUS,RP1 movwf SSPADD^0x080 ; I2C slave address of this device bcf SSPSTAT^0x080,CKE ; Select I2C input levels bsf SSPSTAT^0x080,SMP ; Slew rate control disabled bcf STATUS,RP0 bsf SSPCON,SSPEN ; Enable I2C return; ----------------------------------------------------------------------; End end
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -