📄 power_management_module.asm
字号:
; $Id: power_management_module.asm,v 1.12 2003/10/05 05:56:53 dwalters Exp $; Copyright (C) 2003 Dafydd Walters <dwalters@users.sourceforge.net>;; This program is free software; you can redistribute it and/or modify; it under the terms of the GNU General Public License as published by; the Free Software Foundation; either version 2 of the License, or; (at your option) any later version.;; This program is distributed in the hope that it will be useful,; but WITHOUT ANY WARRANTY; without even the implied warranty of; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the; GNU General Public License for more details.;; You should have received a copy of the GNU General Public License; along with this program (COPYING.SOFTWARE); if not, write to the ; Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, ; MA 02111-1307 USA; ---------------------------------------------------------------------- title "power_management_module.asm - OAP Power Management Module" processor pic16f819 list r=dec ; set radix to decimal include "p16f819.inc"; ----------------------------------------------------------------------; Analog Inputs; AN0 - Charging voltage (Vc) from docking station; AN1 - External Supply voltage (Ve) from docking station; AN3 - Battery voltage (Vb);; Digital Inputs:; RB0 - Charging voltage terminal docking microswitch; RB6 - External power supply terminal docking microswitch; RB7 - Ground terminal docking microswitch;; Digital Outputs:; RB2 - Charger power control; RA7 - External supply power control; RA2 - LED # 1 (green) - Charging; RA4 - LED # 2 (red) - Error; RB3 - LED # 3 (IR LED); ; I2C (initially inputs):; RB4 - SCL; RB1 - SDA;; Not Used:; RA5; RA6; RB5; ----------------------------------------------------------------------; Device states and transitions:;; Initial power on:; - turn off LEDs; - turn off both on-board relays; - instruct docking station to turn off both of its relays; - reset state 1 timer; - enter state 1; ; 1. In this state, the contact switches are polled.;; When all 3 switches have been closed for at least 1 second:; - instruct docking station to turn on external power supply; - reset state 2 timers; - enter state 2.;; 2. Poll external supply voltage and switches.; ; If any of the contact switches opens:; - instruct docking station to turn off external supply relay; - reset state 1 timer; - enter state 1;; If this state has been active for over 2s:; - instruct docking station to turn off external supply relay; - turn on red LED; - set error code to 1 (probably just bad docking - robot should retry); - enter state 4;; If external supply voltage is good (>=11.7V) for at least 1s:; - turn on external supply relay; - delay 0.25s; - record off-load battery voltage Vo; - turn on charge relay; - delay 0.25s; - instruct docking station to turn on charger relay; - turn on green LED; - reset state 3 timers; - enter state 3;; 3. Poll voltages and switches.;; If it's been 17 seconds since "pinging" docking station; - "ping" the docking station;; If external supply voltage drops below 11.7V:; - instruct docking station to stop charging; - delay 1/6s; - turn off charging relay; - delay 1/6s; - turn off external supply relay; - turn off green LED; - reset state 2 timers; - enter state 2;; If any of the contact switches opens:; - instruct docking station to stop charging; - delay 1/6s; - turn off charging relay; - delay 1/6s; - turn off external supply relay; - turn off green LED; - instruct docking station to stop external supply; - reset state 1 timer; - enter state 1;; If battery voltage falls below Vo for more than 1 minute:; - instruct docking station to stop charging; - delay 1/6s; - turn off charging relay; - delay 1/6s; - turn off external supply relay; - turn off green LED; - instruct docking station to stop external supply; - turn on red LED; - set error code to 2 (probably just bad docking - robot should retry); - enter state 4;; 4. Await polling of error status from host via I2C.;; After host polls error status:; - turn off red LED; - reset state 1 timer; - enter state 1;;; I2C and SMBus:; ; The SMBus protocol commands are handled entirely in the interrupt handling; code. The Power Management Module appears as a slave device on the I2C bus.; Each time an I2C interrupt is detected, the interrupt handler code; determines which of the following 5 states the I2C interface is in:; ; - State1: Host wants to write (send) a byte to us, and has just sent us ; our device address. In this state, we must read (and discard) the; address from the receive buffer. The device does not need to take; any further action in response to this state. We should be seeing; State2 next.;; - State2: Host has just finished sending a byte to us. We must read the data; byte from the receive buffer, and act on it (what we do at this; point depends on whether we were expecting a command byte from the; host, or whether we had already recevied that, and are now waiting; for data from the host).;; - State3: Host wants to read a byte from us, and has just sent us our device; address. We must first read the address, and then write a byte to; the buffer (this would typically be a response to host's request; for data).;; - State4: Host has just read a byte from us, and is now expecting us to send; another byte. This state is for transfers of more than one byte; This state should never occur in this application. However, if we; ever find ourselves in this state, we're obliged to send dummy ; data to the host to satisfy protocol requirements.;; - State5: Host has just read a byte from us, and does NOT expect us to send; any more. The device does not need to do anything in response to; this state.;; The interrupt handler also keeps track of which of two states the SMBus; transfers are in as follows:;; - State 0: Waiting for a command byte from the host.;; - State 1: Transferring a data byte (either reading or writing) to/from host.;; We can sometimes set the SMBus state according to which state the I2C ; interface is in. For example, in response to I2C State1 or State5, we know; that the next byte we receive from the host should be a SMBus command, so we; set the SMBus state to 0.;; If we're handling I2C State2 and we've just received a SMBus command (SMBus; state was 0), the next byte we receive will be data, so we set the SMBus; state to 1. ;; See the README document for more information on the SMBus commands that; are implemented by this device.; ; ----------------------------------------------------------------------; Constants#define GOOD_EXT_VOLTAGE_EE_ADDR 0#define I2C_ADDRESS 86#define TMR0_ONE_SEC 15#define TMR1_ONE_SEC 4#define GREEN_LED PORTA,2#define RED_LED PORTA,4#define IR_LED PORTB,3#define CHARGER_RELAY PORTB,2#define EXT_SUPPLY_RELAY PORTA,7#define SWITCH_MASK 0x0C1; SMBus commands from Host:#define READ_BATT_VOLTAGE_COMMAND 1#define READ_EXT_VOLTAGE_COMMAND 2#define READ_CHARGER_VOLTAGE_COMMAND 3#define READ_STATE_COMMAND 4#define READ_ERROR_CODE_COMMAND 5#define READ_SWITCHES_COMMAND 6#define READ_GOOD_EXT_THRESHOLD_COMMAND 7#define WRITE_GOOD_EXT_THRESHOLD_COMMAND 100; IR commands to Docking Station:#define TURN_ON_EXT_COMMAND b'11100001'#define TURN_ON_CHARGER_COMMAND b'11100010'#define PING_COMMAND b'11100100'#define TURN_OFF_CHARGER_COMMAND b'11100101'#define TURN_OFF_EXT_COMMAND b'11100110'; ----------------------------------------------------------------------; Variable Declarations (GPR) starting at data address 0x020 cblock 0x020HiCount ; Used in delay loopsState ; Current state of device (see comments above)SwitchState ; Current state of switchesErrorCode ; Current error code (when device is state 4)Vc ; Charge voltageVe ; External supply voltageVb ; Battery voltageVo ; Off-load battery voltageExtSupplyGoodThreshold ; External power supply good threshold voltageTimer0 ; Interrupt driven down counter, 1/15s periodTimer1 ; Interrupt driven down counter, 1/4s periodSMBusCommand ; Most recent SMBus command from hostSMBusState ; Current SMBus state (see comments above)I2CRxByte ; Most recent I2C byte received from hostIRData ; Temporary variable used to store IR command SendBuffer ; Temporary variable for shifting IR dataBitCount ; Counter variable used in transmitting IR dataSspStatSaved ; Temporary variable to hold SSPSTAT registerSavedW ; Variable to hold saved register during ISRSavedStatus ; Variable to hold saved register during ISRSavedFSR ; Variable to hold saved register during ISRSavedPCLATH ; Variable to hold saved register during ISR endc; ----------------------------------------------------------------------; Configuration bits: ;; - Flash Code Protection off; - CCP1 on RB3; - In-circuit Debugger disabled; - Flash program memory write enable off; - EE Code Protection off; - Low Voltage Programming Enable off, RB3 is I/O; - Brown-out Reset Enable on; - RA5/MCLR pin function is digital I/O; - Power-Up Timer on; - Watchdog Timer off; - Oscillator: INTRC, port I/O function of RA6 and RA7 __CONFIG _CP_OFF & _CCP1_RB3 & _DEBUG_OFF & _WRT_ENABLE_OFF & _CPD_OFF & _LVP_OFF & _BODEN_ON & _MCLR_OFF & _PWRTE_ON & _WDT_OFF & _INTRC_IO; ----------------------------------------------------------------------; Program entry point at device reset org 0 goto MainStart; ----------------------------------------------------------------------; Interrupt Handler entry point org 4 goto IntStart; ----------------------------------------------------------------------; Interrupt handler start pointIntStart movwf SavedW ; Save W movf STATUS,w bcf STATUS,RP0 ; Make sure we're on Page 0 bcf STATUS,RP1 movwf SavedStatus ; Save STATUS movf FSR,w movwf SavedFSR ; Save FSR movf PCLATH,w movwf SavedPCLATH ; Save PCLATH clrf PCLATH ; Execution page 0 btfss INTCON,TMR0IF goto NotTimer0; Timer0 bcf INTCON,TMR0IF ; TMR0 interrupt every 1/15s approx. movf Timer0,f btfsc STATUS,Z goto FinishISR decf Timer0,f ; Decrement Timer0 if not zero. goto FinishISRNotTimer0 btfss PIR1,TMR1IF goto NotTimer1; Timer1 bcf PIR1,TMR1IF ; TMR1 interrupt every 1/4s approx. movf Timer1,f btfsc STATUS,Z goto FinishISR decf Timer1,f ; Decrement Timer1 if not zero. goto FinishISRNotTimer1 btfss PIR1,SSPIF goto FinishISR; I2C bcf PIR1,SSPIF ; Clear interrupt flag 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 FinishISR ; 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 movf SMBusState,w addwf PCL,f ; Jump table for SMBus state goto I2CState2SMBusState0 goto I2CState2SMBusState1 IF ((HIGH($)) != (HIGH($-3))) ERROR("Table crosses page boundary!") ENDIFI2CState2SMBusState0 ; SMBus State 0 (expecting command byte next)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -