⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 smbus.c

📁 用AVR453开发的电池保护板的C语言程序,希望对大家有用!
💻 C
📖 第 1 页 / 共 4 页
字号:
  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?transitions from or to an
open-circuit value (>100k.)

When an SMBus device acting as the bus master detects an error, it must attempt to return the bus to the idle
state by generating a STOP condition.

The Smart Battery must ALWAYS acknowledge its own address. Failure to do so might cause the SMBus
Host or Smart Battery Charger to incorrectly assume the Smart Battery is NOT present in the system,
although the 慡afety Signal?can be used to detect the presence of a Smart Battery in a system. Note
however that the Smart Battery may choose not to acknowledge any byte following its address if it is
busy or otherwise unable to respond. If this occurs, the requestor should re-try the data request.

After each SMBus transaction directed to the Smart Battery device address, the Smart Battery must place
the appropriate error code in the lower nibble of the BatteryStatus() register. If the transaction completed
successfully, the error codes should be cleared to signify that no error was detected. Timeout and other
errors not described by one of the error code types may be signaled with an Unknown Error.

Another device may try to interrogate the battery immediately after a transaction from the Host.
The safest method to insure that the read of BatteryStatus() corresponds to the most recently read data value
is to perform this read of BatteryStatus() immediately after the read of the initial data value. This may be
accomplished by issuing a SMBus START condition after the SMBus STOP condition from the previous
transmission.

A bus master is required to check for bus idle time of 50 us.

The Smart Battery enters the 揙n State whenever it detects that the SMBus Clock and Data lines go high.
The battery should be active and able to communicate via the SMBus within 1 ms of detecting these SMBus
lines going high.

The Smart Battery may not begin *broadcasting* ChargingVoltage(), ChargingCurrent() or AlarmWarning()
messages to either the SMBus Host or Smart Battery Charger for at least 10 seconds after entering the 揙n
State.?
When the Smart Battery enters the 揙n State?the following values must be reinitialized:
Function (Data Value) 		Initial Value 		
---------------------	----------------------------	
BatteryMode() 		Bit 15: CAPACITY_MODE=0
			Bit 14: CHARGER_MODE=0
			Bit 13: ALARM MODE=0
			Bit 9: PRIMARY_BATTERY=0
			Bit 8: CHARGE_CONTROLLER_ENABLED=0


The Smart Battery may enter the 揙ff State?whenever the SMBus Clock and Data lines both remain low
for greater than 2.5 seconds.

There is no limit to the speed (other than SMBus limits) or rate at which data may be requested from the
Smart Battery. Continuous data polling at high rates is permitted and allowed, though not encouraged due
to limitations on SMBus bandwidth and availability. The Smart Battery may delay any data request by
holding the CLOCK line low for up to 25 ms. This may be done in order to re-calculate the requested data
value or to retrieve data from a storage device.


*/

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -