📄 main.c
字号:
}
}
//! \todo Whenever you move 2X the capacity, either into or out of the pack, you are supposed推测
//! to increment the CycleCount variable增加机器周期变量值. You do NOT have to have hit both FULL and EMPTY limits.不需要都达到
//
// if(???)
// SMBvar_int[SMBV_CycleCount]++;
}
void ThermalCheck(void);温度检测
{
unsigned int temp = GetTemperature();
//check for OverTemp alarm (bit D12)
if(temp > MAX_CELL_TEMPERATURE)
SMBvariables[SMBV_BattStatus][hibyte] |= OVER_TEMP_ALARM;
else
SMBvariables[SMBV_BattStatus][hibyte] &= ~OVER_TEMP_ALARM;
//If the Host/Charger doesn't respond fast enough没有足够快的反应速度, SHUT DOWN LOCALLY.
if(temp > MAX_ONCHIP_TEMP)
DoShutdown(SHUTDOWN_REASON_OVERTEMPERATURE);
//! \todo The following Cell temperature checking is disabled since it
//! is left to the user to choose a specific Thermistor.特殊调节器
/*
if(ReadTemperature(1) > MAX_CELL_TEMPERATURE)
;
if(ReadTemperature(2) > MAX_CELL_TEMPERATURE)
;
if(PACKSTACK <= 2)
return;
if(ReadTemperature(3) > MAX_CELL_TEMPERATURE)
;
if(PACKSTACK <= 3)
return;
if(ReadTemperature(4) > MAX_CELL_TEMPERATURE)
;
*/
}
//This makes sure Alarm Mode is only disabled for 60 seconds max.
void AlarmModeDisabledCheck(void)
{
if(SMBvariables[SMBV_BattMode][hibyte] & ALARM_MODE)
{
if(++AlarmModeDisabledTimer >= 59)
{
SMBvariables[SMBV_BattMode][hibyte] &= ~ALARM_MODE; //re-enable
}
}
}
void AlarmConditionsCheck(void) //look for 'other' alarm conditions
{
//Remaining Time (bit D8)
if(SMBvar_int[SMBV_RemTimeAlm] != 0)
{
if(TimeToEmpty(0) < SMBvar_int[SMBV_RemTimeAlm])
SMBvariables[SMBV_BattStatus][hibyte] |= REMAINING_TIME_ALARM;
}
else
SMBvariables[SMBV_BattStatus][hibyte] &= ~REMAINING_TIME_ALARM;
//Remaining Capacity (bit D9)
if(SMBvar_int[SMBV_RemCapAlm] != 0)
{
if(RemainingCap() < SMBvar_int[SMBV_RemCapAlm])
SMBvariables[SMBV_BattStatus][hibyte] |= REMAINING_CAPACITY_ALARM;
}
else
SMBvariables[SMBV_BattStatus][hibyte] &= ~REMAINING_CAPACITY_ALARM;
}
void MasterSMBusCheck(unsigned char ResetTimer) //this gets called once per second (except to assert ResetTimer).
{
static unsigned char timer = 0;
//When you call SMB_Master(), it will only TX if there's something in the buffer.
//To control this, we only INSERT if it's >10 seconds since last TX.
if(ResetTimer)
{
timer = 0;
return;
}
if(++timer < 10)
{
SMB_Master();
return;
}
if(!(SMBvariables[SMBV_BattMode][hibyte] & ALARM_MODE))
{
//Check if there's a newly-updated BatteryStatus that must be sent ASAP
if(SMBvariables[SMBV_BattStatus][hibyte])
{
if(SMBvariables[SMBV_BattStatus][hibyte] & ~(REMAINING_CAPACITY_ALARM | REMAINING_TIME_ALARM))
{ // Need to send this message to BOTH the Host and the Charger.
MasterInsertMsg(CHARGER_ADDR, SMB_M_CMD_ALARMWARNING, SMBvar_int[SMBV_BattStatus]);
}
//All messages are sent to the Host.
MasterInsertMsg(HOST_ADDR, SMB_M_CMD_ALARMWARNING, SMBvar_int[SMBV_BattStatus]);
}
//! \todo Only a very basic charge control algorithm has been implemented. It uses the charge state to decide.
//! It is up to the designer to implement a more sophisticated charging algorithm.
if(!(SMBvariables[SMBV_BattMode][hibyte] & CHARGER_MODE)) // Check that Charger_Mode is enabled, per sbdat110, 5.1.4
{
if(!(SMBvariables[SMBV_BattStatus][lobyte] & FULLY_CHARGED) ||
!(SMBvariables[SMBV_BattStatus][hibyte] & TERMINATE_CHARGE_ALARM) ||
!(SMBvariables[SMBV_BattStatus][hibyte] & OVER_CHARGED_ALARM)) { // it is OK to charge?
SMBvar_int[SMBV_ChgCurrent] = PACK_CCCV_C; //
SMBvar_int[SMBV_ChgVoltage] = PACK_CCCV_V; //
MasterInsertMsg(CHARGER_ADDR, SMB_M_CMD_CHARGINGCURRENT, PACK_CCCV_C);
MasterInsertMsg(CHARGER_ADDR, SMB_M_CMD_CHARGINGVOLTAGE, PACK_CCCV_V);
} else { // it is not ok to charge
SMBvar_int[SMBV_ChgCurrent] = 0x0000; //
SMBvar_int[SMBV_ChgVoltage] = 0x0000; //
}
}
timer = 0; //clearing this prevents the same messages from repeatedly being added to the TX buffer.
}
SMB_Master();
}
void SleepMgr(void)
{
SMCR |= (1<<SE);
__sleep();
__no_operation();
__no_operation();
__no_operation();
__no_operation();
//at this point, we should be asleep.
// ...
//at this point, we've just completed running the ISR for whatever interrupt woke us up.
SMCR &= ~(1<<SE); //According to the datasheet, we should clear the SE bit at wakeup.
return; //Go back to main loop & see if we need to do anything else before sleeping again.
}
void WdogMgr(void)
{
//! \todo This code can be made more sophisticated to prevent runaways
// from continually feeding the Wdog.
__watchdog_reset();
return;
}
void DoCalibrate(void)校准
{
// Explanation of the DoCalibrate routine:
// User requests calibration by sending a word write SMBus command 0x3c (OptionalMfgFunction4)用户通过发送写入一字节SMBUS命令3C来达到校准请求的母的。
// with the appropriate bits set. (用适当的BITS设置)This sets CALIBREQUESTED bit flag in action_flags, and the
// 'calibration_state_req' variable 变量contains the received word(接收字节). A read of OptionalMfgFunction4
// returns the current state contained in the 'calibration_state variable'.
//
// The valibles are both divided into 分成2-bit fields, which makes room for a total of 8 calibration routines.
// Currently two calibration-routines are implemented in the lower 4 bits of the lowest byte:
// xx xx xx xx xx xx BB AA.
//
// xx = Unused bits, always 00.
// AA = State of vref calibration.
// BB = State of coloumb counter offset calibration.
//
// State codes:
// 00 - No calibration / calibration not requested.
// 01 - Calibration on-going / calibration requested.
// 10 - Calibration FAILED / request to delete calibration.
// 11 - Calibration OK / revert to old calibration if calibration failed and valid values exist
// otherwise return to No calibration
//
// See diagram in documentation for details on state transitions. A failed calibration resets the
// values to Atmel factory defaults, but since the values are still in eeprom a reset will load them
// and set calibration_state to calibration OK. A write with Calibration OK will correspondingly restore
// valid calibration values and set state to Calibration OK, or to No calibration if not valid values.
// Note: A write with calibration fail will delete previous calibration values.
unsigned char state, request;
unsigned int backup_state_req = calibration_state_req;
state = ((calibration_state & CAL_VREF_MASK) >> CAL_VREF_BIT_POS);
request = ((backup_state_req & CAL_VREF_MASK) >> CAL_VREF_BIT_POS);
switch(request) {
case RUN_CAL: // calibration requested
__disable_interrupt();
DisableCellBalancing();
calibration_state &= ~CAL_VREF_MASK; // Clear bits.
calibration_state |= CAL_VREF_RUN; // Set state to RUN.
if(CalibrateVREF()) { // Calibration ok?
calibration_state &= ~CAL_VREF_MASK; // Clear bits.
calibration_state |= CAL_VREF_OK; // Set state to OK.
__enable_interrupt();
} else {
calibration_state &= ~CAL_VREF_MASK; // Clear bits.
calibration_state |= CAL_VREF_FAIL; // Set state to FAIL.
__enable_interrupt();
}
EnableCellBalancing();
break;
case CAL_FAIL: // delete calibration
if (state == NO_CAL) { // not relevant in state NO_CAL
break;
} else { // delete calibration constants
do {} while(EECR & (1<<EEPE));
do {} while(SPMCSR & (1<<SPMEN));
EEAR = EESTORAGE_BGCCR;
EEDR = 0xFF;
EECR = (0<<EEPM1) | (0<<EEPM0) | (0<<EERIE) | (1<<EEMPE) | (0<<EEPE) | (0<<EERE); //arm
EECR = (0<<EEPM1) | (0<<EEPM0) | (0<<EERIE) | (1<<EEMPE) | (1<<EEPE) | (0<<EERE); //go
calibration_state &= ~CAL_VREF_MASK; // Clear bits.
ReadVrefCalibration();
}
break;
case CAL_OK: // go to eeprom values if valid values exist
if (state == CAL_FAIL) { // only valid from CAL_FAIL state
if (ReadVrefCalibration()) {
calibration_state &= ~CAL_VREF_MASK; // Clear bits.
calibration_state |= CAL_VREF_OK; // Set state to OK.
} else {
calibration_state &= ~CAL_VREF_MASK; // Clear bits.
}
}
break;
default:
break;
}
state = ((calibration_state & CAL_CC_MASK) >> CAL_CC_BIT_POS);
request = ((backup_state_req & CAL_CC_MASK) >> CAL_CC_BIT_POS);
switch(request) {
case RUN_CAL: // calibration requested
__disable_interrupt();
calibration_state &= ~CAL_CC_MASK; // Clear bits.
calibration_state |= CAL_CC_RUN; // Set state to RUN.
if(CalibrateCCoffset()) { // Calibration ok?
calibration_state &= ~CAL_CC_MASK; // Clear bits.
calibration_state |= CAL_CC_OK; // Set state to OK.
__enable_interrupt();
} else {
calibration_state &= ~CAL_CC_MASK; // Clear bits.
calibration_state |= CAL_CC_FAIL; // Set state to FAIL.
__enable_interrupt();
}
break;
case CAL_FAIL: // delete calibration删除刻度
if (state == NO_CAL) { // not relevant in state NO_CAL正式
break;
} else { // delete calibration valid
do {} while(EECR & (1<<EEPE));
do {} while(SPMCSR & (1<<SPMEN));
EEAR = EESTORAGE_CC_valid;
EEDR = 0xFF;
EECR = (0<<EEPM1) | (0<<EEPM0) | (0<<EERIE) | (1<<EEMPE) | (0<<EEPE) | (0<<EERE); //arm
EECR = (0<<EEPM1) | (0<<EEPM0) | (0<<EERIE) | (1<<EEMPE) | (1<<EEPE) | (0<<EERE); //go
calibration_state &= ~CAL_CC_MASK; // Clear bits.
ReadCCOffsetCalibration();
}
break;
case CAL_OK: // go to eeprom values if valid values exist
if (state == CAL_FAIL) { // only valid from CAL_FAIL state
if (ReadCCOffsetCalibration()) {
calibration_state &= ~CAL_CC_MASK; // Clear bits.
calibration_state |= CAL_CC_OK; // Set state to OK.
} else {
calibration_state &= ~CAL_CC_MASK; // Clear bits.
}
}
break;
default:
break;
}
}
/* ASSORTED DOCUMENTATION复合文件
Automatic Cell Balancing自动单元平衡
Once per second, a scan is done of all cell voltages. (1/2,所有单元电压的扫描 )However, 然而if the cell-balancing
FETs are enabled at this time,(如果单元平衡FETS在当前被激活) they will disrupt the voltage measurements. (它们将中断电压测量)To handle响应
this, the VADC ISR will shut off the balancing FETs during the scan 在扫描期间(early enough for
the input RC filters(输入RC filters) to stabilize (稳定在小于1mv内)to less than 1mV). At the completion of the cell
voltage scan,在完成电压扫描之后 if the cells were being balanced the correct balancing FET will be
re-enabled automatically.
Impedance Measurement阻抗测量
In order to measure a cell's impedance, (为了测量单元的阻抗)the cell's voltage must be measured concurrently
with the instantaneous current.(单元电压的测量必须和瞬间电流同步进行) Therefore所以, a copy of the instantaneous current reading
corresponding to the time when each cell's voltage conversion occurs is stored in the
array cell_current[4]. A mainline routine can then manage this data as appropriate.
Four individual copies are saved in case a CCADC instantaneous interrupt occurs during
a cell voltage reading scan.
*/
/*! \mainpage
* This documents functions功能, variables变量, typedefs结构型, enumerations枚举, enumerator and defines定义
* in the the software for ATAVRSB100.\n软件一家公司的开发板,不值一提!
* Please see the Related Pages for Compilation Info, Release Notes and a Todo List
*/
/*! \page doc_page1 Compilation Info
* \section section Main source
* This software was written for the IAR Embedded Workbench, 4.11A/4.10B, but can also be
* built using 3.20C (see note futher down).\n
* To make project:
* Add the .c files to project(将.C文件导入到项目中) (main.c, gpio.c, main.c, pwrmgmt.c, safety.c, smbus.c
* and timer.c, but not the bootloader bootloader_smbus.c除外),
* use device --cpu=m406, CLIB Heap size 0x80, Data stack (CSTACK) 0x80 bytes,
* Return adress stack (RSTACK) 64 levels, enable bit definitions in I/O include files,
* optimization low, output format: ubrof8 for Debug and intel_extended for
* Release \n
* If using IAR EWAVR 3.20, use Prosessor configuration -v3 and override default linker
* command file with: $PROJ_DIR$\\cfgm406s.xcl (file included with the source). You also
* need to edit analog.c (see todo in CC_Accumulator_ISR(void)).
*/
/*! \page doc_page2 Release Notes
* Note that this source code is preliminary. This release targets ATmega406 rev E,
* older revisions of ATmega406 are not supported.
* The following features are not fully implemented or are not completely verified:\n
* - Temperature monitoring of battery cells requires additional code.\n
* - Encryption may be added to bootloader updates but is not presently implemented.\n
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -