主题中讨论的其他器件: MSP430F249
工具/软件:Code Composer Studio
先生们:
我正在处理的程序将运行一分钟或更长时间、然后在调试模式下停止响应暂停按钮。 一两分钟后、它将开始正常工作一段时间、然后重复该过程。
当编程 Pod 断开连接时、较旧版本似乎正常运行。 该程序的更新版本也将在正常模式下停止运行、一两分钟后、微控制器将再次启动并按应有的方式工作一两分钟、然后停止。
该程序目前不使用任何低功耗模式、没有外部晶振。 时钟设置是使用同一微控制器从其他设计复制的、因此我感到困惑。
谢谢、Harvey
/
*
*子卡:顶部电池卡、修订版0
*
*文件名:main.c
*项目:PowerCortex
*模块:DCM
*产品:PowerCortex - M 系列
公司:1100 Energy Corporation
*作者:Harvey Novak
*
*版本:1.00
*版本:1.
*时间:下午5:03
*日期:2019年2月15日
*
*
*目标处理器:MSP430F2132
*描述:1)
* 2)
* 3)
* 4)
* 5)
*
*注意:
* 1)这是一个连接到输入电源连接器的简单接口。
* 2)为了简洁起见、所有内容都被挤到一个 main.c 中 在生产代码中、各种静态全局变量及其
*相关的附件例程应移出到单独的模块文件中。
* 3)所有以 SMBus_...开头的例程 是 TI SMBus 库的一部分。
* 4)以"_"开头的所有变量在此文件中均为全局范围。
*
*软件更改/改进:
* 1)电流感应例程中的积分器需要改进。
* 2)添加温度监控器(如果可用)!!!
* 3)添加恒温器。
*
*
*关键字:
* VM_1_OUT 通道 A0 -电压表1中的平均 DC_IN 电压=总和/8。
*通道 A1 -电压表2中的平均 DC_IN 电压=总和/8。
* Analog _2 Ch A2 -备用输入 A2的平均值=总和/8。
* Analog _3通道 A3 -备用输入 A3的平均值=总和/8。
* Analog _4 Ch A4 -备用输入 A4的平均值=总和/8。
* Analog _5通道 A5 -备用输入 A5的平均值=总和/8。
*
* Packet Timer
*
*
*修订版1中要解决的硬件问题:
1) UCLK、SOMI、SIMO 和 STE 未连接。
* 2)所有 DMN65D8L-7 FET 都交换了栅极和源极引脚! Q10-13、Q16、Q18
* 3)所有 DMP6350S-7 FET 都交换了源极和漏极引脚! Q1、Q3-8、Q17
* 4) PCT2075D 温度传感器需要在电池之间进行切换!
* 5)二极管 D1向后。 符号绘制正确、但引脚在 PCB 插图中相反。
*
(小部分 /
#include
//#include
#include "definitions.h"
//#include
//#include
//顶部电池卡
//
//常规计数器
//
字节 LED_FLINes;//每个闪存序列的闪存数量。
字节 Flash_Count;//当 mode_State 更改时、在整个代码中设置临时变量。
字节 LED_Sequence_Count;// LED 消隐前的闪存序列数。
字节 REAL_Data_Count;// ADC 收集的数据集计数。
字节 NAK_Count;//传输期间从 f169接收到的 NAK 计数。
字节 Packet_er_Cnt;// Packet 发送的传输错误计数。
字节 Packet_Count;// 8位翻转计数器,用于允许 f169识别过期数据。
字节计数;//计数器变量。
//控制标志寄存器
//
字节 ADC_Flags;//数据采集控制标志。
字命令;//要处理的命令。
字节 System_Flags;//其他系统控制标志。
字节 Command_Flags;//命令处理器标志。
字 Gen_Msg_FLAG1;
//计时器和计数器
//
字 WAIT_Timer;
字 Watch_Dog;
字 LED_Timer;
word over_curry_Timer;//电池单元的冷却关闭周期。
word Powerup_Timer;//保持与 BAT_BUS 的连接、直到螺钉拧紧且操作系统稳定。
字 SMB_Timer_IR;//与 IR 视频驱动程序计时器进行 SMBus 通信。
字 Packet_Timer;//设置数据包与电位器之间的最短时间。
字节 POT_Timer;// SMBus 数据包时序。
Word LED_Pause;
字 LED_Reload;
字 LED_Reload;
//顶部电池卡
//
//---- 状态机---
字节 Command_State;//顶级活动管理器。
字节 Sub_A_Cmd_State;//数据包排序二级状态机。
字节 Sub_B_Cmd_State;//数据包排序二级状态机。
字节 Sub_C_Cmd_State;//数据包排序二级状态机。
字节 POT_WR_STATE;//将一个字节的数据发送到四个较低的 EADC 之一。
字节 PoT_Pkt_WR_State;//向四个较低的 EDEC 之一发送数据包。
字节 ADC_DATA_STstate;//从 ADC 收集。
字节 I_Monitor_state;//监视流入或流出电池串的电流。
字节 A0_Monitor_state;//顶部电池电压监视器。
字节 LED_STATE;// LED 闪烁控制。
//---- 电位器 SMBus 变量---
//
//电位计访问控制寄存器位定义。
//位0 R/W 当置位时、选择一个读取数据传输。
//" 1 A0 Pot 地址位0。
//" 2 a1"" 1.
//" 3 ID0器件标识位0。
//" 4 ID1 "" 1.
//" 5 ID2"" 2.
//" 6 ID3 "" 3.
//" 7 ID4 "" 4.
字节 SMBus_Buffer;//要传输到或从其中一个视频驱动程序传输的字节的临时存储。
字节已被删除;//来自电位器的 SMBus 确认的最后一个值。
字节 bit_Mask;//用于剥离发送到电位器的字节的位。
字 Data_Array_PTR;//数据数组索引。
字 Data_Array_last;//要发送的数组中当前数据块的末尾。
字节 LOCAL_Data[3]={POT_ACR_Wr、POT_AR、POT_WCR};
//顶部电池卡
//
//传感器数据
//
字 Analog 数据;// ADC 转换临时缓冲器
word battery_bus;// Ch A0 -电池总线上的平均电压。
word cell_POS;// Ch A1 -顶部电池上的平均电压。
字 MID_STRING;// Ch A2 -电芯串中心抽头的平均电压。
// I_sense;// Ch A3 -电池串输入或输出的平均电流。
字 VREF;//通道 A4 -基准的平均电压。
字模拟5;//通道 A5 -未使用
字 Ch_A0[9];// Ch A0 battery_bus -最后8个样本和总和的数组。
字 Ch_A1[9];// Ch A1 CELL_POS -""""" ""。
字 Ch_A2[9];// Ch A2 MID_string -""" ""。
字 Ch_A3[9];//通道 A3 I_SENSE -""""" ""。
字 Ch_A4[9];//通道 A4 VREF -""" ""。
字 Ch_A5[9];// Ch A5 Analog5 -"""" ""。
字节 ADC_POINTER;//指向全部六个模拟数据数组的指针。
signed int i_sense、TC_0Iio、IIO_Offset、Integrated _Energy;
/*
//
//总线电压相关测量和计算变量。
//
悬空 BBB_A30;//捕获 BAT_BUS_D30时的电压表读数。
字 BBB_D30;//当 BAT_BUS 电压设置为~30 Vdc 时为 A/D 读取的值。
悬空 BBB_A24;//捕获 BAT_BUS_D30时的电压表读数。
字 BBB_D24;//当 BAT_BUS 电压设置为~30 Vdc 时为 A/D 读取的值。
float bb_m;//为 BAT_BUS 计算出的线性近似斜率。
float bb_b;//为 BAT_BUS 计算的线性近似偏移。
float BB_f;//从 A/D 转换器读取的任意整数值中计算出的 BAT_BUS 电压值。
捕获 CELL_POS_D30时、浮动 CP_A30;//电压表读数。
字 CP_D30;//当 CELL_POS 电压设置为~30 Vdc 时为 A/D 读取的值。
捕获 CELL_POS_D30时、浮动 CP_A24;//电压表读数。
字 CP_D24;//当 CELL_POS 电压设置为~30 Vdc 时为 A/D 读取的值。
float cp_m;//计算出 CELL_POS 线性近似的斜率。
float cp_b;//计算出 CELL_POS 线性近似的偏移。
浮点 CP_f;//从 A/D 转换器读取的任意整数值中计算出 CELL_POS 电压的值。
捕捉 MID_STRING_D30时浮动 MS_A30;//电压表读数。
字 MS_D30;//将 Mid_string 电压设置为~30 Vdc 时为 A/D 读取的值。
捕捉 MID_STRING_D30时浮动 MS_A24;//电压表读数。
字 MS_D24;//将 MID_STRING 电压设置为~30 Vdc 时为 A/D 读取的值。
浮点 MS_m;//计算出 MID_STRING 线性近似的斜率。
浮点 MS_b;//计算出 MID_STRING 线性近似的偏移。
浮点 MS_f;//从 A/D 转换器读取的任意整数值中计算出 MID_string 电压的值。
*
带符号的 int Ipwr 偏移;//用于补偿电流传感器偏移的变量。
//顶部电池卡
//
//======================================================== Main ================================================================
// TC_0Iio = 512转至初始化以测量电流偏移。
int main (空)
{
WDTCTL = WDTPW | WDTHOLD;//停止看门狗计时器
//======================================== 时钟初始化===================
//
//对于 MCLK、我们使用设置为16MHz 的数字控制 OSC。
//它使用存储在受保护闪存段中的预设校准常数。
//如果这些常量已被擦除,则会将 CPU 陷到无限循环中
//防止出现问题。
//
if (CALBC1_16MHz = 0xFF)// if 校准常数被擦除
{
while (1)
{
;//不加载,陷阱 CPU!!
}
}
//此序列取自《MSP430F249用户指南》、
//第283-284页。 预设常量可用于1、8和16MHz。
DCOCTL = 0;//选择最低 DCOx 和 MODx 设置
BCSCTL1 = CALBC1_16MHz;//设置范围
DCOCTL = CALDCO_16MHz;//设置 DCO 步长+调制
//这为 ACLK 选择超低功耗低频率 OSC
BCSCTL3 = LFXT1S_2;// ACLK 的 VLO (~12kHz)
//顶部电池卡
//
//======================================== 端口初始化===================
//这些初始化仅设置 I2C/SMB 引脚(P3.1和 P3.2)和
// LED (P2.5)。 所有其他 GPIO 引脚都保留为数字输入、并且需要
//针对降压/升压卡上的特定用途进行配置。
// LED0同时用作3.3MOD 上电指示器和 SMB 状态查询指示器
//(切换每个接收到的状态请求)。
//
//--端口1设置---
// P1SEL = 0xFF ^(BIT7 | BIT6 | BIT4 | BIT3 | BIT2 | BIT1 | BIT0);//将所有8设置为数字 I/O
//
P1SEL = 0x00;//将所有8个引脚设置为正常数字 I/O
P1OUT = 0x00;//清除输出寄存器。
P1DIR =(WARM_EN | Test1 | Str_EN);//设置端口1输出引脚、其余为输入。
// P1REN = 0x00;//禁用内部上拉/下拉电阻器。
//--端口2设置---
P2SEL = 0x1F;//为模拟输入设置位0到4、为标准数字 I/O 设置高3位
P2OUT =(BIT4);//将 P2.5输出预设为低电平(ON)
P2DIR =(BIT5);//将 P2.5复位为针对/LED0的数字输出
P2REN = 0x00;//禁用内部上拉/下拉电阻器。
//--端口3设置---
P3SEL = 0x00;//将所有8个引脚设置为正常数字 I/O
P3DIR = NI_SENSE_Power;//将除3.3V 开关控制外的所有端口3引脚设置为输入。
P3SEL =(BIT2 | BIT1);//将1&2设置为外设(USCI_A0:/SCL &/SDA)
P3OUT = 0x00;//清除 P3输出寄存器、当引脚方向被设定为输出时硬下拉。
P3REN = 0x00;//禁用内部上拉/下拉电阻器。
LED_Pause = 0xFFFF;while (LED_Pause){LED_Pause -;}
LED_Pause = 0xFFFF;while (LED_Pause){LED_Pause -;}
//================================================ 设置 ADC10 ================================================
//
//这些位从最高通道开始选择单次转换序列的通道。
//
//模数转换器(ADC)初始化。
ADC10CTL1 = 0;//关闭 ADC10
ADC10CTL0 = 0;
ADC10AE0 |= 0x3F;//通过 P2.0引脚将 P3.0和 P2.4设置为 ADC 的输入。
ADC10CTL1 = INCH_5 + ADC10DIV_7 + CONSEQ_1;//选择序列中的最大通道数(A5)
ADC10CTL0 = ADC10SHT_3 + ADC10ON;//选择 Vcc 作为正基准电压。
ADC10CTL0 |=(ADC10IE);//启动 ADC 块转换状态机。
ADC10CTL0 |=(ENC + ADC10SC);
//全新启动,初始化所有标志。
ADC_Flags = 0;//清除 ADC 标志。
System_Flags = 0;
Command_Flags = 0;//清除所有命令。
Gen_Msg_FLAG1 = 0;
//初始化所有状态机。
COMMAND_STATE = Cmd_PoT_Idle;
SUB_A_Cmd_State = Sub_A_Cmd1;
SUB_B_Cmd_State = Sub_B_Cmd1;
SUB_C_Cmd_State = Sub_C_Cmd1;
POT_WR_STATE = POT_Write_Init;
POT_Pkt_WR_State = POT_Pkt_WR_Idle;//
ADC_DATA_STstate = Acquise_A5;// ADC 数据采集状态机。
I_Monitor_state = I_MON_Zero;//电芯堆栈电流监控状态。
A0_Monitor_state = A0_Initialize;
LED_STATE = LED_WAIT_OFF;//从 LED 关闭开始。
packet_Timer = 1000;
POT_Timer = SMB_Dly4;
LED_Timer = 0x1000;
WAIT_Timer = 10;
P3OUT &=~NI_SENSE_Power;//打开电流传感器 U5的电源。
// TC_0Iio = 515;//输入在零电流时从 A/D 转换器读取的计数。
// Iio_Offset = TC_0Iio - 512;//计算电流传感器偏移。
/*
//
//总线电压的线性近似值。
//
// battery_bus
//
BB_m =( BB_A30 - BB_A24 );
BBB_m /=( BBB_D30 - BBB_D24 );
BBb_b = Bb_A30 -(Bb_m * Bb_D30);
// CELL_POS
//
cp_m =( CP_A30 - CP_A24 );
cp_m /=( CP_D30 - CP_D24 );
cp_b = cp_a30 -(cp_m * cp_d30);
// MID_STRING
//
MS_m =( MS_A30 - MS_A24 );
MS_m /=(MS_D30 - MS_D24);
MS_b = MS_A30 -(MS_m * MS_D30);
*
//看门狗定时器启动。
//默认情况下,时钟源被32,768分频。 在16
WDTCTL =(WDTPW + WDTCNTCL + WDTSSEL + WDTTMSEL);//清除看门狗计时器。
WDTCTL = WDT_MDLY_32;
IE1 |= WDTIE;//启用 WDT 中断。
POWERUP_Timer = 5000;//设置延迟计时器。
System_Flags |= TON_DELAY;//保持与 BAT_BUS 的连接,直到螺钉拧紧且操作系统稳定。
_EINT();//启用所有中断。
//必须添加代码以读取温度传感器并打开和关闭加热器!
//
// P1OUT |= WARM_EN;//打开加热器。
// P1OUT &=~WARM_EN;//关闭加热器。
/*********
*
*主循环顶部
*
(小部分 /
while (1)
{
// P1OUT &=~Ω Test1;//清除 Test1引脚低电平。
// P1OUT |= Test1;//将 Test1引脚设置为高电平。
if (turn on delay ==(turn on delay & System_Flags)){
if (POWERUP_Timer =0){
System_Flags &=~TON_DELAY;//启用整个系统操作。
IpwR_Offset = I_sense - 511;//输入在~零电流时从 A/D 转换器读取的计数。
}
P1OUT &=~Ω Test1;//将 Test1引脚清零。
P1OUT |= Test1;//将 Test1引脚设置为高电平。
}
if (Blink_LED ==(Blink_LED & System_Flags)){
开关(LED_STATE)//***** M_LED 管理器状态机的开始*****
{
案例 LED_WAIT_OFF:
if (LED_Timer =0){
P2OUT &=~M_LED;//打开 M_LED。
LED_Timer = LED_Reload;
LED_STATE = LED_WAIT_ON;
}
中断;
案例 LED_WAIT_ON:
if (LED_Timer =0){
P2OUT |= M_LED;//关闭 M_LED。
LED_Timer = LED_Reload;
LED_STATE = LED_WAIT_OFF;
}
中断;
}
}
if (ADC_BCC ==(ADC_BCC & ADC_Flags)){
ADC_Flags &=~(ADC_BCC);//清除块转换完成标志
/
*
*监视流入或流出电池组的电流
*
*
*
秘书长的报告 /
switch (I_Monitor_state)//***** ADC 数据状态机开始*****
{
案例 I_MON_Zero://是在任一方向上大于零阈值的电流。
if (Integral_Energy >0){ Integral_Energy--;}//自热耗散估计值。
if (Integral_Energy >0){ Integral_Energy--;}//自热耗散估计值。
if (Integral_Energy >0){ Integral_Energy--;}//自热耗散估计值。
if (i_sense > I_Minimum_Pos + 1){//如果正在充电
System_Flags |= Blink_LED;
LED_Reload = 500;
LED_Reload = 50;
I_Monitor_state = I_Pos_Safe;
}
否则、如果(i_sense < I_Minimum_Neg -1){//如果放电
System_Flags |= Blink_LED;
LED_Reload = 50;
LED_Reload = 500;
I_Monitor_state = I_Neg_SAFE;
}
中断;
案例 I_Pos_Safe://电流处于安全充电限制范围内。
if (Integral_Energy >0){ Integral_Energy--;}//自热耗散估计值。
if (i_sense > i_safe_Pos){
LED_Reload = 250;
LED_Reload = 50;
I_Monitor_state = I_Pos_Caution;//开始确保电流降至安全限值。
}
否则,如果( i_sense < I_Minimum_Pos ){
System_Flags &&~Blink_LED;//关闭闪烁。
P2OUT &=~M_LED;//打开 LED。
I_Monitor_state = I_MON_Zero;//当前= 0,转到挂起。
}
中断;
案例 I_Neg_SAFE://电流处于安全放电限值内。
if (Integral_Energy >0){ Integral_Energy--;}//自热耗散估计值。
if (i_sense < i_safe_Neg){
LED_Reload = 50;
LED_Reload = 250;
I_Monitor_state = I_Neg_Caution;//开始确保电流降至安全限值。
}
否则,如果( i_sense >I_Minimum_Neg ){
System_Flags &&~Blink_LED;//关闭闪烁。
P2OUT &=~M_LED;//打开 LED。
I_Monitor_state = I_MON_Zero;//当前= 0,转到挂起。
}
中断;
案例 I_Pos_Caution://输入电流高于安全限值但低于绝对最大限值。
if (i_sense < I_SAFE_Pos){
LED_Reload = 500;
LED_Reload = 50;
I_Monitor_state = I_Pos_Safe;//可以返回。
}
否则,如果( i_sense > I_maximum_Pos ){
P1OUT &=~StR_en;//断开电池串。
LED_Reload = 50;
LED_Reload = 50;
ove_curry_Timer = 3400;//在允许重新启动之前让电池有冷却的机会。
I_Monitor_state = I_MON_Max;//已超出绝对最大值、请等待电流变为零。
}
否则{//估算能耗并在太多情况下切断。
Integrated Energy +=(I_sense - I_safe_Pos);
if (Integrated Energy > Toe_Hot){
P1OUT &=~StR_en;//断开电池串。
LED_Reload = 50;
LED_Reload = 50;
ove_curry_Timer = 3400;//在允许重新启动之前让电池有冷却的机会。
I_Monitor_state = I_MON_Max;//已超出绝对最大值、请等待电流变为零。
}
}
中断;
案例 I_Neg_Caution://放电电流高于安全限值但低于绝对最大限值。
if (i_sense > i_safe_Neg){
LED_Reload = 50;
LED_Reload = 500;
I_Monitor_state = I_Neg_SAFE;//可以返回。
}
否则,如果( i_sense < I_maximum_Neg ){
P1OUT &=~StR_en;//断开电池串。
LED_Reload = 50;
LED_Reload = 50;
ove_curry_Timer = 3400;//在允许重新启动之前让电池有冷却的机会。
I_Monitor_state = I_MON_Max;//已超出绝对最大值、请等待电流变为零。
}
否则{//估算能耗并在太多情况下切断。
Integrated Energy +=(I_Safe_Neg - I_SENSE);
if (Integrated Energy > Toe_Hot){
P1OUT &=~StR_en;//断开电池串。
LED_Reload = 50;
LED_Reload = 50;
ove_curry_Timer = 3400;//在允许重新启动之前让电池有冷却的机会。
I_Monitor_state = I_MON_Max;//已超出绝对最大值、请等待电流变为零。
}
}
中断;
案例 I_MON_Max://输入电流已超过可接受的限值,请尝试恢复。
if (((i_sense < 532)&&(i_sense > 492)){
System_Flags &&~Blink_LED;//关闭闪烁。
P2OUT &=~M_LED;//打开 LED。
I_Monitor_state = I_MON_Zero;//当前= 0,转到挂起。
}
中断;
}
}
if (to_ON_DELAY!=(to_ON_DELAY 和 System_Flags)){
/
*
*监视 BAT_BUS、ADC 通道 A0上的电压
*
*
秘书长的报告 /
switch (A0_Monitor_state)//***** 电池总线电压监控器状态机开始*****
{
案例 A0_connected://输入电流为零安培或接近它。
if (WAIT_Timer=0){
if (cell_POS < Vmin_Cell_top){P1OUT &=~StR_en;A0_Monitor_state = A0_DISCONNECTED;}//从 BAT_BUS 断开电池串。
否则,如果(battery_bus < Vmin_Cell_top){ P1OUT &=~Str_en;A0_Monitor_state = A0_DISCONNECTED;}
否则,如果( Str_en !=( Str_en && P1OUT ){ A0_Monitor_state = A0_DISCONNECTED;}
}
中断;
案例 A0_DISCONNECTED://检查顶部电池的电压是否在电池总线的+/- 3个 ADC 计数内。
if ((((batter_BUS + 6)> CELL_POS)&&((battery_bus - 6)< CELL_POS)){
P1OUT |= StR_en;//将电池字符串连接到 BAT_BUS。
WAIT_Timer = 10;
A0_Monitor_state = A0_Connected;
}
否则,如果(( battery_bus < 20 )&&( I_Monitor_state < I_Pos_Caution )){
P1OUT |= StR_en;//将电池字符串连接到 BAT_BUS。
WAIT_Timer = 10;
A0_Monitor_state = A0_Connected;
}
中断;
案例 A0_Initialize://
P1OUT &=~StR_en;//将电池串与 BAT_BUS 断开。
if (over_current_Timer =0){
P3OUT &=~NI_SENSE_Power;//打开电流传感器 U5的电源。
A0_Monitor_state = A0_DISCONNECTED;
}
中断;
默认值:
Gen_Msg_FLAG1 |= Gen_Msg_0;
A0_Monitor_state = A0_Initialize;
中断;
}//终端开关,监控电池总线上的电压。
}//结束接通延迟。
/
*
*名称:ADC 数据状态机
*
*说明:收集 ADC 的所有电压、电流和温度读数。 该状态
*机器还计算每个模拟输入的最后8个样本的平均值。
*
*收集的数据:
* P2.0 A0 BAT_BUS*
* P2.1 A1 Cell_POS*
* P2.2 A2 MID_STRING*
* P2.3 A3 I_Sns_Volt
* P2.4 A4 VREF_2.5
* P3.0 A5 UCLK
* P3.6 A6 /I_SnS_PWR
* P3.7 A7 /OS_TEMP
秘书长的报告 /
if (ADC_CC ==(ADC_CC & ADC_Flags)){
ADC_Flags &=~(ADC_CC);//清除转换完成标志
switch (ADC_DATA_STstate)//***** ADC 数据状态机开始*****
{
案例 Acquite_A5://模拟输入 A5 -备用模拟、当前分配的数字输出 UCLK。
CH_A5[8]= Ch_A5[ADC_POINTER];//从所有样本之和减去最早的样本。
CH_A5[ADC_POINTER]= Analog _DATA;//保存最新样本。
CH_A5[8]+= Ch_A5[ADC_POINTER];//添加最新样本。
Analog5 = Ch_A5[8]>> 3;//备用输入 A5的平均值=总和/8。
ADC10CTL0 |= ADC10SC;//开始下一次转换。
ADC_DATA_STstate = Acquire _A4;
中断;
案例 Acquire _A4://模拟输入 A4 - VREF_2.5
CH_A4[8]= Ch_A4[ADC_POINTER];//从所有样本之和减去最早的样本。
CH_A4[ADC_POINTER]= Analog _DATA;//保存最新样本。
CH_A4[8]+= Ch_A4[ADC_POINTER];//添加最新样本。
VREF = Ch_A4[8]>> 3;//通道 A4 -基准的平均电压。
ADC10CTL0 |= ADC10SC;//开始下一次转换。
ADC_DATA_STstate = Acquire _A3;
中断;
案例 Acquore_A3://模拟输入 A3 - I_Sns_Volt -流入或流出电池串的电流。
CH_A3[8]= Ch_A3[ADC_POINTER];//从所有样本之和减去最早的样本。
CH_A3[ADC_POINTER]= Analog _DATA - IMPw_Offset;//保存最新样本更少传感器偏移。
CH_A3[8]+= Ch_A3[ADC_POINTER];//添加最新样本。
if ((Ch_A3[ADC_POINTER]< 25)||(Ch_A3[ADC_POINTER]> I_maximum_Pos)(
P1OUT &=~StR_en;//断开电池串。
P3OUT |= NI_SENSE_Power;//通过循环通电到 U5来重置电流传感器的故障标志。
LED_Reload = 50;
LED_Reload = 50;
OVER 电流计时器= 34;//在允许重新启动之前为电池提供冷却的机会。
I_Monitor_state = I_MON_Max;//已超出绝对最大值、请等待电流变为零。
A0_Monitor_state = A0_Initialize;//查看是否可以将电池串重新连接到 BAT_BUS。
}
I_SENSE = Ch_A3[8]>> 3;//通道 A3 -电池串输入或输出的平均电流。
ADC10CTL0 |= ADC10SC;//开始下一次转换。
ADC_DATA_STstate = Acquire _A2;
中断;
案例 Acquire _A2://模拟输入 A2 - MID_STRING*
CH_A2[8]= Ch_A2[ADC_POINTER];//从所有样本之和减去最早的样本。
CH_A2[ADC_POINTER]= Analog _DATA;//保存最新样本。
CH_A2[8]+= Ch_A2[ADC_POINTER];//添加最新样本。
MID_STRING = Ch_A2[8]>> 3;// Ch A2 -电芯串中心抽头的平均电压。
// ms_f = ms_m * mid_string + ms_b;//计算调整后的浮点等效值。
ADC10CTL0 |= ADC10SC;//开始下一次转换。
ADC_DATA_STstate = Acquire _A1;
中断;
案例 Acquire _A1://模拟输入 A1 - Cell_POS*
CH_A1[8]= Ch_A1[ADC_POINTER];//从所有样本之和减去最早的样本。
CH_A1[ADC_POINTER]= Analog _DATA;//保存最新样本。
CH_A1[8]+= Ch_A1[ADC_POINTER];//添加最新样本。
CELL_POS = Ch_A1[8]>> 3;// Ch A1 -顶部电池的平均电压。
// cp_f = cp_m * CELL_POS + cp_b;//计算调整后的浮点等效值。
ADC10CTL0 |= ADC10SC;//开始下一次转换。
ADC_DATA_STstate = Acquire _A0;
中断;
案例 Acquire _A0://模拟输入 A0 - BAT_BUS*
CH_A0[8]= Ch_A0[ADC_POINTER];//从所有样本之和减去最早的样本。
CH_A0[ADC_POINTER]= Analog _DATA;//保存最新样本。
CH_A0[8]+= Ch_A0[ADC_POINTER];//添加最新样本。
BATTERY_BUS = Ch_A0[8]>> 3;//通道 A0 -电池总线上的平均电压。
// bbb_f = bbb_m * battery_bus + bb_b;//计算调整后的浮点等效值。
//内部管理
//
ADC10CTL0 &=~(ENC + ADC10SC);//禁用 ADC
if (+ADC_Pointer > 7){ ADC_Pointer = 0;}//指向数组中的下一个元素。
if (adc_Real!=(adc_Real 和 adc_Flags)){
if (REAL_Data_Count!= 0){REAL_Data_Count--;}
否则{ADC_Flags |= ADC_REAL;}//告知主循环数据现在是可靠的。
}
ADC_Flags |= ADC_BCC;//设置数据块完成标志。
ADC10CTL0 |=(ENC + ADC10SC);//开始新的块转换
if (WAIT_Timer >0){ WAIT_Timer--;}//如果尚未为0,则递减计时器。
ADC_DATA_STstate = Acquire _A5;// Go 获取下一个转换块
中断;
默认值:
Gen_Msg_FLAG1 |= Gen_Msg_0;
ADC_DATA_STstate = Acquire _A5;
中断;
}//结束开关***** ADC 数据状态机底部*****
}//如果 ADC_CC 和 PACKE_DEFAULT 则结束
/
*
*电位计命令处理器。
*
秘书长的报告 /
开关(Command_State)
{
案例 Cmd_PoT_Idle:
if (Command_Flags!= 0x00){
if (Cmd_set_PoT_WCR =(Cmd_Set_PoT_WCR 和 Command_Flags)){ Command_State = Cmd_PoT_Set_WCR;}
否则,if (Cmd_incument_Pot ==(Cmd_Increment_Pot & Command_Flags){ Command_State = Cmd_PoT_Increment;}
否则,如果( Cmd_Decreime_Pot ==( Cmd_Decreime_Pot & Command_Flags ){ Command_State = Cmd_PoT_Decrement;}
否则,if (Cmd_set_PoT_DR ==(Cmd_set_PoT_DR 和 Command_Flags){ Command_State = Cmd_PoT_Set_DR;}
否则{Command_Flags = 0x00;}
}
中断;
案例 Cmd_PoT_SET_WCR://将电位计设置为 WOPER_VALUE 的值。
开关(Sub_A_Cmd_State)
{
案例 Sub_A_Cmd1://发送电位计命令的数据包1。
if (POT_WR_PKT!=(POT_WR_PKT 和 System_Flags)){//确保最后一个数据包传输完成。
DATA_Array_PTR = 0;
DATA_Array_Last = 2;
LOCAL_Data[0]= POT_ACR_wr;
LOCAL_Data[1]= POT_AR;
LOCAL_Data[2]= POT_WCR;
System_Flags |= POT_WR_PKT;//开始向电位计写入数据包。
SUB_A_Cmd_State = Sub_A_Cmd2;
}
中断;
案例 Sub_A_Cmd2://发送电位计命令的数据包2。
if (POT_WR_PKT!=(POT_WR_PKT & System_Flags)){
DATA_Array_PTR = 0;
LOCAL_Data[1]= 0;
LOCAL_Data[2]= 0;
System_Flags |= POT_WR_PKT;//开始向电位计写入数据包。
SUB_A_Cmd_State = Sub_A_Cmd3;
}
中断;
案例 Sub_A_Cmd3://等待第二个数据包完成。
if (POT_WR_PKT!=(POT_WR_PKT & System_Flags)){
SUB_A_Cmd_State = Sub_A_Cmd1;
Command_Flags &=~Cmd_SET_POT_WCR;//终止此命令。
packet_Timer = 0x1000;
COMMAND_STATE = Cmd_PoT_Idle;// GO 等待下一条命令。
}
中断;
}
中断;
案例 Cmd_PoT_Increment://递增电位计设置。
开关(Sub_B_Cmd_State)
{
案例 Sub_B_Cmd1:
if (POT_WR_PKT!=(POT_WR_PKT & System_Flags)){
DATA_Array_PTR = 0;
DATA_Array_Last = 2;
LOCAL_Data[0]= POT_ACR_wr;
LOCAL_Data[1]= POT_AR;
LOCAL_Data[2]= POT_WCR;
System_Flags |= POT_WR_PKT;//开始向电位计写入数据包。
SUB_B_Cmd_State = Sub_B_Cmd2;
}
中断;
案例 Sub_B_Cmd2:
if (POT_WR_PKT!=(POT_WR_PKT & System_Flags)){
DATA_Array_PTR = 0;
LOCAL_Data[1]= 0;// WCR 地址。
LOCAL_Data[2]= 0xFF;//递增命令。
System_Flags |= POT_WR_PKT;//开始向电位计写入数据包。
SUB_B_Cmd_State = Sub_B_Cmd3;
}
中断;
案例 Sub_B_Cmd3://等待第二个数据包完成。
if (POT_WR_PKT!=(POT_WR_PKT & System_Flags)){
SUB_B_Cmd_State = Sub_B_Cmd1;
Command_Flags &=~Cmd_Increment_Pot;//终止此命令。
COMMAND_STATE = Cmd_PoT_Idle;// GO 等待下一条命令。
}
中断;
}
中断;
案例 Cmd_PoT_Decrement://测量电位计设置。
开关(Sub_C_Cmd_State)
{
案例 Sub_C_Cmd1:
if (POT_WR_PKT!=(POT_WR_PKT & System_Flags)){
DATA_Array_PTR = 0;
DATA_Array_Last = 2;
LOCAL_Data[0]= POT_ACR_wr;
LOCAL_Data[1]= POT_AR;
LOCAL_Data[2]= POT_WCR;
System_Flags |= POT_WR_PKT;//开始向电位计写入数据包。
SUB_C_Cmd_State = Sub_C_Cmd2;
}
中断;
案例 Sub_C_Cmd2:
if (POT_WR_PKT!=(POT_WR_PKT & System_Flags)){
DATA_Array_PTR = 0;
LOCAL_Data[0]= 0x58;//从机地址递增或递减。
LOCAL_Data[1]= 0;// WCR 地址。
LOCAL_Data[2]= 0;//减量命令。
System_Flags |= POT_WR_PKT;//开始向电位计写入数据包。
SUB_C_Cmd_State = Sub_C_Cmd1;
Command_Flags &=~Cmd_Decreime_Pot;//终止此命令。
COMMAND_STATE = Cmd_PoT_Idle;// GO 等待下一条命令。
}
中断;
}
中断;
案例 Cmd_PoT_Set_DR://将特定值写入电位器数据寄存器。
Command_Flags &=~Cmd_SET_POT_DR;//终止此命令。
COMMAND_STATE = Cmd_PoT_Idle;// GO 等待下一条命令。
中断;
默认值:
Gen_Msg_FLAG1 |= Gen_Msg_0;//发送进入电子邮件。
COMMAND_STATE = Cmd_PoT_Idle;// GO 等待下一条命令。
中断;
}
/
*
*说明:将一个字节的数据写入 I2C 器件。 假定 START 位已经被发送并且 SMBCLK 为低电平
*参数:数据-从器件地址或寄存器地址
*如果从从器件接收到 ACK、则返回值:1;否则为0
*
*在写入序列完成之前、SMBdata 行会在 ACK 和之前立即释放
*在 ACK 后、SMBCLK 线路被切换为高电平、然后被切换为低电平。
(三 /
if (POT_WRITE =(POT_WRITE & System_Flags)){//如果已启动电位计 SMBus 字节写入,则...
// P3OUT &=~BIT3;//清除 P3输出寄存器,当引脚方向设置为输出时硬下拉。
// P3OUT |= BIT3;//清除 P3输出寄存器,当引脚方向设置为输出时硬下拉。
//这是对电位器的字节写入操作。
开关(POT_WR_STATE)//***** SMBus 字节写入状态机的开始*****
{
Case PoT_Write_Init://初始化字节写入状态机。
bit_Mask = 0x80;
POT_WR_STATE = POT_BIT_Write;
中断;
Case PoT_bit_Write:
if (--PoT_Timer =0){
if (bit_Mask & SMBus_Buffer){SMBdata_set;}else{SMBdata_Clr;}
POT_Timer = SMB_Dly4;
POT_WR_STATE = POT_Byte_Write;
}
中断;
Case PoT_Byte_Write:
if (--PoT_Timer =0){
SMBCLK_SET;//将 BBB_SCL IO 引脚设置为输入模式并被外部电阻器拉高。
POT_Timer = SMB_Dly4;
POT_WR_STATE = POT_Clk_HIA;
}
中断;
Case PoT_Clk_HIA:
if (--PoT_Timer =0){PoT_WR_State = PoT_Clk_LOA;PoT_Timer = SMB_Dly4;}
中断;
Case PoT_Clk_LOA:
if (--PoT_Timer =0){
SMBCLK_Clr;//强制 BBB_SCL 线路为低电平。
bit_Mask >=1;
if (bit_Mask =0){PoT_WR_State = PoT_END_Byte;}否则{PoT_WR_State = PoT_bit_Write;}
POT_Timer = SMB_Dly4;
}
中断;
Case PoT_END_Byte://释放 SMBdata 以便从器件可以应答。
if (--PoT_Timer =0){
SMBDATA_SET;
POT_Timer = SMB_Dly4;
POT_WR_STATE = POT_Clk_HiB;
}
中断;
Case PoT_Clk_HIB://再次切换 BBB_SCL 行以终止字节写入序列。
if (--PoT_Timer =0){
SMBCLK_SET;//将 BBB_SCL IO 引脚设置为输入模式并被外部电阻器拉高。
POT_Timer = SMB_Dly4;
POT_WR_STATE = POT_Clk_LoB;
}
中断;
Case PoT_Clk_LoB:
if (--PoT_Timer =0){
SMBCLK_Clr;//强制 BBB_SCL 线路为低电平。
//已设置=(P1IN & TS_SDA);//从从器件读取确认。
// if (acked =0){
//}
POT_Timer = SMB_Dly4;
POT_WR_STATE = POT_Clk_END;
}
中断;
Case PoT_Clk_End:
System_Flags &=~POT_WRITE;//终止字节写入操作。
POT_WR_STATE = POT_Write_Init;//重新布设状态机。
中断;
默认值:
System_Flags &=~POT_WRITE;//终止字节写入操作。
Gen_Msg_FLAG1 |= Gen_Msg_0;//发送进入电子邮件。
POT_WR_STATE = POT_Write_Init;// Go 等待下一条命令。
中断;
}// Endswitch PoT_WR_State。
}// endif 字节写入。
if (pot_write!=(pot_write & System_Flags)){//在这里等待电位器数据包传输标志。
/
*
*对电位器执行数据包写入操作。
*
此时、电位器和主器件必须将 BBB_SDA 和 BBB_SCL 置为无效、以确保
*正确的启动顺序。
*
(三 /
switch (PoT_Pkt_WR_State)//***** SMBus 数据包写入状态机的开始*****
{
Case PoT_Pkt_WR_Idle://等待数据包启动序列。
if (POT_WR_PKT =(POT_WR_PKT 和 System_Flags)){ POT_Pkt_WR_State = POT_Pkt_WR_ST2;}
中断;
Case PoT_Pkt_WR_ST2://开始序列。
if (--PoT_Timer =0){
SMBdata_Clr;//丢弃数据线。
POT_Timer = SMB_Dly4;
POT_Pkt_WR_State = POT_Pkt_WR_Start;
}
中断;
Case PoT_Pkt_WR_Start://丢弃时钟线。
if (--PoT_Timer =0){
SMBCLK_Clr;//强制 BBB_SCL 线路为低电平。
POT_Timer = SMB_Dly4;
POT_Pkt_WR_State = POT_Pkt_WR_Data;
}
中断;
Case PoT_Pkt_WR_Data://发送字节序列。
if (((Data_Array_PTR <= Data_Array_Last)&&(POT_write!=(POT_write & System_Flags))){
SMBus_Buffer = local_Data[Data_Array_PTR];//复制下一个要传输到传输缓冲区的数据字节。
DATA_Array_PTR++;//递增数组索引。
System_Flags |= POT_WRITE;//设置 SMBus 写入字节标志。
}
否则{PoT_Pkt_WR_State = PoT_Pkt_WR_stop1;}
中断;
Case PoT_Pkt_WR_stop1://使用停止序列结束数据传输。
if (--PoT_Timer =0){
SMBdata_Clr;//丢弃数据线。
POT_Timer = SMB_Dly4;
POT_Pkt_WR_State = POT_Pkt_WR_Stop2;
}
中断;
Case PoT_Pkt_WR_Stop2://提高时钟线。
if (--PoT_Timer =0){
SMBCLK_SET;//将 BBB_SCL IO 引脚设置为输入模式并被外部电阻器拉高。
POT_Timer = SMB_Dly4;
POT_Pkt_WR_State = POT_Pkt_WR_Stop3;
}
中断;
Case PoT_Pkt_WR_Stop3://提起数据线以完成序列。
if (--PoT_Timer =0){
SMBDATA_SET;// SMBus 现在空闲。
System_Flags &=~POT_WR_PKT;//禁用电位计数据包发送。
POT_Timer = SMB_Dly4;
POT_Pkt_WR_State = POT_Pkt_WR_Idle;//重新布设状态机。
}
中断;
默认值:
SMBCLK_SET;//将 BBB_SCL IO 引脚设置为输入模式并被外部电阻器拉高。
SMBDATA_SET;// SMBus 现在空闲。
System_Flags &=~POT_WR_PKT;//禁用电位计数据包发送。
Gen_Msg_FLAG1 |= Gen_Msg_0;//发送进入电子邮件。
POT_Pkt_WR_State = POT_Pkt_WR_Idle;//重新布设状态机。
中断;
}//***** SMBus 数据包写入状态机结束*****
}//如果数据包发送标志被置位则结束。
Watch_dog = watch_time_out;//重新启动看门狗计时器
}//结束 while (1)
}//========================================= Main 的末尾================================================================
//=================== isRs ================================================================================================
/*----------------------------------
*名称:evadc_isr
*
*描述:
*对 ADC 进行了转换
*设置最多样化的进程标志
*
*
******************------------------------------------------------------- *
#pragma vector = ADC10_vector
_interrupt void evADC_ISR (void)
{
_dint();
ADC_Flags |= ADC_CC;//设置转换完成标志
ADC10CTL0 &=~(ADC10IFG);//清除 ADC 转换完成中断标志
ANALOG_DATA = ADC10MEM;//将来自 ADC 的数据保存在临时缓冲区中
ADC10CTL0 &=~ADC10SC;//开始下一次转换。
_EINT();
}
/
*名称:evRTC_ISR
*
*说明:实时时钟中断处理器。
*此例程设置进程标志以通知主进程
*个事件并重新初始化各种计数器。
*
(小部分 /
#pragma vector = WDT_Vector
_interrupt void evRTC_ISR (void)
{
_dint();
if (Watch_Dog!= 0){ Watch_Dog --;}//如果计数达到0,则停止倒计时。
否则{WDTCTL = 0x00 + WDTHOLD;}//超时、发生了错误、请尝试软重启以恢复。
if (over_curry_Timer!= 0){ove_curry_Timer-;}//如果计数达到0,则停止倒计时。
if (LED_Timer!= 0){ LED_Timer--;}//如果计数达到0,则停止倒计时。
if (POWERUP_Timer!= 0){POWERUP_Timer-;}//如果计数达到0,则停止倒计时。
IFG1 &=~WDTIFG;//复位定时器标志、启用下一个中断。
_EINT();
}