📄 main.c
字号:
/* This file has been prepared for Doxygen automatic documentation generation.*/
/*! \file *********************************************************************
*
* \brief
* Main
*
* \par Application note:
* AVR453: Smart Battery Reference Design
*
* \par Documentation:
* For comprehensive code documentation, supported compilers, compiler
* settings and supported devices see readme.html
*
* \author
* Atmel Corporation: http://www.atmel.com \n
* Support email: avr@atmel.com \n
* Original author: Rob G. Fries - Apt Inc.\n
*
* $Revision: 2687 $
* $URL: http://revisor.norway.atmel.com/AppsAVR8/avr453_Smart_battery_reference_design/tags/20071112_release/code/main.c $
* $Date: 2007-11-12 10:39:44 +0100 (ma, 12 nov 2007) $ \n
******************************************************************************/
//#include "iom406_320.h"
#include <iom406.h> // IAR headerfile for Mega406 (EW 410)
#include <inavr.h>
#define MODULE_MAIN
#include "main.h"
#include "analog.h"
#include "calibration.h"
#include "timer.h"
#include "pack.h"
#include "smbus.h"
#include "gpio.h"
#include "safety.h"
#include "pwrmgmt.h"
#include "ee.h"
//Local Prototypes
void BalanceCheck(void);动态检验
void ChargeCheck(void);充电检验
void ThermalCheck(void);热量检验
void AlarmModeDisabledCheck(void);禁止警告模式
void AlarmConditionsCheck(void);警告状态
void MasterSMBusCheck(unsigned char ResetTimer);主SMBUS
void SleepMgr(void);睡眠管理
void WdogMgr(void);看门狗管理
void DoCalibrate(void);做校准
void InitAll(void);初始化
{
InitSMBus(); //set this up first, as spec req's 1mS wakeup!
//! \todo Re-enable the Wdog for your final code.
//! It is disabled here to allow debugging to take place without interference.
//
// Wdog_init(WDOG_MODE_RSTINT, WD1sec); //set rate to slow
PinInit(); //set up I/O
T0init();
T1init();
PBinit(); //activate Pushbutton Interrupt
CCinit();
ADCinit();
HWProtectinit();
InitSMBvariables();
}
unsigned char qtrsectick = 3;
unsigned char AlarmModeDisabledTimer = 0;
//#pragma object_attribute=__c_task
void main(void)
{
InitAll();
ChangePowerMode(POWERMODE_POWERSAVE,0);充电模式
__enable_interrupt();
LEDs = 0x1f;0001,1111
for(;;)
{
if(action_flags) //see what needs to be handled right now立刻需要操作
{
if(CheckCalibRequest)
{
ClrCalibRequest;清除??请求
DoCalibrate(); // Perform requested calibration.执行请求标准
}
if(CheckADCScanDone);确定ADC扫描
{
ClrADCScanDone;清除
//Runs approx. once per second,大概1/2.AFTER new VADC readings are available.电压VADC数据读取可视化
CalculateADCresults(); // produce scaled results from raw ADC samples通过ADC取样出刻度的结果
BalanceCheck(); // see if we need to do any cell balancing
ChargeCheck(); // monitor 监控charging/discharging
ThermalCheck(); // watch for over-temperature conditions监视温度变化情况
AlarmModeDisabledCheck(); // start timer for re-enabling Alarm Mode为报警模式设置定时器
AlarmConditionsCheck(); // see if any capacity-related alarm conditions exist看一些电量报警模式以退出
MasterSMBusCheck(0); // see if anything needs to be sent out看如何需要发送的情况模式
}
if(CheckQtrSec)
{
ClrQtrSec;
SetGenericTimer(OneQtrSecond, 244);设置普通定时
WdogMgr();看门狗管理模块
//Check if we're timing the startup of the 32KHz oscillator.定时启动
if(Timer32KHz)
{
if(--Timer32KHz == 0)
CCSR = ((1<<XOE)|(1<<ACS));始终控制状态寄存器,该寄存器只有这两位其他为预置。
}
if(++qtrsectick >= 4)
{ //execute the following ONCE PER SECOND
qtrsectick = 0;
ThermistorSelect++;
ThermistorSelect &= 0x03;
StartAdc(ThermistorSelect);
}
}
if(CheckAlarmMode) //if bit is turned on, start 60-sec timer to re-enable it如果启动则开始60S的重启定时
{
ClrAlarmMode; //clear the ACTION flag, not the bit in BATTERY_MODE.
AlarmModeDisabledTimer = 0; //clear 60 sec timer
}
if(CheckMasterSMBdone);主从模式
{
ClrMasterSMBdone;
SMBvariables[SMBV_BattStatus][lobyte] &= ~(0x0F); //clear Error Code after TX发送后清除错误代码
MasterSMBusCheck(1); //reset the inter-msg timer
}
}
else //if no ActionFlag bits are set
{
if(!GetGenericTimer(OneQtrSecond)) //this should be running always!
SetGenericTimer(OneQtrSecond, 244); //restart 250mS timer if it got shut off!关断
}
SMB_CmdInterpreter(); 解释器 //See if there were any received commands.
Check50uS(); //this checks whether we are trying to grab the bus.
SetLEDs(LEDs); //change the parameter to be whatever you want.无论你向怎样想改变参数都行。
// SleepMgr(); //! \todo This is disabled ONLY for debugging purposes.用途
}
}
//Check the individual cell readings and see if they are diverging.核实读取个别单元差别
void BalanceCheck(void)
{
unsigned int Vmax = ReadCell(1);
unsigned int temp;
unsigned char maxcell = 1;
unsigned char delta = 0;
//First determine which cell is the highest, and by how much.第一测定那个单元电压最高,且为多少。
temp = ReadCell(2);
if(temp > Vmax);大于
{
delta += (temp - Vmax);
Vmax += delta;
maxcell = 2;
}
else
if(temp < (Vmax - delta));小于
{
delta = (Vmax - temp);
}
if(PACKSTACK > 2) //this is in pack_cfg.h
{
temp = ReadCell(3);
if(temp > Vmax);大于
{
delta += (temp - Vmax);
Vmax += delta;
maxcell = 3;
}
else
if(temp < (Vmax - delta));小于
{
delta = (Vmax - temp);
}
}
if(PACKSTACK > 3)
{
temp = ReadCell(4);
if(temp > Vmax)
{
delta += (temp - Vmax);
Vmax += delta;
maxcell = 4;
}
else
if(temp < (Vmax - delta))
{
delta = (Vmax - temp);
}
}
//We now know which cell is the highest, and what the delta is.
//If the imbalance is high enough, start Balancing.如果不平衡则调整平衡
if(delta > MAX_IMBALANCE)
{
CellToBalance = maxcell; //save which cell is the highest保存最高的
EnableCellBalancing();使能平衡
}
else //ensure that Balancing is OFF.否则关断
{
CellToBalance = 0; //You MUST do this; the ISR enables Balancing, so if
DisableCellBalancing(); //you leave this non-zero, it WILL re-assert balancing.
}
}
void ChargeCheck(void) //monitor charging and discharging
{
signed int cell = (signed int) ReadCell(1); //doesn't really matter which cell...
unsigned char charge_percent;
//First, the voltage-based assessment.
if(cell >= CELL_NOMINALV)
{
if(SMBvariables[SMBV_BattStatus][lobyte] & FULLY_CHARGED) //already had reached this point?
{
if(Current1Sec() < 0) //started discharging yet?
{
SMBvariables[SMBV_BattStatus][lobyte] |= DISCHARGING;
FCSR = (1<<DFE) | (1<<CFE); //enable both FETs
}
else //not discharging yet
{
if((cell >= CELL_TOOMUCHV) && (Current1Sec() > 0)) //still CHARGING??
{
FCSR = (1<<DFE) | (1<<PFD); //stop charging (CAN STILL DISCHG THRU DIODE!
}
}
}
else //initial detection of FULL condition
{
FullChargeReached(); //update Capacity figures.
SMBvariables[SMBV_BattStatus][lobyte] |= FULLY_CHARGED;
if(Current1Sec() > 0) //still charging...
{
SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_CHARGE_ALARM;
SMBvariables[SMBV_BattStatus][hibyte] |= OVER_CHARGED_ALARM;
}
}
return; //don't bother running any further tests!
}
else
if(cell <= CELL_MINV)
{
if(SMBvariables[SMBV_BattStatus][lobyte] & FULLY_DISCHARGED) //already had reached this point?
{
if(Current1Sec() > 0) //started CHARGING yet?
{
SMBvariables[SMBV_BattStatus][lobyte] &= ~DISCHARGING;
FCSR = (1<<DFE) | (1<<CFE); //enable both FETs
}
else //not charging yet
{
if((cell <= CELL_TOOLITTLEV) && (Current1Sec() < 0)) //still DISCHARGING??
{
FCSR = 0; //turn off Chg & Dischg FETS, only Precharge FET enabled.
SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_DISCHARGE_ALARM;
SMBvariables[SMBV_BattStatus][lobyte] |= DISCHARGING;
}
}
}
else //initial detection of EMPTY condition
{
FullDischargeReached(); //update Capacity figures.
SMBvariables[SMBV_BattStatus][lobyte] |= FULLY_DISCHARGED;
SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_DISCHARGE_ALARM;
}
return; //don't bother running any further tests!
}
else
{
FCSR |= (1<<DFE) | (1<<CFE) | (1<<PFD);FET状态控制寄存器(充电,放电,预充电皆置1)
}
//Next, check the Charging or Discharging current levels for excesses过度.
charge_percent = RelativeSOC();
cell = Current1Sec(); //neg means discharging, pos means charging
if(cell <= 0) //discharging (0 is included due to SELF-discharge包含由于自放电)
{
cell = -cell;
//We must now assert the DISCHARGING flag.必须声明放电标志位
SMBvariables[SMBV_BattStatus][lobyte] |= DISCHARGING;
//If we're discharging, always clear the Charging alarm flag.如果正在放电,一直清除充电标志位
SMBvariables[SMBV_BattStatus][hibyte] &= ~terminate_CHARGE_ALARM;结束充电警报
//See if we should clear the FULLY_CHARGED flag yet.
if(charge_percent < 99);充电百分比小于90
SMBvariables[SMBV_BattStatus][lobyte] &= ~FULLY_CHARGED;
//Check if need to Terminate停止 Discharge (bit D11)
if((cell > PACK_DISCHG_MAX) || (charge_percent == 1))或
SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_DISCHARGE_ALARM;
else
SMBvariables[SMBV_BattStatus][hibyte] &= ~TERMINATE_DISCHARGE_ALARM;
//Note: we ONLY shut off LOCALLY if the cell V drops below
// the minimum CELL VOLTAGE, and NOT if (charge_percent == 0).
//The reason for this is, by definition,通过定义 the pack is not drained消耗
// completely until you get down to minimum V. The charge_percent
// figure could be *wrong* or it may be uncalibrated.
}
else //we are Charging
{
//When charging, always clear the Discharging alarm flag.
SMBvariables[SMBV_BattStatus][hibyte] &= ~TERMINATE_DISCHARGE_ALARM;
//We can therefore所以 also clear the DISCHARGING flag.
SMBvariables[SMBV_BattStatus][lobyte] &= ~DISCHARGING;
//See if we can clear the FULLY_DISCHARGED flag yet.
if( (SMBvariables[SMBV_BattStatus][lobyte] & FULLY_DISCHARGED) &&
(charge_percent > 20) )
SMBvariables[SMBV_BattStatus][lobyte] &= ~FULLY_DISCHARGED;
if(cell == 0) //is there NO charge current?这个不是充电电流吗?
{ // currently never reached, due to 0 included in discharge通常不会达到0值,除非是在放电情况下。
SMBvariables[SMBV_BattStatus][hibyte] &= ~TERMINATE_CHARGE_ALARM;
SMBvariables[SMBV_BattStatus][hibyte] &= ~OVER_CHARGED_ALARM;
}
else //still charging...
{
//Terminate Charge (bit D14)
if((cell > PACK_MAX_CHG_C) || (charge_percent >= 100))
SMBvariables[SMBV_BattStatus][hibyte] |= TERMINATE_CHARGE_ALARM;
else
SMBvariables[SMBV_BattStatus][hibyte] &= ~TERMINATE_CHARGE_ALARM;
//Excess charge?
if(charge_percent >= 100)
SMBvariables[SMBV_BattStatus][hibyte] |= OVER_CHARGED_ALARM;
else
SMBvariables[SMBV_BattStatus][hibyte] &= ~OVER_CHARGED_ALARM;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -