📄 power_management_module.asm
字号:
movf I2CRxByte,w movwf SMBusCommand ; Save SMBus command code movlw 1 movwf SMBusState ; Next SMBus state = 1 goto FinishISRI2CState2SMBusState1 movf SMBusCommand,w sublw WRITE_GOOD_EXT_THRESHOLD_COMMAND btfss STATUS,Z ; Is this command 100? goto EndProcessWriteCommand ; No; Set good external voltage threshold movf I2CRxByte,w movwf ExtSupplyGoodThreshold call WriteGoodExtVoltageEepromEndProcessWriteCommand clrf SMBusState ; Expecting SMBus command code byte next goto FinishISRI2CNotState2 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) movf SMBusState,w addwf PCL,f ; SMBus state jump table goto I2CState3SMBusState0 goto I2CState3SMBusState1 IF ((HIGH($)) != (HIGH($-3))) ERROR("Table crosses page boundary!") ENDIFI2CState3SMBusState0 clrf SSPBUF ; Shouldn't be here, but the master is bsf SSPCON,CKP ; expecting data, so we must oblige. goto FinishISR I2CState3SMBusState1 movf SMBusCommand,w sublw READ_BATT_VOLTAGE_COMMAND btfss STATUS,Z goto I2CNotBattCommand; Read Battery voltage movf Vb,w ; Battery voltage movwf SSPBUF ; Put transmit data in buffer bsf SSPCON,CKP ; SCK release control: Enable Clock clrf SMBusState ; SMBus state is expecting command next goto FinishISRI2CNotBattCommand movf SMBusCommand,w sublw READ_EXT_VOLTAGE_COMMAND btfss STATUS,Z goto I2CNotExtCommand; Read External voltage movf Ve,w ; External voltage movwf SSPBUF ; Put transmit data in buffer bsf SSPCON,CKP ; SCK release control: Enable Clock clrf SMBusState ; SMBus state is expecting command next goto FinishISRI2CNotExtCommand movf SMBusCommand,w sublw READ_CHARGER_VOLTAGE_COMMAND btfss STATUS,Z goto I2CNotChargerCommand; Read Charger voltage movf Vc,w ; Charger voltage movwf SSPBUF ; Put transmit data in buffer bsf SSPCON,CKP ; SCK release control: Enable Clock clrf SMBusState ; SMBus state is expecting command next goto FinishISRI2CNotChargerCommand movf SMBusCommand,w sublw READ_STATE_COMMAND btfss STATUS,Z goto I2CNotStateCommand; Read State movf State,w ; State movwf SSPBUF ; Put transmit data in buffer bsf SSPCON,CKP ; SCK release control: Enable Clock clrf SMBusState ; SMBus state is expecting command next goto FinishISRI2CNotStateCommand movf SMBusCommand,w sublw READ_ERROR_CODE_COMMAND btfss STATUS,Z goto I2CNotErrorCodeCommand; Read Error Code movf ErrorCode,w ; Error Code movwf SSPBUF ; Put transmit data in buffer bsf SSPCON,CKP ; SCK release control: Enable Clock clrf SMBusState ; SMBus state is expecting command next movf State,w sublw 4 btfss STATUS,Z goto FinishISR; Reset Error State clrf State goto FinishISRI2CNotErrorCodeCommand movf SMBusCommand,w sublw READ_SWITCHES_COMMAND btfss STATUS,Z goto I2CNotSwitchesCommand; Read Switches movf SwitchState,w ; Switch state movwf SSPBUF ; Put transmit data in buffer bsf SSPCON,CKP ; SCK release control: Enable Clock clrf SMBusState ; SMBus state is expecting command next goto FinishISRI2CNotSwitchesCommand movf SMBusCommand,w sublw READ_GOOD_EXT_THRESHOLD_COMMAND btfss STATUS,Z goto I2CNotReadExtThresholdCommand; Read good external threshold movf ExtSupplyGoodThreshold,w ; Good external supply threshold voltage movwf SSPBUF ; Put transmit data in buffer bsf SSPCON,CKP ; SCK release control: Enable Clock clrf SMBusState ; SMBus state is expecting command next goto FinishISRI2CNotReadExtThresholdCommand clrf SSPBUF ; Shouldn't be here, but the master is bsf SSPCON,CKP ; expecting data, so we must oblige. goto FinishISR 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) movf SMBusState,w addwf PCL,f ; SMBus state jump table goto I2CState4SMBusState0 goto I2CState4SMBusState1 IF ((HIGH($)) != (HIGH($-3))) ERROR("Table crosses page boundary!") ENDIFI2CState4SMBusState0 clrf SSPBUF ; Shouldn't be here, but the master is bsf SSPCON,CKP ; expecting data, so we must oblige. goto FinishISR I2CState4SMBusState1 clrf SSPBUF ; Shouldn't be here, but the master is bsf SSPCON,CKP ; expecting data, so we must oblige. goto FinishISR I2CNotState4 movlw b'00101000' ; Nack received from master after reading data? subwf SspStatSaved,w btfss STATUS,Z goto FinishISR ; No. Impossible state.; Nack received from master (I2C State 5) clrf SMBusState ; SMBus state is expecting command next goto FinishISR ; Nothing further to doFinishISR movf SavedPCLATH,w movwf PCLATH ; Restore PCLATH movf SavedFSR,w movwf FSR ; Restore FSR movf SavedStatus,w movwf STATUS ; Restore STATUS swapf SavedW,f swapf SavedW,w ; Restore W (without affecting Z,C flags,etc) retfie; ----------------------------------------------------------------------; Main Program start pointMainStart call InitClock ; Initialize internal clock oscillator call GetGoodExtVoltageEeprom ; Read setting from EEPROM movwf ExtSupplyGoodThreshold ; Store it in a variable for convenience call InitADC ; Initialize the ADC call InitIO ; Initialize IO ports call InitTimer ; Initialize Timer call InitI2C ; Initialize the I2C interface call InitInterrupts ; Enable interrupts clrf State ; Start in device state 0MainLoop call ReadVoltages ; Populate the variables Vb, Vc and Ve call ReadSwitches ; Populate the variable SwitchState movf State,w addwf PCL,f ; Jump table for the current State goto State0 ; State 0: Device Reset (transient state -> 1) goto State1 ; State 1: Waiting for microswitches goto State2 ; State 2: Waiting for good external power goto State3 ; State 3: Charging goto State4 ; State 4: Error (safe mode - relays off) IF ((HIGH($)) != (HIGH(MainLoop))) ERROR("Table crosses page boundary!") ENDIF; --- Device Reset (momentary state to initialize device)State0 bsf GREEN_LED ; Green LED off bsf RED_LED ; Red LED off bcf CHARGER_RELAY ; Charger relay off bcf EXT_SUPPLY_RELAY ; External supply relay off movlw TURN_OFF_EXT_COMMAND ; Tell docking station: both relays off call BeamToDockingStation movlw TMR0_ONE_SEC * 1 movwf Timer0 movlw 1 movwf State ; Go to state 1 next goto MainLoop; --- Waiting for microswitchesState1 movf SwitchState,w btfss STATUS,Z goto State1SwitchOpen ; At least one switch open; All switches closed movf Timer0,w btfss STATUS,Z goto MainLoop; Switches have been closed for at least 1s movlw TURN_ON_EXT_COMMAND ; Tell docking station to turn on ext power call BeamToDockingStation movlw TMR1_ONE_SEC * 2 movwf Timer1 ; Timer1 = state 2 timeout movlw TMR0_ONE_SEC * 1 movwf Timer0 ; Timer0 = good voltage time movlw 2 movwf State ; Go to state 2 next goto MainLoopState1SwitchOpen movlw TMR0_ONE_SEC * 1 movwf Timer0 goto MainLoop; --- Waiting for good external power supply voltageState2 movf SwitchState,w btfsc STATUS,Z goto State2SwitchesClosed; At least one switch is open movlw TURN_OFF_EXT_COMMAND ; Tell docking station to turn off ext supply call BeamToDockingStation movlw TMR0_ONE_SEC * 1 movwf Timer0 movlw 1 movwf State ; Go to state 1 next goto MainLoopState2SwitchesClosed movf Timer1,w btfss STATUS,Z goto State2NotTimedOut; Timeout movlw TURN_OFF_EXT_COMMAND ; Tell docking station to turn off ext power call BeamToDockingStation bcf RED_LED ; Turn on red LED movlw 1 movwf ErrorCode ; Set error code to 1 movlw 4 movwf State ; Change to state 4 goto MainLoopState2NotTimedOut movf ExtSupplyGoodThreshold,w subwf Ve,w ; Calculate Ve-Vthreshold btfsc STATUS,C goto State2VoltageAtLeastThreshold; External supply voltage is below threshold movlw TMR0_ONE_SEC * 1 movwf Timer0 goto MainLoopState2VoltageAtLeastThreshold movf Timer0,w btfss STATUS,Z goto MainLoop; Threshold voltage for at least a second bsf EXT_SUPPLY_RELAY ; Turn on ext supply relay movlw TMR0_ONE_SEC / 4 movwf Timer0 movf Timer0,w btfss STATUS,Z goto $-2 ; Delay 0.25s call ReadVoltages movf Vb,w movwf Vo ; Record off-load battery voltage, store in Vo bsf CHARGER_RELAY ; Turn on charge relay movlw TMR0_ONE_SEC / 4 movwf Timer0 movf Timer0,w btfss STATUS,Z goto $-2 ; Delay 0.25s movlw TURN_ON_CHARGER_COMMAND ; Tell docking station to turn on its charger call BeamToDockingStation bcf GREEN_LED ; Turn on green LED clrf Timer0 ; First ping ASAP movlw TMR1_ONE_SEC * 60 movwf Timer1 movlw 3 movwf State ; Change to state 3 goto MainLoop; --- Charging StateState3 movf Timer0,w btfss STATUS,Z goto State3DonePing; Ping docking station movlw PING_COMMAND ; Send "ping" to Docking Station call BeamToDockingStation movlw TMR0_ONE_SEC * 17 movwf Timer0State3DonePing movf ExtSupplyGoodThreshold,w subwf Ve,w ; Calculate Ve-Vthreshold btfsc STATUS,C goto State3VoltageAtLeastThreshold; External supply voltage is below threshold movlw TURN_OFF_CHARGER_COMMAND ; instruct docking station to stop charging call BeamToDockingStation movlw TMR0_ONE_SEC / 6 movwf Timer0 movf Timer0,w btfss STATUS,Z goto $-2 ; Delay 1/6s bcf CHARGER_RELAY ; turn off charging relay movlw TMR0_ONE_SEC / 6 movwf Timer0 movf Timer0,w btfss STATUS,Z goto $-2 ; Delay 1/6s bcf EXT_SUPPLY_RELAY ; turn off external supply relay bsf GREEN_LED ; turn off green LED movlw TMR1_ONE_SEC * 2 movwf Timer1 ; Timer1 = state 2 timeout movlw TMR0_ONE_SEC * 1 movwf Timer0 ; Timer0 = good voltage time movlw 2 movwf State ; Go to state 2 next goto MainLoopState3VoltageAtLeastThreshold movf SwitchState,w btfsc STATUS,Z goto State3SwitchesClosed; At least one switch is open movlw TURN_OFF_CHARGER_COMMAND ; tell docking station to stop charging call BeamToDockingStation movlw TMR0_ONE_SEC / 6 movwf Timer0 movf Timer0,w btfss STATUS,Z goto $-2 ; Delay 1/6s bcf CHARGER_RELAY ; turn off charging relay movlw TMR0_ONE_SEC / 6 movwf Timer0
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -