/************************** Copyright (c) **********************************
|
** FUZHOU FUGUANG ELECTRONICS Co.,LTD.
|
** 福州福光电子有限公司
|
** http://www.fuguang.com
|
**
|
**-------------- File Info -------------------------------------------------
|
** File name: NRF905_Driver.c
|
** Last modified Date: 2008-11-16
|
** Last Version: 1.0
|
** Descriptions: NRF905 Drivers lib
|
**
|
**--------------------------------------------------------------------------
|
** Created by: mxpopstar
|
** Created date: 2008-11-16
|
** Version: 1.0
|
** Descriptions: The original version
|
**
|
**--------------------------------------------------------------------------
|
** Modified by: mxpopstar
|
** Modified date: 2008-11-20
|
** Version:
|
** Descriptions: NRF905 Drivers lib
|
**
|
***************************************************************************/
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
#include "NRF905_Driver.h"
|
#include "M64ADC_Driver.h"
|
#include <avr/eeprom.h>
|
#include "SYSSetPage.h"
|
#include "Buzzer_Driver.h"
|
#include "TFT_Driver.h"
|
#include "WorkingPage.h"
|
#include "ChargePage.h"
|
#include <avr/eeprom.h>
|
#include <avr/pgmspace.h>
|
#include "SingleVol.h"
|
#include "CRC16.h"
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
extern volatile unsigned int GB_TestingParm[15];
|
extern volatile FBO_Data GB_FBO_Data;
|
extern volatile SYS_State GB_SYS_State;
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
#if(SoftLanguage == CN)
|
const prog_uchar MonomerOrderText[2][7] =
|
{
|
{230, 68, 69, 231, 233, 234, 235},//从组端正极递增
|
{230, 68, 69, 232, 233, 234, 235},//从组端负极递增
|
};
|
const prog_uchar NRF905Text[3][1] =
|
{
|
{101},
|
{244}, //无线单体图标
|
{245}, //有线单体图标
|
};
|
//
|
#else
|
const prog_uchar MonomerOrderText[2][5] =
|
{
|
{107,78,0,11},//从组端正极递增4
|
{107,78,0,13},//从组端负极递增
|
};
|
const prog_uchar NRF905Text[3][1] =
|
{
|
{0},
|
{33}, //无线单体图标
|
{34}, //有线单体图标
|
};
|
//
|
#endif
|
//
|
|
/*
|
const prog_uchar MonomerAlarmText[1][10] =
|
{
|
{101,101,157,70, 71, 158,159,168,169,137},//XX号单体模块异常!
|
};
|
//
|
*/
|
static unsigned char RFConfig[10] =
|
{
|
0x6b,0x0c,0x44,0x10,0x10,0xAB,0xCD,0xFF,0xF0,0xdf
|
};
|
//
|
// The content of this struct is nRF905's initialize data.
|
// CH_NO=1;433MHZ;Normal Opration,No Retrans;RX,TX Address is 4 Bytes
|
// RX TX Payload Width is 32 Bytes;Disable Extern Clock;Fosc=16MHZ
|
// 8 Bits CRC And enable
|
|
//static unsigned char EEpMasterADDR __attribute__((section(".eeprom"))) = 0xF0;
|
|
static unsigned char MonomerModuleType = MonomeTypeNull;
|
|
static MonomerVolState m_MonomerVolState;
|
static RFData m_RFDataTX,m_RFDataRX,m_RFCurTX,m_RFCurRX;
|
static unsigned int MonomerLowTag[32] = {0};
|
|
unsigned int EEPMonomerOrder __attribute__((section(".eeprom"))) = 0;
|
|
//function InitIO();
|
/*******************************************************************************************/
|
void InitIO_NRF905(void)
|
{
|
DDRB |= 0x86; // PINB
|
DDRB &= ~0x08; //MISO - PINB3
|
DDRD |= 0x10; //CSN - PIND4
|
DDRD &= ~0x01; //DR - PIND0
|
DDRG |= 0x18; //POWER_UP-PING4,TRX_CE-PING3,
|
|
DDRD |= (1<<PD5);
|
PORTD |= (1<<PD5);//RS485有线单体中继片选;
|
|
NRF905_SPI_OFF; // Spi disable
|
SCK_0; // Spi clock line init high
|
PWR_UP_1; // nRF905 power on
|
TRX_CE_0; // Set nRF905 in standby mode
|
TX_EN_0; // set radio in Rx mode
|
|
m_MonomerVolState.MonomerEnabled = 0;
|
|
m_MonomerVolState.ModuleSum = 6;
|
m_MonomerVolState.EachGroupModule = 6;
|
m_MonomerVolState.MasterADDR = 0xF0;
|
eeprom_busy_wait();
|
m_MonomerVolState.MonomerOder = eeprom_read_word(&EEPMonomerOrder);
|
m_MonomerVolState.ModuleStartIndex = 1;
|
|
for(unsigned char m=0; m<4; m++)
|
{
|
m_MonomerVolState.MonomerMaxVol[m] = 0;
|
m_MonomerVolState.MonomerMinVol[m] = 0;
|
m_MonomerVolState.MonomerMaxIndex[m] = 0;
|
m_MonomerVolState.MonomerMinIndex[m] = 0;
|
}
|
m_MonomerVolState.ModuleDropCount = 0;
|
m_MonomerVolState.ModuleDropIndex = 0;
|
m_MonomerVolState.StopMVolCount = 0;
|
m_MonomerVolState.ClampDropCount = 0; //电流钳异常总数
|
m_MonomerVolState.ClampDropIndex = 0; //异常电流钳编号
|
m_MonomerVolState.ClampType = ClampTypeNull;
|
|
m_RFDataTX.Addr[0] = 0xAB;
|
m_RFDataTX.Addr[1] = 0xCD;
|
m_RFDataTX.Addr[2] = 0xFF;
|
m_RFDataTX.Addr[3] = 0xF0;
|
m_RFDataTX.CMD = 0x00A0;
|
|
m_RFCurTX.Addr[0] = 0xAB;
|
m_RFCurTX.Addr[1] = 0xCD;
|
m_RFCurTX.Addr[2] = 0xFF;
|
m_RFCurTX.Addr[3] = 0xF0;
|
m_RFCurTX.CMD = 0x00AA;
|
|
_delay_ms(1);
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
SetRxMode();
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
}
|
/*******************************************************************************************/
|
|
//function Config905();
|
/*******************************************************************************************/
|
void Write_Config905(void)
|
{
|
unsigned char n;
|
|
NRF905_SPI_EN; // Spi enable for write a spi command
|
SpiWrite(WC); // Write config command
|
for (n=0; n<10; n++) // Write configration words
|
{
|
if(n == 8)
|
{
|
SpiWrite(m_MonomerVolState.MasterADDR);
|
}
|
else
|
{
|
SpiWrite(RFConfig[n]);
|
}
|
}
|
NRF905_SPI_OFF; // Disable Spi
|
}
|
/*******************************************************************************************/
|
|
void Read_Config905(unsigned char *buf)
|
{
|
unsigned char i;
|
NRF905_SPI_EN; // Spi enable for write a spi command
|
SpiWrite(RC); // Write config command
|
for(i=0; i<10; i++) // Write configration words
|
{
|
*buf++=SpiRead();
|
}
|
NRF905_SPI_OFF; // Disable Spi
|
}
|
/*******************************************************************************************/
|
|
//function SpiWrite();
|
/*******************************************************************************************/
|
void SpiWrite(const unsigned char byte)
|
{
|
unsigned char i;
|
for (i=0; i<8; i++) // Setup byte circulation bits
|
{
|
if (0x80 & (byte<<i)) // Put DATA_BUF.7 on data line
|
MOSI_1;
|
else
|
MOSI_0;
|
SCK_1; // Set clock line high
|
_delay_us(5);
|
SCK_0; // Set clock line low
|
_delay_us(5);
|
}
|
}
|
/*******************************************************************************************/
|
|
//function SpiRead();
|
/*******************************************************************************************/
|
unsigned char SpiRead(void)
|
{
|
unsigned char i;
|
unsigned char data = 0;
|
for (i=0; i<8; i++) // Setup byte circulation bits
|
{
|
SCK_1; // Set clock line high
|
_delay_us(5);
|
if (MISO_1)
|
data += 1; // Read data
|
if(i<7)
|
data <<= 1;
|
SCK_0; // Set clock line low
|
_delay_us(5);
|
}
|
return data; // Return function parameter
|
}
|
/*******************************************************************************************/
|
|
//function TxPacket();
|
/*******************************************************************************************/
|
void TxPacket(const unsigned char *addr, const void *datas)
|
{
|
unsigned char *pdatas = (unsigned char *)datas;
|
unsigned char i;
|
|
NRF905_SPI_EN; // Spi enable for write a spi command
|
SpiWrite(WTA); // Write address command
|
for (i=0; i<ADDR_len; i++) // Write 4 bytes address
|
{
|
SpiWrite(*addr++);
|
}
|
NRF905_SPI_OFF; // Spi disable
|
|
_delay_us(10);
|
|
NRF905_SPI_EN; // Spi enable for write a spi command
|
SpiWrite(WTP); // Write payload command
|
for (i=0; i<TRDATA_len; i++)
|
{
|
SpiWrite(*pdatas++); // Write 32 bytes Tx data
|
}
|
NRF905_SPI_OFF; // Spi disable
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
SetTxMode();
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
TRX_CE_1; // Set TRX_CE high,start Tx data transmission
|
_delay_ms(1);
|
TRX_CE_0; // Set TRX_CE low
|
}
|
/*******************************************************************************************/
|
|
//function RxPacket();
|
/*******************************************************************************************/
|
void RxPacket(void *rxdata)
|
{
|
unsigned char *pdata = (unsigned char *)rxdata;
|
unsigned char i;
|
TRX_CE_0; // Set nRF905 in standby mode
|
NRF905_SPI_EN; // Spi enable for write a spi command
|
SpiWrite(RRP); // Read payload command
|
for (i=0; i<TRDATA_len; i++)
|
{
|
*pdata++ = SpiRead(); // Read data and save to buffer
|
}
|
NRF905_SPI_OFF; // Disable spi
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
SetRxMode(); //设置为接收模式
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
}
|
/*******************************************************************************************/
|
void Set905Fre(const unsigned char fre)
|
{
|
RFConfig[0] = fre;
|
}
|
//function SetTxMode();
|
/*******************************************************************************************/
|
void SetTxMode(void)
|
{
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
TRX_CE_0;
|
TX_EN_1;
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
_delay_ms(2); // delay for mode change(>=650us)
|
}
|
/*******************************************************************************************/
|
|
//function SetRxMode();
|
/*******************************************************************************************/
|
void SetRxMode(void)
|
{
|
TX_EN_0;
|
TRX_CE_1;
|
_delay_ms(2); // delay for mode change(>=650us)
|
}
|
/*******************************************************************************************/
|
//--------------------------------------------------------------------------------------------------
|
unsigned char CheckDataIfOK(const unsigned char *ADDR, RFData* m_RFData)
|
{
|
unsigned int crc;
|
//---------------- 数据的CRC校验和从机的地址核对 -------------------
|
crc = CalCRC16(m_RFData, sizeof(RFData)-2);
|
|
if((crc==m_RFData->CRC)&&(m_RFData->CMD!=0)
|
&&((m_RFData->Addr[2])==ADDR[2])&&((m_RFData->Addr[3])==ADDR[3]))
|
{
|
return 0;
|
}
|
else
|
{
|
return 1;
|
}
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
void DSPMonomerModuleType(const unsigned int px, const unsigned int py, const unsigned char color)
|
{
|
if(MonomerModuleType == MonomeTypeNull)
|
DSP24x24Graph(NRF905Text[0], 1, 24, px, py, blue, color);
|
else if(MonomerModuleType == MonomeWireless)
|
DSP24x24Graph(NRF905Text[1], 1, 24, px, py, blue, color);
|
else if(MonomerModuleType == MonomeLine)
|
DSP24x24Graph(NRF905Text[2], 1, 24, px, py, blue, color);
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
unsigned char GetNRF905Data(const unsigned char *TX_ADDR, const void *TXData, void *RXData)
|
{
|
unsigned char error = 0;
|
|
((RFData*)TXData)->Addr[0] = 0xAB;
|
((RFData*)TXData)->Addr[1] = 0xCD;
|
((RFData*)TXData)->Addr[2] = 0xFF;
|
((RFData*)TXData)->Addr[3] = 0xF0;
|
((RFData*)TXData)->CRC = CalCRC16(TXData, sizeof(RFData)-2);
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
for(unsigned char cnt=0; cnt<3; cnt++)
|
{
|
unsigned char t=0;
|
TxPacket(TX_ADDR, TXData); // Transmit Tx buffer data
|
SetRxMode();
|
_delay_ms(10);
|
while(t++ < 20)//---2012-03-15:20改为40,改回20
|
{
|
if(DR)
|
goto PROCESS;
|
else
|
_delay_ms(1);
|
}
|
}
|
|
PROCESS:
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
if(DR) // If recive data ready...
|
{
|
RxPacket(RXData); // ... recive data
|
error = CheckDataIfOK(TX_ADDR, (RFData*)RXData);
|
}
|
else // 没有收到单体模块数据
|
{
|
error = 2; //错误标志位置1
|
}
|
|
if(error == 0)
|
{
|
MonomerModuleType = MonomeWireless;
|
}
|
|
return error;
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
unsigned char GetRS485Data(const unsigned char *TX_ADDR, void *TXData, void *RXData)
|
{
|
unsigned char *pTXdata = (unsigned char *)TXData;
|
unsigned char *pRXdata = (unsigned char *)RXData;
|
unsigned char t=0;
|
unsigned char error = 0;
|
|
for(t=0; t<4; t++)
|
{
|
*pTXdata++ = TX_ADDR[t];
|
}
|
pTXdata = (unsigned char *)TXData;
|
|
((RFData*)TXData)->CRC = CalCRC16(TXData, sizeof(RFData)-2);
|
|
Max485SPI_CS_0; //开始片选
|
for(t=0; t<4; t++) //发送同步码
|
{
|
SpiWrite(0xAA);
|
}
|
for(t=0; t<sizeof(RFData); t++) //发送数据
|
{
|
SpiWrite(*pTXdata++);
|
}
|
|
_delay_ms(10); //延时10ms
|
|
for(t=0; t<sizeof(RFData); t++) //接收数据
|
{
|
*pRXdata++ = SpiRead();
|
_delay_us(10);
|
}
|
Max485SPI_CS_1; //结束片选
|
|
error = CheckDataIfOK(TX_ADDR, (RFData*)RXData);
|
|
if(error == 0)
|
{
|
MonomerModuleType = MonomeLine;
|
}
|
|
return error; //错误标志位置1
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
//---------------- 使能和禁用无线单体采集 ----------------------------------
|
void EnableMonomerVolGether(void)
|
{
|
m_MonomerVolState.MonomerEnabled = 1;
|
}
|
void DisableMonomerVolGether(void)
|
{
|
m_MonomerVolState.MonomerEnabled = 0;
|
}
|
unsigned char GetMonomerVolGetherState(void)
|
{
|
return m_MonomerVolState.MonomerEnabled;
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
void SetEachGroupBattSum(unsigned int value)
|
{
|
m_MonomerVolState.EachGroupBattSum = value;
|
}
|
unsigned int GetEachGroupBattSum(void)
|
{
|
return m_MonomerVolState.EachGroupBattSum;
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
//---------------- 获取单体电压最大最小值 ----------------------------------
|
/*
|
unsigned int GetStopMVolCountSet(void)
|
{
|
return m_MonomerVolState.StopMVolCountSet;
|
}
|
void GetAndDspStopMVolCountSet(void)
|
{
|
if(GB_SYS_State.CurrentPage == DSPSYSSetPage)
|
{
|
PrintValue(2, 0, m_MonomerVolState.StopMVolCountSet, "#", 16, 328, 304, blue, yellow); //XXXM
|
}
|
}
|
void SetStopMVolCountSet(unsigned char value)
|
{
|
if(value == 0)
|
{
|
if(m_MonomerVolState.StopMVolCountSet < GB_FBO_Data.BattSum)
|
{
|
m_MonomerVolState.StopMVolCountSet++;
|
return;
|
}
|
}
|
else
|
{
|
if(m_MonomerVolState.StopMVolCountSet > 1)
|
{
|
m_MonomerVolState.StopMVolCountSet--;
|
return;
|
}
|
}
|
BuzzerBeep(50);
|
}
|
*/
|
unsigned int GetMLimitVolCount(void)
|
{
|
return m_MonomerVolState.StopMVolCount;
|
}
|
unsigned char GetStopMonomerVolStop(void)
|
{
|
if(m_MonomerVolState.StopMVolCount >= GB_TestingParm[11])
|
return 1;
|
else return 0;
|
}
|
unsigned int GetMonomerMaxVol(unsigned char index)
|
{
|
return m_MonomerVolState.MonomerMaxVol[index];
|
}
|
unsigned int GetMonomerMinVol(unsigned char index)
|
{
|
return m_MonomerVolState.MonomerMinVol[index];
|
}
|
unsigned int GetMonomerMaxIndex(unsigned char index)
|
{
|
return m_MonomerVolState.MonomerMaxIndex[index];
|
}
|
unsigned int GetMonomerMinIndex(unsigned char index)
|
{
|
return m_MonomerVolState.MonomerMinIndex[index];
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
void ClearModuleError(void)
|
{
|
m_MonomerVolState.ModuleDropIndex = 0;
|
m_MonomerVolState.ModuleDropCount = 0;
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
//-------------------- 获取脱落的单体模块编号 ------------------------------
|
unsigned char GetModuleDropIndex(void)
|
{
|
return m_MonomerVolState.ModuleDropIndex;
|
}
|
/*
|
void SetModuleDropIndex(const unsigned char num)
|
{
|
m_MonomerVolState.ModuleDropIndex = num;
|
}
|
*/
|
unsigned char GetClampDropIndex(void)
|
{
|
return m_MonomerVolState.ClampDropIndex;
|
}
|
unsigned char GetClampType(void)
|
{
|
return m_MonomerVolState.ClampType;
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
//-------------------- 根据电池数量确定模块数量 ----------------------------
|
void SetModuleSum(const unsigned int eachgroupbattsum, const unsigned char group)
|
{
|
if((eachgroupbattsum%4) == 0)
|
m_MonomerVolState.EachGroupModule = (unsigned char)(eachgroupbattsum/4);
|
else m_MonomerVolState.EachGroupModule = (unsigned char)(eachgroupbattsum/4 + 1);
|
|
m_MonomerVolState.ModuleSum = m_MonomerVolState.EachGroupModule * group;
|
}
|
unsigned int GetModuleSum(void)
|
{
|
return m_MonomerVolState.ModuleSum;
|
}
|
unsigned int GetEachGroupModule(void)
|
{
|
return m_MonomerVolState.EachGroupModule;
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
/*
|
//------------------- 设置和显示本主机的无线通信地址 -----------------------
|
void GetAndDSPMasterADDR(void)
|
{
|
if(GB_SYS_State.CurrentPage == DSPSYSSetPage)
|
{
|
PrintValue(3, 0, m_MonomerVolState.MasterADDR-0xF0, "", 16, 280, 176, blue, yellow);
|
}
|
}
|
*/
|
unsigned char GetMasterADDR(void)
|
{
|
return m_MonomerVolState.MasterADDR;
|
}
|
/*
|
void SetMasterADDR(const unsigned char settype)
|
{
|
if(settype == 0)
|
{
|
if(m_MonomerVolState.MasterADDR++ >= 0xFF)
|
{
|
m_MonomerVolState.MasterADDR = 0xF0;
|
}
|
}
|
else
|
{
|
if(m_MonomerVolState.MasterADDR-- <= 0xF0)
|
{
|
m_MonomerVolState.MasterADDR = 0xFF;
|
}
|
}
|
Write_Config905();
|
}
|
*/
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
//-------------- 设置和显示单体模块的电池顺序(降序/降序) -------------------
|
void GetAndDSPMonomerOrder(void)
|
{
|
eeprom_busy_wait();
|
m_MonomerVolState.MonomerOder = eeprom_read_word(&EEPMonomerOrder);
|
if(GB_SYS_State.CurrentPage == DSPSYSSetPage)
|
{
|
DSP16x24Str(MonomerOrderText[m_MonomerVolState.MonomerOder],4, 16, 345, 176, blue, white);
|
}
|
}
|
unsigned char GetMonomerOrder(void)
|
{
|
eeprom_busy_wait();
|
m_MonomerVolState.MonomerOder = eeprom_read_word(&EEPMonomerOrder);
|
return m_MonomerVolState.MonomerOder;
|
}
|
void SetMonomerOrder(void)
|
{
|
eeprom_busy_wait();
|
m_MonomerVolState.MonomerOder = eeprom_read_word(&EEPMonomerOrder);
|
if(m_MonomerVolState.MonomerOder == 0)
|
{
|
m_MonomerVolState.MonomerOder = 1;
|
}
|
else m_MonomerVolState.MonomerOder = 0;
|
|
eeprom_busy_wait();
|
eeprom_write_word(&EEPMonomerOrder,m_MonomerVolState.MonomerOder);
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
/*
|
//----------------- 设置和显示无线单体模块的起始地址 -----------------------
|
void GetAndDSPModuleStartIndex(void)
|
{
|
if(GB_SYS_State.CurrentPage == DSPSYSSetPage)
|
{
|
PrintValue(2, 0, m_MonomerVolState.ModuleStartIndex, "", 16, 328, 272, blue, yellow);
|
}
|
}
|
*/
|
unsigned char GetModuleStartindex(void)
|
{
|
return m_MonomerVolState.ModuleStartIndex;
|
}
|
/*
|
void SetModuleStartindex(const unsigned char settype)
|
{
|
if(settype == 0)
|
{
|
if(m_MonomerVolState.ModuleStartIndex++ >= 250)
|
{
|
m_MonomerVolState.ModuleStartIndex = 0;
|
}
|
}
|
else
|
{
|
if(m_MonomerVolState.ModuleStartIndex-- <= 0)
|
{
|
m_MonomerVolState.ModuleStartIndex = 250;
|
}
|
}
|
}*/
|
//
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
//-------------- 采集最后一个单体模块(解决不是4的倍数问题) -----------------
|
void GetLastModuleVol(const unsigned int battsum, const unsigned char order,
|
volatile FBO_Data *FBOdata, const unsigned int *vol)
|
{
|
if(order == 0)
|
{
|
switch(m_MonomerVolState.EachGroupBattSum % 4)
|
{
|
case 0: FBOdata->SingleVol[battsum-4] = vol[0];
|
FBOdata->SingleVol[battsum-3] = vol[1];
|
FBOdata->SingleVol[battsum-2] = vol[2];
|
FBOdata->SingleVol[battsum-1] = vol[3];
|
break;
|
case 1: FBOdata->SingleVol[battsum-1] = vol[3];
|
break;
|
case 2: FBOdata->SingleVol[battsum-2] = vol[2];
|
FBOdata->SingleVol[battsum-1] = vol[3];
|
break;
|
case 3: FBOdata->SingleVol[battsum-3] = vol[1];
|
FBOdata->SingleVol[battsum-2] = vol[2];
|
FBOdata->SingleVol[battsum-1] = vol[3];
|
break;
|
}
|
}
|
else
|
{
|
switch(m_MonomerVolState.EachGroupBattSum % 4)
|
{
|
case 0: FBOdata->SingleVol[battsum-4] = vol[3];
|
FBOdata->SingleVol[battsum-3] = vol[2];
|
FBOdata->SingleVol[battsum-2] = vol[1];
|
FBOdata->SingleVol[battsum-1] = vol[0];
|
break;
|
case 1: FBOdata->SingleVol[battsum-1] = vol[3];
|
break;
|
case 2: FBOdata->SingleVol[battsum-2] = vol[3];
|
FBOdata->SingleVol[battsum-1] = vol[2];
|
break;
|
case 3: FBOdata->SingleVol[battsum-3] = vol[3];
|
FBOdata->SingleVol[battsum-2] = vol[2];
|
FBOdata->SingleVol[battsum-1] = vol[1];
|
break;
|
}
|
}
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
void GetEachBattGroupCurrent(volatile FBO_Data *FBOdata)
|
{
|
static unsigned char Module_Error[5] = {0};
|
static unsigned char getdatarate = 0;
|
static unsigned char targetaddr = 0;
|
unsigned int SumSubCurrent = 0;
|
unsigned char n = 0;
|
unsigned char TX_ADDR[4] = {0xAB,0xCD,0xEE,0x00};//slave addr
|
|
//--------------------- 全部不接无线电流钳的时候 -----------------------
|
if((GB_SYS_State.WorkState!=Stopped) && (m_MonomerVolState.ClampType==ClampTypeNull)
|
&& (Module_Error[0]>=10) && (Module_Error[1]>=10))
|
{
|
for(n=0; n<FBOdata->BattGroup; n++)
|
{
|
FBOdata->SubCurrent[n] = FBOdata->SumCurrent/FBOdata->BattGroup;
|
}
|
m_MonomerVolState.ClampDropIndex = 0;
|
return;
|
}
|
|
getdatarate++;
|
if(getdatarate%50 != 0)
|
{
|
return;
|
}
|
getdatarate = 0;
|
|
for(targetaddr=0; targetaddr<FBOdata->BattGroup+1; targetaddr++)
|
{
|
if((m_MonomerVolState.ClampType==ClampTypeWireless)&&(targetaddr==0))
|
{
|
continue;
|
}
|
|
//--------------------- 接收无线电流钳数据 --------------------
|
TX_ADDR[3] = targetaddr;
|
m_RFCurTX.CRC = CalCRC16(&m_RFCurTX, sizeof(RFData)-2);
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
/////*SetTxMode(); // Set Tx Mode*/////
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
TxPacket(TX_ADDR, &m_RFCurTX); // Transmit Tx buffer data
|
|
SetRxMode();
|
_delay_ms(20);
|
if(DR) // If recive data ready...
|
{
|
unsigned int crc;
|
RxPacket(&m_RFCurRX); // ... recive data
|
|
//---------------- 数据的CRC校验和从机的地址核对 -------------------
|
crc = CalCRC16(&m_RFCurRX, 14);
|
if((crc!=m_RFCurRX.CRC)||((m_RFCurRX.Addr[2])!=TX_ADDR[2])||((m_RFCurRX.Addr[3])!=TX_ADDR[3]))
|
{
|
if(Module_Error[targetaddr] < 10)
|
Module_Error[targetaddr]++;
|
}
|
else
|
{
|
Module_Error[targetaddr] = 0;
|
if(targetaddr == 0)
|
{
|
m_MonomerVolState.ClampType = ClampType7100;
|
for(n=0; n<4; n++)
|
{
|
FBOdata->SubCurrent[n] = m_RFCurRX.VolData[n];
|
if(FBOdata->SubCurrent[n] > 3000)
|
FBOdata->SubCurrent[n] = 3000;
|
else if(FBOdata->SubCurrent[n] < 10)
|
FBOdata->SubCurrent[n] = 0;
|
}
|
}
|
else
|
{
|
m_MonomerVolState.ClampType = ClampTypeWireless;
|
FBOdata->SubCurrent[targetaddr-1] = m_RFCurRX.VolData[0];
|
if(FBOdata->SubCurrent[targetaddr-1] > 3000)
|
FBOdata->SubCurrent[targetaddr-1] = 3000;
|
else if(FBOdata->SubCurrent[targetaddr-1] < 10)
|
FBOdata->SubCurrent[targetaddr-1] = 0;
|
}
|
}
|
}
|
else
|
{
|
if(Module_Error[targetaddr] < 10)
|
Module_Error[targetaddr]++;
|
}
|
|
if(Module_Error[targetaddr] >= 10)
|
{
|
if(targetaddr == 0)
|
{
|
for(n=0; n<4; n++)
|
{
|
FBOdata->SubCurrent[n] = 0;
|
}
|
}
|
else
|
{
|
FBOdata->SubCurrent[targetaddr-1] = 0;
|
}
|
}
|
|
if(m_MonomerVolState.ClampType == ClampType7100)
|
{
|
break;
|
}
|
_delay_ms(20);
|
}
|
|
for(n=0; n<FBOdata->BattGroup; n++)
|
{
|
SumSubCurrent += FBOdata->SubCurrent[n];
|
}
|
SetSumSubCurrent(SumSubCurrent);
|
|
//---------------------- 接7100但7100损坏的情况 ------------------------
|
if((m_MonomerVolState.ClampType==ClampType7100) && (Module_Error[0]>=10))
|
{
|
for(n=0; n<FBOdata->BattGroup; n++)
|
{
|
FBOdata->SubCurrent[n] = FBOdata->SumCurrent/FBOdata->BattGroup;
|
}
|
}
|
|
//--------------- 使用独立的无线电流钳 ---------------------------------
|
if((m_MonomerVolState.ClampType==ClampTypeWireless) && (SumSubCurrent<(FBOdata->SumCurrent)))
|
{
|
unsigned char count = 0;
|
//----------- 检查是否有异常的电流钳 -------------
|
for(n=0; n<FBOdata->BattGroup; n++)
|
{
|
if(Module_Error[n+1] >= 10)
|
{
|
count++;
|
}
|
}
|
if(count > 0)
|
{
|
for(n=0; n<FBOdata->BattGroup; n++)
|
{
|
//------------ 找出没连接或损坏的那个电流钳 ----------------
|
if(Module_Error[n+1] >= 10)
|
FBOdata->SubCurrent[n] = (FBOdata->SumCurrent-SumSubCurrent)/count;
|
}
|
}
|
}
|
|
//-------------- 在放电或充电中检测无线电流钳是否异常 ------------------
|
if((m_MonomerVolState.ClampType!=ClampTypeNull)&&((GB_SYS_State.WorkState==Discharging)||(GB_SYS_State.WorkState==Charging)))
|
{
|
m_MonomerVolState.ClampDropIndex = 0;
|
if(m_MonomerVolState.ClampType == ClampType7100)
|
{
|
if(Module_Error[0] >= 10)
|
{
|
m_MonomerVolState.ClampDropIndex = 1;
|
}
|
}
|
else
|
{
|
for(n=0; n<FBOdata->BattGroup; n++)
|
{
|
if(Module_Error[n+1] >= 10)
|
{
|
m_MonomerVolState.ClampDropIndex = n+2;
|
break;
|
}
|
}
|
}
|
//---------------- 检测无线电流钳的异常状态是否改变 ------------------
|
if(m_MonomerVolState.ClampDropCount != m_MonomerVolState.ClampDropIndex)
|
{
|
m_MonomerVolState.ClampDropCount = m_MonomerVolState.ClampDropIndex;
|
//------------- XX号无线电流钳异常 ----------------
|
if(m_MonomerVolState.ClampDropIndex > 0)
|
{
|
StartAlarmBeep(MonomerModleDrop);
|
}
|
else
|
{
|
StopAlarmBeep();
|
}
|
|
//--------- 如果当前处于是查看单体页面,则退出单体页面 --------------
|
if(GB_SYS_State.CurrentPage == DSPSingleVolData)
|
{
|
QuitSingleVolPage();
|
}
|
|
if(GB_SYS_State.CurrentPage == DSPWorkingPage)
|
{
|
UpdateWPStateText(GetWPStateIndex());
|
}
|
else if(GB_SYS_State.CurrentPage == DSPChargePage)
|
{
|
UpdateCPStateText(GetCPStateIndex());
|
}
|
}
|
}
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
unsigned char ExchangeMonomerData(const unsigned char *TX_ADDR, void *DataTX, void *DataRX)
|
{
|
unsigned char error = 0;
|
//-------------- 通过RS485有线模块接收单体数据 -------------------
|
if(MonomerModuleType != MonomeWireless)
|
{
|
error = GetRS485Data(TX_ADDR, DataTX, DataRX);
|
}
|
//---------------- 通过无线模块接收单体数据 ----------------------
|
if(MonomerModuleType != MonomeLine)
|
{
|
error = GetNRF905Data(TX_ADDR, DataTX, DataRX);
|
}
|
|
return error;
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
//------------------- 采集单体电压(一次一个模块) ---------------------------
|
void Get_Vol_Datas(volatile FBO_Data *FBOdata, volatile SYS_State *SYSstate, const unsigned int MStopV)
|
{
|
static unsigned char Module_Error[125] = {0};
|
static unsigned int Module_Addr = 0;
|
static unsigned int startindex = 0;
|
static unsigned char getdatarate = 1;
|
unsigned char TX_ADDR[4] = {0xAB,0xCD,0x00,0x01};//slave addr
|
unsigned long SumVol[4] = {0};//由单体来统计总电压
|
unsigned char error = 0;
|
unsigned char nn = 0;
|
|
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
//----------- 均衡单体采集速率 --------------
|
getdatarate++;
|
if(getdatarate%(250/m_MonomerVolState.ModuleSum+5) != 0)
|
{
|
//----------- 采集无线钳口数据 ----------
|
GetEachBattGroupCurrent(FBOdata);
|
return;
|
}
|
getdatarate = 0;//此语句切勿删除
|
//-------------------------------------------
|
|
//----------- 无线模块被禁用 ----------------
|
if((m_MonomerVolState.MonomerEnabled==0) || (FBOdata->BattSum==0))
|
{
|
return;
|
}
|
//-------------------------------------------
|
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
TX_ADDR[2] = (Module_Addr+1) / 256;
|
TX_ADDR[3] = (Module_Addr+1) % 256;
|
|
error = ExchangeMonomerData(TX_ADDR, &m_RFDataTX, &m_RFDataRX);
|
|
//--------------------- 单体电压值范围检测 ---------------------
|
if(error == 0)
|
{
|
for(nn=0; nn<4; nn++)
|
{
|
if((m_RFDataRX.VolData[nn]<100) || (m_RFDataRX.VolData[nn]>16000))
|
m_RFDataRX.VolData[nn] = 0;
|
}
|
|
//----------------------- 提取正确的数据 -----------------------
|
Module_Error[Module_Addr] = 0;
|
|
if(m_MonomerVolState.MonomerOder == 0)//模块电池降序
|
{
|
if((Module_Addr%m_MonomerVolState.EachGroupModule) == (m_MonomerVolState.EachGroupModule-1))
|
{
|
GetLastModuleVol(m_MonomerVolState.EachGroupBattSum*(Module_Addr/m_MonomerVolState.EachGroupModule + 1),
|
m_MonomerVolState.MonomerOder, FBOdata, m_RFDataRX.VolData);
|
}
|
else
|
{
|
for(nn=0; nn<4; nn++)
|
{
|
FBOdata->SingleVol[startindex+nn] = m_RFDataRX.VolData[nn];
|
}
|
}
|
}
|
else //模块电池升序
|
{
|
if((Module_Addr%m_MonomerVolState.EachGroupModule) == (m_MonomerVolState.EachGroupModule-1))
|
{
|
GetLastModuleVol(m_MonomerVolState.EachGroupBattSum*(Module_Addr/m_MonomerVolState.EachGroupModule + 1),
|
m_MonomerVolState.MonomerOder, FBOdata, m_RFDataRX.VolData);
|
}
|
else
|
{
|
for(nn=0; nn<4; nn++)
|
{
|
FBOdata->SingleVol[startindex+nn] = m_RFDataRX.VolData[3-nn];
|
}
|
}
|
}
|
}
|
|
if(error != 0)
|
{
|
if(Module_Error[Module_Addr] < 10)
|
Module_Error[Module_Addr]++;
|
if(Module_Error[Module_Addr] >= 10) // 模块错误计数超过10次
|
{
|
if(((Module_Addr%m_MonomerVolState.EachGroupModule)==(m_MonomerVolState.EachGroupModule-1))
|
&& (m_MonomerVolState.EachGroupBattSum%4 > 0))
|
{
|
for(nn=0; nn<m_MonomerVolState.EachGroupBattSum%4; nn++) //该模块对应的单体电压全部置零
|
{
|
FBOdata->SingleVol[startindex+nn] = 0;
|
}
|
}
|
else
|
{
|
for(nn=0; nn<4; nn++) //该模块对应的单体电压全部置零
|
{
|
FBOdata->SingleVol[startindex+nn] = 0;
|
}
|
}
|
}
|
}
|
else
|
{
|
unsigned int m_index;
|
for(unsigned char m=0; m<FBOdata->BattGroup; m++)
|
{
|
if(m_MonomerVolState.EachGroupBattSum%4 == 0)
|
m_index = m_MonomerVolState.EachGroupBattSum*m;
|
else
|
m_index = (m_MonomerVolState.EachGroupBattSum/4+1)*4*m;
|
|
if(m_MonomerVolState.MonomerMinVol[m] < 100)
|
Module_Error[(m_MonomerVolState.MonomerMinIndex[m]+m_index)/4] = 10;
|
}
|
}
|
|
//------------------ 在放电或充电中检测单体模块连接线脱落 ----------------------
|
if((GB_SYS_State.WorkState==Discharging) || (GB_SYS_State.WorkState==Charging))
|
{
|
m_MonomerVolState.ModuleDropIndex = 0;
|
for(nn=0; nn<m_MonomerVolState.ModuleSum; nn++)
|
{
|
if(Module_Error[nn] >= 10)
|
{
|
m_MonomerVolState.ModuleDropIndex = nn+1;
|
break;
|
}
|
}
|
}
|
//---------------- 检测无线单体模块的异常状态是否改变 ------------------
|
if(((GB_SYS_State.WorkState==Discharging)||(GB_SYS_State.WorkState==Charging))
|
&&(m_MonomerVolState.ModuleDropIndex != m_MonomerVolState.ModuleDropCount))
|
{
|
m_MonomerVolState.ModuleDropCount = m_MonomerVolState.ModuleDropIndex;
|
//------------- XX号模块接线开路 ----------------
|
if(m_MonomerVolState.ModuleDropIndex > 0)
|
{
|
StartAlarmBeep(MonomerModleDrop);
|
}
|
else
|
{
|
StopAlarmBeep();
|
}
|
|
//--------- 如果当前处于是查看单体页面,则退出单体页面 --------------
|
if(GB_SYS_State.CurrentPage == DSPSingleVolData)
|
{
|
QuitSingleVolPage();
|
}
|
|
if(GB_SYS_State.CurrentPage == DSPWorkingPage)
|
{
|
UpdateWPStateText(GetWPStateIndex());
|
}
|
else if(GB_SYS_State.CurrentPage == DSPChargePage)
|
{
|
UpdateCPStateText(GetCPStateIndex());
|
}
|
}
|
|
//---------------- 切换到下一个要采集的模块 ----------------------------
|
if(((Module_Addr%m_MonomerVolState.EachGroupModule)==(m_MonomerVolState.EachGroupModule-1))
|
&& (m_MonomerVolState.EachGroupBattSum%4 > 0))
|
{
|
startindex += m_MonomerVolState.EachGroupBattSum % 4;
|
}
|
else
|
{
|
startindex += 4;
|
}
|
Module_Addr++;
|
if(Module_Addr > m_MonomerVolState.ModuleSum-1)
|
{
|
Module_Addr = 0;
|
startindex = 0;
|
}
|
|
for(unsigned char m=0; m<FBOdata->BattGroup; m++)
|
{
|
m_MonomerVolState.MonomerMaxVol[m] = 0;
|
m_MonomerVolState.MonomerMinVol[m] = 20000;
|
SumVol[m] = 0;
|
}
|
|
m_MonomerVolState.StopMVolCount = 0;
|
//------------------- 获取最大最小单体,总电压 --------------------------
|
for(int G=0; G<FBOdata->BattGroup; G++)
|
{
|
unsigned int tmpvol[4];
|
for(int m=0; m<m_MonomerVolState.EachGroupBattSum; m++)
|
{
|
tmpvol[G] = FBOdata->SingleVol[m + m_MonomerVolState.EachGroupBattSum*G];
|
if((tmpvol[G]<=MStopV) && (tmpvol[G]>=100))
|
{
|
MonomerLowTag[m/16] |= (1<<(m%16));
|
}
|
else if(tmpvol[G] > MStopV)
|
{
|
MonomerLowTag[m/16] &= ~(1<<(m%16));
|
}
|
|
if(MonomerLowTag[m/16] & (1<<(m%16)))
|
{
|
m_MonomerVolState.StopMVolCount++;
|
}
|
|
if(m_MonomerVolState.MonomerMinVol[G] > tmpvol[G])
|
{
|
m_MonomerVolState.MonomerMinVol[G] = tmpvol[G];
|
m_MonomerVolState.MonomerMinIndex[G] = m;
|
}
|
if(m_MonomerVolState.MonomerMaxVol[G] < tmpvol[G])
|
{
|
m_MonomerVolState.MonomerMaxVol[G] = tmpvol[G];
|
m_MonomerVolState.MonomerMaxIndex[G] = m;
|
}
|
SumVol[G] += tmpvol[G];//总电压累加
|
}
|
}
|
|
FBOdata->SumVoltage = SumVol[0]/100;
|
for(unsigned char G=1; G<FBOdata->BattGroup; G++)
|
{
|
if(FBOdata->SumVoltage < SumVol[G]/100)
|
FBOdata->SumVoltage = SumVol[G]/100;
|
}
|
|
//------------- 单体累加的总电压异常就采用放电端的总电压 ---------------
|
if((FBOdata->SumVoltage < GetInnerSumVol())
|
&&(GetInnerSumVol()-FBOdata->SumVoltage > 5))
|
{
|
FBOdata->SumVoltage = GetInnerSumVol();
|
}
|
}
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|
//--------------------------------------------------------------------------------------------------
|