📄 smbus.c
字号:
return SMBerr_ReservedCommand; //unused
}
unsigned char SMBR_Opt2(void) // 0x3E
{
return SMBerr_ReservedCommand; //unused
}
unsigned char SMBR_Opt1(void) // 0x3F
{
return SMBerr_ReservedCommand; //unused
}
unsigned char SMBR_invalid(void) //This should never execute, if error is caught early!
{
return SMBerr_UnsuptdCommand;
}
//typedef unsigned char (*ptr2funcUC_V)(void);
//Table of pointers to functions, indexed from the received SMBus Command byte.
ptr2funcUC_V SMB_ReadCmd[HIGHEST_SMB_CMD+1] =
{
SMBR_MfrAccess, // 0
SMBR_RemCapAlm, // 1
SMBR_RemTimeAlm, // 2
SMBR_BattMode, // 3
SMBR_AtRate, // 4
SMBR_AtRateTTF, // 5
SMBR_AtRateTTE, // 6
SMBR_AtRateOK, // 7
SMBR_Temperature, // 8
SMBR_Voltage, // 9
SMBR_Current, // 10
SMBR_AvgCurrent, // 11
SMBR_MaxError, // 12
SMBR_RelSOC, // 13
SMBR_AbsSOC, // 14
SMBR_RemCap, // 15
SMBR_FullChgCap, // 16
SMBR_RunTTE, // 17
SMBR_AvgTTE, // 18
SMBR_AvgTTF, // 19
SMBR_ChgCurrent, // 20
SMBR_ChgVoltage, // 21
SMBR_BattStatus, // 22
SMBR_CycleCount, // 23
SMBR_DesignCap, // 24
SMBR_DesignVolt, // 25
SMBR_SpecInfo, // 26
SMBR_MfrDate, // 27
SMBR_SerialNo, // 28
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_MfrName, // 32
SMBR_DeviceName, // 33
SMBR_DeviceChem, // 34
SMBR_MfrData, // 35
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_Opt5, // 0x2F
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_invalid,
SMBR_Opt4, // 0x3C
SMBR_Opt3, // 0x3D
SMBR_Opt2, // 0x3E
SMBR_Opt1 // 0x3F
};
/* *************************************************************************
*
* Individual handlers for SMBus WRITE-type commands
*
************************************************************************* */
unsigned char SMBW_MfrAccess(void) // 0
{
unsigned char temp = TW_RxBuf[TW_RxBufIndex++];
SMBvar_int[SMBV_MfrAccess] = temp | (TW_RxBuf[TW_RxBufIndex]<<8);
SMBvariables[SMBV_BattStatus][lobyte] &= 0xF0; //since this cmd is OK, clear Error bits per sbdat110, 4.3.2
return 0;
}
unsigned char SMBW_RemCapAlm(void) // 1
{
unsigned char temp = TW_RxBuf[TW_RxBufIndex++];
SMBvar_int[SMBV_RemCapAlm] = temp | (TW_RxBuf[TW_RxBufIndex]<<8);
SMBvariables[SMBV_BattStatus][lobyte] &= 0xF0; //since this cmd is OK, clear Error bits per sbdat110, 4.3.2
return 0;
}
unsigned char SMBW_RemTimeAlm(void) // 2
{
unsigned char temp = TW_RxBuf[TW_RxBufIndex++];
SMBvar_int[SMBV_RemTimeAlm] = temp | (TW_RxBuf[TW_RxBufIndex]<<8);
SMBvariables[SMBV_BattStatus][lobyte] &= 0xF0; //since this cmd is OK, clear Error bits per sbdat110, 4.3.2
return 0;
}
unsigned char SMBW_BattMode(void) // 3
{
unsigned char tempH = TW_RxBuf[TW_RxBufIndex+1];
unsigned char tempL;
tempL = SMBvariables[SMBV_BattMode][lobyte] & 0xF0;
if(tempH & 0x1C)
return SMBerr_AccessDenied; //attempt to write to reserved bits!
if(~(tempL & INTERNAL_CHARGE_CONTROLLER))
{
tempH &= ~CHARGE_CONTROLLER_ENABLED; //feature not present, don't let it get turned on.
}
if(tempH & PRIMARY_BATTERY)
{
; //let the Host do what it wants with this flag; we ignore it.
}
if(tempH & ALARM_MODE)
SetAlarmMode; //this DISABLES sending alarm msgs for 60 secs
if(tempH & CHARGER_MODE)
{
; //Allow Host to enable us to send Master-mode Charger-Voltage/Current msgs to the Charger
}
if(tempH & CAPACITY_MODE)
{
; //Host must be allowed to control this bit (report in mAH or 10mWH)
}
SMBvar_int[SMBV_BattMode] = tempL | (tempH<<8); //write the modified bits.
return 0;
}
unsigned char SMBW_AtRate(void) // 4
{
unsigned char temp = TW_RxBuf[TW_RxBufIndex++];
SMBvar_int[SMBV_AtRate] = temp | (TW_RxBuf[TW_RxBufIndex++]<<8);
SMBvariables[SMBV_BattStatus][lobyte] &= 0xF0; //since this cmd is OK, clear Error bits per sbdat110, 4.3.2
return 0;
}
unsigned char SMBW_Opt5(void) // 0x2F
{
__disable_interrupt();
MCUSR = 0x1F; //clear all reset sources before jumping to bootloader code.
// __watchdog_reset; //
asm("jmp 0x9000"); // Byte adress
// __watchdog_reset; // reset watchdog
return(1); // to avoid compiler warning, should never be reached
// return SMBerr_ReservedCommand; // <-- Compiler generates warning if return statement is missing.
}
unsigned char SMBW_Opt4(void) // 0x3C
{
calibration_state_req = TW_RxBuf[TW_RxBufIndex++];
calibration_state_req |= (unsigned int)TW_RxBuf[TW_RxBufIndex++] << 8; // Store request details.
SetCalibRequest; // Set action flag so that main loop starts calibrating.
return 0; // Return OK.
}
unsigned char SMBW_Opt3(void) // 0x3D
{
return SMBerr_ReservedCommand;
}
unsigned char SMBW_Opt2(void) // 0x3E
{
return SMBerr_ReservedCommand;
}
unsigned char SMBW_Opt1(void) // 0x3F
{
return SMBerr_ReservedCommand;
}
unsigned char SMBW_Invalid(void) //This should never execute, if error is caught early!
{
return SMBerr_AccessDenied;
}
//Table of pointers to functions, indexed from the received SMBus Command byte.
ptr2funcUC_V SMB_WriteCmd[HIGHEST_SMB_CMD+1] =
{
SMBW_MfrAccess, // 0
SMBW_RemCapAlm, // 1
SMBW_RemTimeAlm, // 2
SMBW_BattMode, // 3
SMBW_AtRate, // 4
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid, //0x0F
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid, //0x1F
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Opt5, // 0x2F
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Invalid,
SMBW_Opt4, // 0x3C
SMBW_Opt3, // 0x3D
SMBW_Opt2, // 0x3E
SMBW_Opt1 // 0x3F
};
/* *************************************************************************
*
* Utilities for SMBus commmunications
*
************************************************************************* */
__flash unsigned char crctable[16] = {0,0x07,0x0E,0x90, 0x1c,0x1b,0x12,0x15, 0x38,0x3F,0x36,0x31, 0x24,0x23,0x2A,0x2D};
__flash unsigned char crctable2[16] = {0,0x70,0xE0,0x90, 0xC1,0xB1,0x21,0x51, 0x83,0xF3,0x63,0x13, 0x42,0x32,0xA2,0xD2};
unsigned char FastCRC(unsigned char LastCRC, unsigned char newbyte)
{
unsigned char index;
index = newbyte;
index ^= LastCRC;
index >>= 4;
LastCRC &= 0x0F;
LastCRC ^= crctable2[index];
index = LastCRC;
index ^= newbyte;
index &= 0x0F;
LastCRC &= 0xF0;
LastCRC ^= crctable[index];
return(LastCRC);
}
/* This version doesn't require crctable2[], but requires more shifts.
unsigned char SlowerCRC(unsigned char LastCRC, unsigned char newbyte)
{
unsigned char index;
index = newbyte;
index ^= LastCRC;
index >>= 4;
LastCRC <<= 4;
LastCRC ^= crctable[index];
index = LastCRC >> 4;
index ^= newbyte;
index &= 0x0F;
LastCRC <<= 4;
LastCRC ^= crctable[index];
return(LastCRC);
} */
//! \todo This can be modified to load defaults from EEPROM rather than fixed values to the SMB variables.
// This sets power-up defaults.
void InitSMBvariables(void)
{
SMBvar_int[SMBV_MfrAccess] = 0x4060; // Mega406 ap-note, revision 0 code
SMBvar_int[SMBV_RemCapAlm] = (PACK_DESIGNCAPTYP / 10); // per sbdat110, 4.4.1
SMBvar_int[SMBV_RemTimeAlm] = 0x000A; // per sbdat110, 4.4.1
SMBvar_int[SMBV_BattMode ] = 0x0000; //
SMBvar_int[SMBV_AtRate ] = 0x0000; //
/* For testing with no calcs
SMBvar_int[SMBV_AtRateTTF ] = 0x0000; //
SMBvar_int[SMBV_AtRateTTE ] = 0x0000; //
SMBvar_int[SMBV_AtRateOK ] = 0x0000; //
SMBvar_int[SMBV_Temperature] = 0x0000; //
SMBvar_int[SMBV_Voltage ] = 0x0000; //
SMBvar_int[SMBV_Current ] = 0x0000; //
SMBvar_int[SMBV_AvgCurrent ] = 0x0000; //
SMBvar_int[SMBV_MaxError ] = 0x0000; //
SMBvar_int[SMBV_RelSOC ] = 0x0000; //
SMBvar_int[SMBV_AbsSOC ] = 0x0000; //
SMBvar_int[SMBV_RemCap ] = 0x0000; //
SMBvar_int[SMBV_FullChgCap] = 0x0000; //
SMBvar_int[SMBV_RunTTE ] = 0x0000; //
SMBvar_int[SMBV_AvgTTE ] = 0x0000; //
SMBvar_int[SMBV_AvgTTF ] = 0x0000; //
SMBvar_int[SMBV_ChgCurrent] = 0x0000; //
SMBvar_int[SMBV_ChgVoltage] = 0x0000; //
*/
SMBvar_int[SMBV_BattStatus] = 0x0080; //per sbdat110, 4.4.1
SMBvar_int[SMBV_CycleCount] = 0x0000; //per sbdat110, 4.4.1
/* For testing with no calcs
SMBvar_int[SMBV_DesignCap ] = 0x0000; //
SMBvar_int[SMBV_DesignVolt] = 0x0000; //
*/
SMBvar_int[SMBV_SpecInfo ] = 0x0031; // no scaling of I or V; we support PEC, and we're V1.1
SMBvar_int[SMBV_MfrDate ] = ((2005-1980)<<9)+(8<<5)+(31); //! \todo Fill in current year, month, day. Values are octal
SMBvar_int[SMBV_SerialNo ] = 12345; // arbitrary...
//Note that for the Block-Read variables, we copy those into a RAM buffer only as needed.
// These are MfrName, DeviceName, DeviceChem, and MfrData.
SetMaxTopAcc((long)6600*10727); //! \todo for testing, initialized value before reaching fully charged, 6600mAh * 10727
// RunningAcc = (long)1000*10727; //for testing, to start at other point than 0, 1000 * 10727
}
/* Some important notes from the SMBus specs:
Insertion or removal of a Smart Battery may be detected when the 慡afety Signal
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -