Compare commits

..

53 Commits

Author SHA1 Message Date
Carl 833cfa6562 bcu偶尔会丢失订阅的主题,导致远程配置失效,增加了订阅主题的定时检查 2025-06-19 09:52:47 +08:00
ahu_gq cf6d3bc00f 迁移数据 2025-06-09 18:08:15 +08:00
ahu_gq 6985aded2e 提交内存分配 2025-06-09 17:59:28 +08:00
Carl ccd6ea6432 优化远程配置驱动--目前支持全部读取和单个写入,上个版本问题未解决 2025-06-06 11:11:58 +08:00
Carl 857a4b434d 测试远程读配置与写配置驱动时,如果远程复位,则上位机复位后,程序就异常了 2025-06-05 17:38:55 +08:00
Carl 1def56eb47 解决了配置下发后程序崩溃的问题 2025-06-04 17:01:11 +08:00
Carl b7c3ddf4e1 读取配置驱动以及响应基本完成 2025-06-04 15:54:41 +08:00
Carl 34f02a66d9 配置下发的驱动基本完成,配置下发成功后可以读取到ok 2025-06-04 13:18:56 +08:00
Carl a2b75cf76c 配置下发主题分类 2025-05-29 18:13:04 +08:00
Carl 1dc6f097e0 ”实现了bluesun/bms/control/sn的主题配置“ 2025-05-29 15:52:09 +08:00
Carl 5aff48e4b0 add dma delay time 2025-05-26 16:38:24 +08:00
Carl 10aa1a8c24 dma--bug 2025-05-26 16:26:51 +08:00
Carl 553cd2414c 将485地址与can设备地址同一起来 2025-05-22 09:21:45 +08:00
Carl 080f45620e fix some bugs--解决了同一批数据,时间戳不一样的问题 2025-05-19 14:13:04 +08:00
Carl 3c6b5eec89 mqtt上传数据的方式使用DMA,避免占用cpu 2025-05-19 11:40:39 +08:00
Carl dcb4f440df 增加蓝牙消失检测,检测蓝牙消失后,重新初始化蓝牙 2025-05-19 08:44:03 +08:00
Carl 7a7bd6e768 与张工重新核对了一遍mqtt上传的数据--第一版 2025-05-17 08:27:05 +08:00
Carl 0efd486cbe fix some bugs--extremeFault 2025-05-16 11:24:05 +08:00
Carl d697ad7e5f 解决了mqtt上传信息中,总压告警缺失的问题,并核对了一遍告警上传的部分 2025-05-16 10:26:41 +08:00
Carl 05a9411a6c 加入了是否已经连接mqtt服务器的检测,只有当连接失败的时候,才会重连mqtt服务器,减少tcp请求,节省服务器资源 2025-05-16 10:24:56 +08:00
Carl b6552b8b21 mqtt上传信息中增加了预充,总正,总负继电器的状态 2025-05-15 10:35:26 +08:00
Carl 2635b93a5a 高压堆叠融合wifi功能,成功,第一版 2025-05-13 16:37:29 +08:00
guzz 5dd97a6761 adjust some params saving when power shunt down 2025-04-27 17:49:11 +08:00
guzz e62cd7941a 高压堆叠程序,除wifi外基本OK 2025-04-27 16:06:36 +08:00
Carl ea635ee7b6 高压堆叠产品单独程序,支持最多8个pack包 2025-04-26 14:57:50 +08:00
guzz 1be9fc25f7 fix soc saving when power shut down--still the function of adapt bmu number and wifi left 2025-04-25 08:20:46 +08:00
guzz 6d2a8c4179 fix soc calc figure 2025-04-23 16:50:30 +08:00
guzz 9f84c0a1c5 fix shunt problem when current is minus 2025-04-23 14:40:51 +08:00
guzz 7e580ed58c fix shunt 2025-04-22 18:20:14 +08:00
Carl da78eb8f86 system test1 -- fix hv sample 2025-04-21 10:20:19 +08:00
Carl 594b7b90c8 merge version 2025-04-15 19:21:49 +08:00
Carl 5280b76d65 BCU function ok --new PCB 2025-04-09 15:17:27 +08:00
ahu_gq 83b4133c68 Merge branch 'wk' of http://47.120.14.45:3000/Bluesun/BCU into wk 2025-03-02 15:50:49 +08:00
guzz c2cceee9df bcu function is basiclly ok 2025-03-01 16:55:37 +08:00
guzz da3aca4948 bcu功能基本ok 2025-03-01 16:53:28 +08:00
guzz 6b4089ed1e bcu功能基本ok 2025-03-01 16:33:40 +08:00
guzz a6ddf7f43d 注释了反馈异常中dly加base_time的条件 2025-02-25 15:48:49 +08:00
guzz 25aaac1080 4000modbus 2025-02-25 14:58:14 +08:00
guzz 091a70874e 4000多地址增加连续可写的功能 2025-02-25 10:24:49 +08:00
guzz ed4c22e628 除了分流器部分,soctmp计算少除100,电量计算多除100 2025-02-20 11:17:24 +08:00
guzz b4ce65176d 高压采集问题解决 2025-02-15 19:57:30 +08:00
guzz f02582475f 提交测试 2025-02-15 08:21:45 +08:00
guzz de4f10aaf2 单体温感排线错误故障 2025-02-12 15:02:26 +08:00
guzz 0375e81dd6 更改dido枚举 2025-02-10 16:45:06 +08:00
guzz 75158d3bf3 Merge branch 'gary' into wk 2025-02-10 16:15:54 +08:00
guzz 61a91657bd 1 2025-02-10 16:15:29 +08:00
ahu_gq 7624dbe183 解决ADS1818官方示例错误 2025-02-09 17:04:22 +08:00
ahu_gq 8470d2c41a Merge branch 'master' into gary 2025-02-09 16:34:37 +08:00
ahu_gq a3d5cc58b5 添加忽略 2025-02-09 16:30:51 +08:00
ahu_gq de38f54c76 添加忽略 2025-02-09 16:29:24 +08:00
guzz 9920f30203 提交测试 2025-02-09 10:53:08 +08:00
ahu_gq 1f0cef7f45 Merge branch 'master' into gary 2025-02-09 10:31:55 +08:00
ahu_gq 803b34c34e Merge branch 'master' into gary 2025-02-06 15:26:32 +08:00
68 changed files with 21176 additions and 429210 deletions

3
.gitignore vendored
View File

@ -5,6 +5,8 @@
*.rpt
*.plg
*.uvgui.*
*.uvprojx
*.uv*
*.crf
*.map
*.hex
@ -12,6 +14,7 @@
*.o
*.s19
*.dbgconf
*.uv*
# 忽略编译器输出目录(如果您有自定义的输出目录)
Objects/
Listings/

View File

@ -17,7 +17,6 @@
Objects/
Listings/
Exe/
prj/
# 忽略用户设置文件,通常包含调试和布局等信息
*.uvoptx

View File

@ -12,7 +12,7 @@
#define MCU_MAX_AD_VALUE 4095
#define ADC_SAMPLE_CNT 250
uint16_t adc_dma_buf[kAdcDataEnd * ADC_SAMPLE_CNT];
uint16_t adc_dma_buf[kAdcDataEnd * ADC_SAMPLE_CNT] __attribute__((section(".ccmram")));
uint32_t adc_value[kAdcDataEnd];
const AdcArray adc_array[kAdcDataEnd] =
{
@ -47,23 +47,23 @@ void bms_poll_adc(uint32_t base_time)
tmp = kit_get_dma_avg_filter_min_max(adc_dma_buf, kAdcDataEnd, i, ADC_SAMPLE_CNT);
switch (i)
{
case kAdcData_5vVolt:
adc_value[i] = 0; // 返回电压0.1V/bit
break;
case kAdcData_Temp1:
case kAdcData_Temp2:
case kAdcData_Temp3:
case kAdcData_Temp4:
tmp = tmp * 10000 / (MCU_MAX_AD_VALUE - tmp); // 返回阻值1Ω/bit
adc_value[i] = bms_get_linear_temp(tmp, kNtcType_CWFH708_H713);
bms_set_en_temp((EnTemp)(i - kAdcData_Temp1), adc_value[i]);
break;
case kAdcData_Hall1:
case kAdcData_Hall2:
// 扩大100倍
//adc_value[i] = tmp * (4 * 100 / 3);
adc_value[i] = tmp * 3 / 4;//先获取电压值
break;
case kAdcData_5vVolt:
adc_value[i] = 0; // 返回电压0.1V/bit
break;
case kAdcData_Temp1:
case kAdcData_Temp2:
case kAdcData_Temp3:
case kAdcData_Temp4:
tmp = tmp * 10000 / (MCU_MAX_AD_VALUE - tmp); // 返回阻值1Ω/bit
adc_value[i] = bms_get_linear_temp(tmp, kNtcType_CWFH708_H713);
bms_set_en_temp((EnTemp)(i - kAdcData_Temp1), adc_value[i]);
break;
case kAdcData_Hall1:
case kAdcData_Hall2:
// 扩大100倍
//adc_value[i] = tmp * (4 * 100 / 3);
adc_value[i] = tmp * 3 / 4;//先获取电压值
break;
}
}
}

View File

@ -7,7 +7,7 @@
******************************************************************************/
#include "bmu_adbms1818.h"
BmuItem bmu_data;
__attribute__((section(".ccmram"))) BmuItem bmu_data;
static uint8_t adapt_falg = 0;
//adapt ic number
@ -31,7 +31,6 @@ void bmu_adapt_ic_num(void)
bmu_data.total_ic_num = bmu_data.total_ic_adapt_num;
}
//
void bmu_adapt_volt_temp(void)
{
@ -83,7 +82,6 @@ void bmu_adapt_volt_temp(void)
bmu_data.bmu_cell_num = bmu_data.total_cell_num / bmu_data.bmu_ic_num;
bmu_data.bmu_temp_num = bmu_data.total_temp_num / bmu_data.bmu_ic_num;
}
void bmu_init_isoSpi(void)
@ -102,8 +100,8 @@ void bmu_config_init(void)
drv_gpio_set_pin_status(kGpioType_SP1_Cs_En2, kGpioStatus_Low);
//drv_gpio_set_pin_status(kGpioType_SP1_Cs_En1, kGpioStatus_Low);
//bmu_data.bmu_num = get_eeprom_data(kEep_DevAddr_SlaverNum, kEepromDataType_Low);
bmu_data.bmu_num = 2;
bmu_data.bmu_num = get_eeprom_data(kEep_DevAddr_SlaverNum, kEepromDataType_Low);
//bmu_data.bmu_num = 1;
if (bmu_data.bmu_num > BMU_MAX_NUM || bmu_data.bmu_num == 0)
{
bmu_data.bmu_num = BMU_MAX_NUM;
@ -112,11 +110,11 @@ void bmu_config_init(void)
bmu_data.bmu_ic_num = get_eeprom_data(kEep_AfeNum_CellNum, kEepromDataType_High);
bmu_data.total_ic_num = bmu_data.bmu_num * bmu_data.bmu_ic_num;
bmu_data.ic = bsp_adbms1818_global();
//bmu_data.total_cell_num = get_eeprom_data(kEep_CellNum, kEepromDataType_Full);
//bmu_data.total_temp_num = get_eeprom_data(kEep_TempNum, kEepromDataType_Full);
bmu_data.total_cell_num = get_eeprom_data(kEep_CellNum, kEepromDataType_Full);
bmu_data.total_temp_num = get_eeprom_data(kEep_TempNum, kEepromDataType_Full);
bmu_data.total_cell_num = 32;
bmu_data.total_temp_num = 18;
//bmu_data.total_cell_num = 16;
//bmu_data.total_temp_num = 8;
//set num from hmi =>adapt num for furture
cell_num = bmu_data.total_cell_num / bmu_data.bmu_num;
@ -240,14 +238,21 @@ void bmu_vlot_breakline_check()
}
static int tempJudge_cnt[26][9] = {0};
//static int tempCellErr_cnt = 0;
//@wkun the here can add temp line break or connect
void bmu_temp_breakline_check()
void bmu_temp_breakline_check(int value, int bmuIdx, int tempIdx)
{
//核心逻辑是通过每个bmu中的温度是否大于60000来确定温感排线是否有问题通过for循环然后将故障塞入kFaultCode_TempCable对应的故障中
//bms_get_bmu_fault_bit(kBmuFaultBit_TempCable)将这个接口中的数据如果有则置1否则为0
if (value > 6000)
{
tempJudge_cnt[bmuIdx][tempIdx]++;
}
if(tempJudge_cnt[bmuIdx][tempIdx] > 1)
{
//bms_set_bmu_fault_bit(kBmuFaultBit_TempCable, 1);
}
}
@ -269,11 +274,11 @@ static void bmu_statistic_cell_volt(uint16_t bmuIdx)
{
value = bmu_data.bmu_unit[bmuIdx].cell_volt_buf[i];
//实时计算防止个别电芯真放空为0或者充满
if(value > 1000 && value < 4000)
{
sum_value += value;
valid_num++;
//实时计算防止个别电芯真放空为0或者充满
if(value > 1000 && value < 4000)
{
sum_value += value;
valid_num++;
}
if(max_value < value)
{
@ -288,14 +293,14 @@ static void bmu_statistic_cell_volt(uint16_t bmuIdx)
}
}
bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_TotalVolt] = sum_value;
bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_TotalVolt] = sum_value;
if(valid_num > 0)
{
sum_value /= valid_num;
}
bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_AvgVolt] = sum_value;
bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_AvgVolt] = sum_value;
bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_MaxVolt] = max_value;
bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_MaxVoltIdx] = max_idx;
bmu_data.bmu_unit[bmuIdx].statistic_data[kBmuStatistic_MinVolt] = min_value;
@ -361,7 +366,7 @@ static void bmu_statistic_cell_temp(uint16_t bmuIdx)
void bmu_data_handler(uint32_t base_time)
{
uint8_t bmuIdx = 0,cellIdx = 0,_cellIdx = 0,_bmuIdx = 0,_ntcIdx = 0;
uint16_t current = 0,load = 0;
uint16_t current = 0,load = 0, tempJudge = 0;
//calc cell volt
for(bmuIdx = 0;bmuIdx < bmu_data.total_ic_num;bmuIdx++)
{
@ -388,7 +393,9 @@ void bmu_data_handler(uint32_t base_time)
current = 1;
}
load = (bmu_data.ic[bmuIdx].aux.a_codes[_ntcIdx] / 10) * 1000 / current; //修订索引错误
bmu_data.bmu_unit[bmuIdx].cell_temp_buf[cellIdx] = (bms_get_linear_temp(load, kNtcType_CWFH708_H713) - 500) / 10;
tempJudge = (bms_get_linear_temp(load, kNtcType_CWFH708_H713) - 500) / 10;
bmu_data.bmu_unit[bmuIdx].cell_temp_buf[cellIdx] = tempJudge;
bmu_temp_breakline_check(tempJudge, bmuIdx, _ntcIdx);
}
//统计温度
bmu_statistic_cell_temp(bmuIdx);
@ -396,7 +403,6 @@ void bmu_data_handler(uint32_t base_time)
//alarm monitor
//bmu_comm_offline_check(base_time);
bmu_vlot_breakline_check();
bmu_temp_breakline_check();
}
@ -418,6 +424,8 @@ void bms_bmu_init()
}
void bms_poll_bmu(uint32_t base_time)
{
//Automatic Recognition
@ -435,10 +443,15 @@ void bms_poll_bmu(uint32_t base_time)
run_command(6,bmu_data.bmu_num*bmu_data.bmu_ic_num);
bmu_data_handler(base_time);
//温感检测是否脱落加上了防抖需要两次大于6000才设置温感排线错误温感排线错误显示的有点慢
//温感的值最开始全是大于6000的第二次才是采集值
//memset(tempJudge_cnt, 0, sizeof(tempJudge_cnt));
//2-5 @wangk add this line bcu statistic data is show
bms_poll_statistic(0);
//2-6 @wangk
bms_poll_run_status(base_time);
// bms_poll_statistic(0);
// //2-6 @wangk
// bms_poll_run_status(base_time);
// //2-10 @wangk
// task_dido_ctrl_handle(1000);
}

View File

@ -19,6 +19,10 @@ extern "C" {
//2-6
#include "statistic_manager.h"
#include "run_status.h"
#include "logic_ctrl.h"
#include "bmu_manager.h"
#include "string.h"
#include "stdio.h"
typedef struct
{

View File

@ -58,6 +58,22 @@ uint8_t bms_get_bmu_num(void)
return bmu_data.bmu_num;
}
void bms_set_bmu_num(uint8_t number)
{
bmu_data.bmu_num = number;
bmu_data.total_ic_num = number;
}
void bms_set_bmu_volt_num(uint8_t number)
{
bmu_data.total_cell_num = number * 16;
}
void bms_set_bmu_temp_num(uint8_t number)
{
bmu_data.total_temp_num = number * 4;
}
uint8_t bms_get_bmu_online_num(void)
{
return bmu_data.bmu_online_num;

View File

@ -78,7 +78,11 @@ uint16_t bms_get_pole_temp_by_bmu(uint8_t bmu_idx, uint16_t idx);
uint16_t bms_get_balance_temp_by_bmu(uint8_t bmu_idx, uint16_t idx);
uint32_t bms_get_balance_status(uint8_t bmu_idx, uint8_t idx);
void bms_set_bmu_fault_bit(BmuFaultBit idx,uint8_t value);
void bms_set_bmu_num(uint8_t number);
void bms_set_bmu_num(uint8_t number);
void bms_set_bmu_volt_num(uint8_t number);
void bms_set_bmu_temp_num(uint8_t number);
#ifdef __cplusplus
}

View File

@ -16,14 +16,15 @@
#include "bsp_hmi.h"
#include "drv_w5500.h"
#define APP_HMI_BUF_SIZE (1024 * 4)
uint8_t hmi_buf[4][APP_HMI_BUF_SIZE] __attribute__((section (".CCM_RAM")));
/************************************************ETH接口***************************************************/
static void w5500_rcv_call(uint8_t socket, uint8_t *buf, uint16_t len);
ModbusItem w5500_modbus_tcp_array[W5500_MODBUS_NUM];
ModbusItem w5500_modbus_tcp_array[W5500_MODBUS_NUM] __attribute__((section (".ccmram")));
W5500_STATIC_INIT(w5500, kSpiDev_3, kGpioType_W5500Cs, w5500_rcv_call);
uint8_t canID_devNumber = 0;
static void eth_ctrl_rx_int(uint8_t comm_dev, bool is_en)
{
@ -271,16 +272,18 @@ typedef enum
const uint16_t uart_parity[kUartParity_End] = {0x0000, 0x0007, 0x0005};
const uint32_t uart_baudrate[kR485BaudRateEnd] = {4800, 9600, 19200, 38400, 115200};
const uint32_t can_baudrate[kCanBaudRateEnd] = {125, 250, 500, 1000};
void bms_init_comm(void)
{
uint32_t i, tmp, prop;
tmp = bms_get_tag_data(kTagData_DevAddr);
modbus_gate.is_write_check = true;
modbus_gate.write_buf = &eeprom_item.data_buf[kEep_GateDataStart];
bsp_eeprom_set_data(kEep_Inter485Parity_Baudrate,1,kEepromDataType_Low);
bsp_eeprom_set_data(kEep_Exter485_2Parity_Baudrate,1,kEepromDataType_Low);
canID_devNumber = get_eeprom_data(kEep_ExterRS485_1SlaveID_Protocol, kEepromDataType_High);
for(i = 0; i < BMS_485_CHANNEL; i++)
{
@ -292,20 +295,22 @@ void bms_init_comm(void)
prop = get_eeprom_data(kEep_Inter485Parity_Baudrate + i, kEepromDataType_High);
prop = (prop < kUartParity_End) ? uart_parity[prop] : 0;
uint32_t tmpBaud = uart_baudrate[prop];
drv_uart_init((UartDev)modbus_rtu_array[i]->comm_dev, 115200, 0 | UART_CFG_STOP_BIT_1, kGpioType_Rs485_Ch1_Tx + (i << 1), kGpioType_Rs485_Ch1_Rx + (i << 1));
drv_uart_set_interrupt((UartDev)modbus_rtu_array[i]->comm_dev, kUartInterrupt_Tx, APP_CFG_INT_PRIO_UART2_RX, uart_tx_it_call);//设置中断回调
}
uint32_t tmpIndex = get_eeprom_data(kEep_InterCanProtocol_Baudrate + i, kEepromDataType_Low);
uint32_t tmpCanBaud = can_baudrate[tmpIndex];
drv_uart_set_interrupt(INTER_UART_PORT, kUartInterrupt_Rx, APP_CFG_INT_PRIO_UART2_RX, inter_uart_rx_it_call);
drv_uart_set_interrupt(EXTER_UART1_PORT, kUartInterrupt_Rx, APP_CFG_INT_PRIO_UART2_RX, exter_uart1_rx_it_call);
drv_uart_set_interrupt(EXTER_UART2_PORT, kUartInterrupt_Rx, APP_CFG_INT_PRIO_UART2_RX, exter_uart2_rx_it_call);
drv_can_init(INTER_CAN_PORT, 250, kGpioType_Can_Ch1_Rx, kGpioType_Can_Ch1_Tx);
drv_can_init(INTER_CAN_PORT, 500, kGpioType_Can_Ch1_Rx, kGpioType_Can_Ch1_Tx);
drv_can_set_interrupt(INTER_CAN_PORT, kcan_interrupt_e_Rx, APP_CFG_INT_PRIO_CAN1_RX, inter_can_rx_it_call);
drv_can_set_interrupt(INTER_CAN_PORT, kcan_interrupt_e_Tx, APP_CFG_INT_PRIO_CAN1_TX, inter_can_tx_it_call);
drv_can_init(EXTER_CAN_PORT, 250, kGpioType_Can_Ch2_Rx, kGpioType_Can_Ch2_Tx);
drv_can_init(EXTER_CAN_PORT, 500, kGpioType_Can_Ch2_Rx, kGpioType_Can_Ch2_Tx);
drv_can_set_interrupt(EXTER_CAN_PORT, kcan_interrupt_e_Rx, APP_CFG_INT_PRIO_CAN2_RX, exter_can_rx_it_call);
drv_can_set_interrupt(EXTER_CAN_PORT, kcan_interrupt_e_Tx, APP_CFG_INT_PRIO_CAN2_TX, exter_can_tx_it_call);

View File

@ -195,7 +195,8 @@ void bms_force_crtl_do_status(uint8_t idx, DoCtrlStatus status)
if(status < kDoCtrlStatus_None)
{
do_item.tick[idx] = RELAY_CTRL_NO_DLY;
do_item.ctrl_status[idx] = (DoStatus)(status + 2);
//@wagnk2-17这里原本的status加了2取消了
do_item.ctrl_status[idx] = (DoStatus)(status);
}
else
{
@ -225,7 +226,7 @@ const GpioStatus relay_status_to_ctrl[kDoStatus_End] ={kGpioStatus_Low, kGpioSta
void bms_poll_di_do(uint32_t base_time)
{
uint32_t i;
uint32_t i,j = 0;
DoStatus rly_st;
if(do_item.bmsCircuitCtrl != NULL)
@ -247,6 +248,10 @@ void bms_poll_di_do(uint32_t base_time)
do_item.tick[i] = 0;
rly_st = do_item.ctrl_status[i];
do_item.actual_status[i] = rly_st;
if((relay_status_to_ctrl[rly_st] == kGpioStatus_Low) && (i == 1))
{
j = 1;
}
drv_gpio_set_pin_status(do_item.relay_start_io + i, relay_status_to_ctrl[rly_st]);
}
else

View File

@ -37,9 +37,9 @@ typedef enum
{
kDoType_Start = 0,
kDoType_Unused = kDoType_Start,
kDoType_Chg,
kDoType_Dis,
kDoType_PreChg, //3
kDoType_PreChg,
kDoType_Chg,
kDoType_Dis,//3
kDoType_Positive, //4
kDoType_Negative,//5
kDoType_Cool,
@ -84,6 +84,8 @@ typedef enum
kDiType_Start = 0,
kDiType_Unused= kDiType_Start,
kDiType_FireAlarm1, //消防1
kDiType_FireAlarm2,
kDiType_FireAlarm3,
kDiType_EmergStop1, //急停
kDiType_Do1Feedback,
kDiType_Do2Feedback,

View File

@ -875,10 +875,10 @@ static const EepromDataFormat data_format[kEEDataIdx_End] =
STATIC_UNCHECK_MAX_MIN, 0x0000, 0x0000, 0xFFFF, //预留10
//eeeprom
//soc
STATIC_CHECK, 0, 0, 1, //电池循环次数更新标志
STATIC_CHECK, 0, 0x0000, 0xFFFF, //电池循环次数
STATIC_CHECK, 5000, 0, 10000, //SOC
STATIC_CHECK, 5000, 0, 10000, //SOE
DAYNMIC_CHECK, 0, 0, 1, //电池循环次数更新标志
DAYNMIC_CHECK, 0, 0x0000, 0xFFFF, //电池循环次数
DAYNMIC_CHECK, 5000, 0, 10000, //SOC
DAYNMIC_CHECK, 5000, 0, 10000, //SOE
DAYNMIC_UNCHECK_MAX_MIN, 0x0000, 0x0000, 0xFFFF, //日充放电累计时间
DAYNMIC_UNCHECK_MAX_MIN, 0x0000, 0x0000, 0xFFFF,
@ -951,17 +951,19 @@ void bms_init_eeprom(void)
void bms_pwr_off_save(void)
{
uint32_t i, cnt = 0, tmp_32u;
EepromPoData data[30];
tmp_32u = bms_get_cycle_flag() | (bms_get_stat_day() << 8);
data[cnt++].value = (kEep_StatDay_CycleTimesFlag << 16) | ((uint16_t)tmp_32u);
EepromPoData data[15];
// tmp_32u = bms_get_cycle_flag() | (bms_get_stat_day() << 8);
// data[cnt++].value = (kEep_StatDay_CycleTimesFlag << 16) | ((uint16_t)tmp_32u);
data[cnt++].value = (kEep_SOC << 16) | ((uint16_t)bms_get_soc());
data[cnt++].value = (kEep_SOE << 16) | ((uint16_t)bms_get_soc());
data[cnt++].value = (kEep_CycleTimes << 16) | ((uint16_t)bms_get_cycle());
tmp_32u = drv_rtc_get_tick();
data[cnt++].value = (kEep_PowerOffTimeL << 16) | ((uint16_t)tmp_32u);
data[cnt++].value = (kEep_PowerOffTimeH << 16) | ((uint16_t)(tmp_32u >> 16));
tmp_32u = bms_get_cumulate_data(kCumulateData_DayDisTime);
// data[cnt++].value = (kEep_SOE << 16) | ((uint16_t)bms_get_soc());
// data[cnt++].value = (kEep_CycleTimes << 16) | ((uint16_t)bms_get_cycle());
// tmp_32u = drv_rtc_get_tick();
// data[cnt++].value = (kEep_PowerOffTimeL << 16) | ((uint16_t)tmp_32u);
// data[cnt++].value = (kEep_PowerOffTimeH << 16) | ((uint16_t)(tmp_32u >> 16));
//
tmp_32u = bms_get_cycle_flag() | (bms_get_stat_day() << 8);
data[cnt++].value = (kEep_StatDay_CycleTimesFlag << 16) | ((uint16_t)tmp_32u);
tmp_32u = bms_get_cumulate_data(kCumulateData_DayDisTime);
tmp_32u |= bms_get_cumulate_data(kCumulateData_DayChgTime) << 8;
data[cnt++].value = (kEep_DayChg_DisTime << 16) | ((uint16_t)tmp_32u);
for(i = 0; i < 10; i++)
@ -970,7 +972,7 @@ void bms_pwr_off_save(void)
data[cnt++].value = ((kEep_DayDisCapL + (i << 1)) << 16) | (uint16_t)tmp_32u;
data[cnt++].value = ((kEep_DayDisCapH + (i << 1)) << 16) | (uint16_t)(tmp_32u >> 16);
}
data[cnt++].value = (kEep_IsSoftReset << 16) | 0;
// data[cnt++].value = (kEep_IsSoftReset << 16) | 0;
bsp_eeprom_power_off_save_data(data, cnt);
}

View File

@ -117,7 +117,7 @@ void bms_analyse_exterme_fault(RunStatus status, uint32_t base_time)
|| (fault_item.fault_data[kFaultData_MinVolt] <= cell_limit_value[cell_type][0]))
{
volt_dly += base_time;
if(volt_dly >= KIT_SECOND_CONVERT(2))
if(volt_dly >= KIT_SECOND_CONVERT(10))
{
bms_set_fault_level_by_status(status, kFaultCode_Exterme, (FaultLevel)(kFaultLevel_End - 1), kFaultHandle_CutNoRelIdx);
bms_cut_all_relay();
@ -128,20 +128,20 @@ void bms_analyse_exterme_fault(RunStatus status, uint32_t base_time)
volt_dly = 0;
}
if((fault_item.fault_data[kFaultData_MaxTemp] >= KIT_TEMP_CONVERT(65))
|| (fault_item.fault_data[kFaultData_MinTemp] <= KIT_TEMP_CONVERT(-30)))
{
temp_dly += base_time;
if(temp_dly >= KIT_SECOND_CONVERT(2))
{
bms_set_fault_level_by_status(status, kFaultCode_Exterme, kFaultLevel_Third, kFaultHandle_CutNoRelIdx);
bms_cut_all_relay();
}
}
else
{
temp_dly = 0;
}
// if((fault_item.fault_data[kFaultData_MaxTemp] >= KIT_TEMP_CONVERT(65))
// || (fault_item.fault_data[kFaultData_MinTemp] <= KIT_TEMP_CONVERT(-30)))
// {
// temp_dly += base_time;
// if(temp_dly >= KIT_SECOND_CONVERT(2))
// {
// bms_set_fault_level_by_status(status, kFaultCode_Exterme, kFaultLevel_Third, kFaultHandle_CutNoRelIdx);
// bms_cut_all_relay();
// }
// }
// else
// {
// temp_dly = 0;
// }
}
FaultLevel bms_get_max_fault_level(void)
@ -180,7 +180,19 @@ FaultLevel bms_get_min_fault_level(void)
return level1;
}
uint32_t bms_get_total_alarm(uint16_t input)
{
FaultLevel level;
level = bms_get_max_fault_level() == kFaultLevel_First || bms_get_max_fault_level() == kFaultLevel_Second;
return level;
}
uint32_t bms_get_total_fault(uint16_t input)
{
FaultLevel level;
level = bms_get_max_fault_level() == kFaultLevel_Third;
return level;
}
uint8_t bms_get_fault_cur_rate(RunStatus status)
{
@ -384,6 +396,7 @@ const FaultLevel alarm_level_map[8] =
kFaultLevel_Normal, kFaultLevel_First, kFaultLevel_Second, kFaultLevel_Second,
kFaultLevel_Third, kFaultLevel_Third, kFaultLevel_Third, kFaultLevel_Third,
};
void bms_analyse_fault(RunStatus status, FaultArray *fault_array)
{
uint32_t i, j;
@ -412,15 +425,29 @@ void bms_analyse_fault(RunStatus status, FaultArray *fault_array)
handler = get_eeprom_data(FAULT_ALARM_HANDLER_ADDR(tmp), kEepromDataType_Full);
alarm_handle = handler & 0x0003;
cur_rate[j + kFaultLevel_End - level] = handler >> 8;
if(alarm_handle == kFaultHandle_ForbidIdx)//禁用
{
continue;
}
if(alarm_handle == kFaultHandle_ForbidIdx)//禁用
{
continue;
}
else if(alarm_handle != kFaultHandle_ForbidIdx)
{
data = fault_item.fault_data[prop_array[i].data_idx];
threshold[kCondType_Alarm] = get_eeprom_data(FAULT_ARARM_THRESHOLD_ADDR(tmp), kEepromDataType_Full);
threshold[kCondType_Release] = get_eeprom_data(FAULT_RELEASE_THRESHOLD_ADDR(tmp), kEepromDataType_Full);
if (i == 10 || i == 11)
{
uint16_t cell_threshold_idx = (i == 10) ? prop_array[12].threshold_idx : prop_array[13].threshold_idx;
uint16_t cell_threshold = get_eeprom_data(FAULT_ARARM_THRESHOLD_ADDR(cell_threshold_idx + j * 5), kEepromDataType_Full);
threshold[kCondType_Alarm] = (cell_threshold * bms_get_cell_num()) / 100;
cell_threshold = get_eeprom_data(FAULT_RELEASE_THRESHOLD_ADDR(cell_threshold_idx + j * 5), kEepromDataType_Full);
threshold[kCondType_Release] = (cell_threshold * bms_get_cell_num()) / 100;
}
else
{
threshold[kCondType_Alarm] = get_eeprom_data(FAULT_ARARM_THRESHOLD_ADDR(tmp), kEepromDataType_Full);
threshold[kCondType_Release] = get_eeprom_data(FAULT_RELEASE_THRESHOLD_ADDR(tmp), kEepromDataType_Full);
}
if(prop_array[i].other_cond == NULL) //如果没有其他故障判断策略,默认模版策略
{
check_type = prop_array[i].check_type & 0x03;

View File

@ -166,8 +166,8 @@ typedef enum
//******报警级别******//
typedef enum
{
kFaultLevel_Normal = 0,
kFaultLevel_First,
kFaultLevel_Normal = 0,
kFaultLevel_First,
kFaultLevel_Second,
kFaultLevel_Third,
kFaultLevel_End,
@ -253,6 +253,10 @@ void bms_analyse_pwr_on_fault(RunStatus status, FaultArray *fault_array, uint32_
void bms_clear_fault_relay_off_bit(FaultCode idx);
void bms_clear_fault_relay_off_bit_by_status(RunStatus status, FaultCode idx);
//总故障,总告警
uint32_t bms_get_total_alarm(uint16_t input);
uint32_t bms_get_total_fault(uint16_t input);
#ifdef __cplusplus
}
#endif

View File

@ -48,10 +48,10 @@ const FaultProp dis_fault_array[] =
{kFaultCode_MSComm, 1, kFaultData_MScomm, kEep_MSCommAlarm1, kCheckType_MoreThan | FAULT_RELAY_BOTH_OFF, NULL},
{kFaultCode_CmdTimeout, 1, kFaultData_CmdHeart, kEep_CmdTimeoutAlarm, kCheckType_MoreThan | FAULT_RELAY_BOTH_OFF, NULL},
{kFaultCode_LowTotalVolt, 3, kFaultData_TotalVolt, kEep_DisLTVoltHTAlarm1, kCheckType_LessThan, bms_dis_low_volt_ht_call},
{kFaultCode_LowTotalVolt, 3, kFaultData_TotalVolt, kEep_DisLTVoltLTAlarm1, kCheckType_LessThan, bms_dis_low_volt_lt_call},
{kFaultCode_LowCellVolt, 3, kFaultData_MinVolt, kEep_DisLCVoltHTAlarm1, kCheckType_LessThan, bms_dis_low_volt_ht_call},
{kFaultCode_LowCellVolt, 3, kFaultData_MinVolt, kEep_DisLCVoltLTAlarm1, kCheckType_LessThan, bms_dis_low_volt_lt_call},
{kFaultCode_LowTotalVolt, 3, kFaultData_TotalVolt, kEep_DisLTVoltHTAlarm1, kCheckType_LessThan, bms_dis_low_volt_ht_call}, //10
{kFaultCode_LowTotalVolt, 3, kFaultData_TotalVolt, kEep_DisLTVoltLTAlarm1, kCheckType_LessThan, bms_dis_low_volt_lt_call}, //11
{kFaultCode_LowCellVolt, 3, kFaultData_MinVolt, kEep_DisLCVoltHTAlarm1, kCheckType_LessThan, bms_dis_low_volt_ht_call}, //12
{kFaultCode_LowCellVolt, 3, kFaultData_MinVolt, kEep_DisLCVoltLTAlarm1, kCheckType_LessThan, bms_dis_low_volt_lt_call}, //13
{kFaultCode_HighCellVolt, 3, kFaultData_MaxVolt, kEep_DisHCVoltAlarm1, kCheckType_MoreThan, NULL},
{kFaultCode_HighCur, 3, kFaultData_Current, kEep_DisOverCurAlarm1, kCheckType_MoreThan, bms_dis_high_cur_call},
{kFaultCode_HighCellTemp, 3, kFaultData_MaxTemp, kEep_DisHighTempAlarm1, kCheckType_MoreThan, NULL},
@ -104,10 +104,10 @@ const FaultProp chg_fault_array[] =
{kFaultCode_MSComm, 1, kFaultData_MScomm, kEep_MSCommAlarm1, kCheckType_MoreThan | FAULT_RELAY_BOTH_OFF, NULL},
{kFaultCode_CmdTimeout, 1, kFaultData_CmdHeart, kEep_CmdTimeoutAlarm, kCheckType_MoreThan | FAULT_RELAY_BOTH_OFF, NULL},
{kFaultCode_HighTotalVolt, 3, kFaultData_TotalVolt, kEep_ChgHTVoltHTAlarm1, kCheckType_MoreThan, bms_chg_high_volt_ht_call},
{kFaultCode_HighTotalVolt, 3, kFaultData_TotalVolt, kEep_ChgHTVoltLTAlarm1, kCheckType_MoreThan, bms_chg_high_volt_lt_call},
{kFaultCode_HighCellVolt, 3, kFaultData_MaxVolt, kEep_ChgHCVoltHTAlarm1, kCheckType_MoreThan, bms_chg_high_volt_ht_call},
{kFaultCode_HighCellVolt, 3, kFaultData_MaxVolt, kEep_ChgHCVoltLTAlarm1, kCheckType_MoreThan, bms_chg_high_volt_lt_call},
{kFaultCode_HighTotalVolt, 3, kFaultData_TotalVolt, kEep_ChgHTVoltHTAlarm1, kCheckType_MoreThan, bms_chg_high_volt_ht_call}, //10
{kFaultCode_HighTotalVolt, 3, kFaultData_TotalVolt, kEep_ChgHTVoltLTAlarm1, kCheckType_MoreThan, bms_chg_high_volt_lt_call}, //11
{kFaultCode_HighCellVolt, 3, kFaultData_MaxVolt, kEep_ChgHCVoltHTAlarm1, kCheckType_MoreThan, bms_chg_high_volt_ht_call}, //12
{kFaultCode_HighCellVolt, 3, kFaultData_MaxVolt, kEep_ChgHCVoltLTAlarm1, kCheckType_MoreThan, bms_chg_high_volt_lt_call}, //13
{kFaultCode_LowCellVolt, 3, kFaultData_MinVolt, kEep_ChgLCVoltAlarm1, kCheckType_LessThan, NULL},
{kFaultCode_HighCur, 3, kFaultData_Current, kEep_ChgOverCurAlarm1, kCheckType_MoreThan, bms_chg_high_cur_call},
{kFaultCode_HighCellTemp, 3, kFaultData_MaxTemp, kEep_ChgHighTempAlarm1, kCheckType_MoreThan, NULL},

View File

@ -5,6 +5,13 @@
* @copyright
******************************************************************************/
#include "gpio_manager.h"
#include "stm32f4xx.h"
//#define TX_DMA_BUFFER_SIZE 800
extern uint8_t dma_tx_buffer[];
extern volatile uint8_t dma_tx_busy;
extern volatile uint8_t current_buffer;
const GpioArray io_array[kGpioType_End] =
{
@ -50,6 +57,9 @@ const GpioArray io_array[kGpioType_End] =
kGpioMode_Comm_Rx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 1), kGpioPort_A, kGpioPin_1 , //rs485A Rx(mcu uart1)
kGpioMode_Comm_Tx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 0), kGpioPort_A, kGpioPin_0 , //rs485A Tx(mcu uart1)
kGpioMode_Comm_Rx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 3), kGpioPort_A, kGpioPin_3, //Sim卡/wifi/ble Rx(mcu uart2)
kGpioMode_Comm_Tx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 2), kGpioPort_A, kGpioPin_2, //Sim卡/wifi/ble Tx(mcu uart2)
/*CAN枚举*/
kGpioMode_Comm_Rx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 11), kGpioPort_A, kGpioPin_11 , //can1 rx
kGpioMode_Comm_Tx, kGpioStatus_Low, GPIO_PORT_PIN(kGpioPort_A, 12), kGpioPort_A, kGpioPin_12 , //can1 tx
@ -89,9 +99,51 @@ const GpioArray io_array[kGpioType_End] =
kGpioMode_Input_Floating, kGpioStatus_High, GPIO_PORT_PIN(kGpioPort_G, 15), kGpioPort_G, kGpioPin_15 , //W5500_INT
};
void reset_dma_tx_state(void)
{
__disable_irq();
dma_tx_busy = 0;
current_buffer = 0;
__enable_irq();
}
void drv_wireless_dma_init(void)
{
// 使能 DMA1 和 USART2 的时钟
RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN;
RCC->APB1ENR |= RCC_APB1ENR_USART2EN;
// 配置 USART2 基本参数
USART2->CR1 &= ~USART_CR1_UE; // 先禁用USART
USART2->BRR = SystemCoreClock / 115200; // 设置波特率
USART2->CR1 = USART_CR1_TE | USART_CR1_UE;
// 配置 DMA1 Stream6 通道4 对应 USART2_TX
DMA1_Stream6->CR &= ~DMA_SxCR_EN;
while (DMA1_Stream6->CR & DMA_SxCR_EN); // 等待 DMA 关闭
DMA1_Stream6->PAR = (uint32_t)&USART2->DR;
DMA1_Stream6->M0AR = (uint32_t)dma_tx_buffer;
DMA1_Stream6->NDTR = 0;
DMA1_Stream6->CR = (4 << 25) | // 通道4
DMA_SxCR_MINC | // 内存递增
DMA_SxCR_DIR_0 | // 内存到外设
DMA_SxCR_TCIE | // 传输完成中断
DMA_SxCR_TEIE | // 建议添加传输错误中断
(0 << 16); // 优先级
reset_dma_tx_state();
DMA1_Stream6->CR |= (1 << 0); // 启用FIFO
DMA1_Stream6->FCR = (0x3 << 0); // 全FIFO模式
NVIC_EnableIRQ(DMA1_Stream6_IRQn);
}
void bms_init_gpio(void)
{
drv_gpio_init(io_array, kGpioType_End);
drv_wireless_dma_init();
}

View File

@ -36,13 +36,13 @@ typedef enum
kGpioType_DO_Start = kGpioType_Di_End,
kGpioType_DO1 = kGpioType_DO_Start,
kGpioType_DO2,
kGpioType_DO3,
kGpioType_DO4,
kGpioType_DO5,
kGpioType_DO6,
kGpioType_DO3,
kGpioType_DO4,
kGpioType_DO5,
kGpioType_DO6,
kGpioType_DO7,
kGpioType_DO8,
kGpioType_DO9, //低边1
kGpioType_DO8,
kGpioType_DO9, //低边1
kGpioType_DO10, //低边2
kGpioType_DO_End,
@ -52,11 +52,14 @@ typedef enum
kGpioType_RS485_Ch3_Tx_En,
kGpioType_Rs485_Ch1_Rx,
kGpioType_Rs485_Ch1_Tx,
kGpioType_Rs485_Ch2_Rx,
kGpioType_Rs485_Ch2_Rx,
kGpioType_Rs485_Ch2_Tx,
kGpioType_Rs485_Ch3_Rx,
kGpioType_Rs485_Ch3_Rx,
kGpioType_Rs485_Ch3_Tx,
kGpioType_WIRELESSUart_Rx, //Sim卡/wifi/ble
kGpioType_WIRELESSUart_Tx, //Sim卡/wifi/ble
/*CAN枚举*/
kGpioType_Can_Ch1_Rx,
kGpioType_Can_Ch1_Tx,
@ -65,11 +68,11 @@ typedef enum
/*绝缘监测*/
kGpioType_IsoS1,
kGpioType_IsoS2,
kGpioType_IsoS2,
kGpioType_IsoS3,
/*ADC枚举*/
kGpioType_Adc24V,
kGpioType_Adc24V,
kGpioType_AdcNtc, //板载温度
kGpioType_AdcHall1,
@ -88,12 +91,12 @@ typedef enum
kGpioType_ADC_Cs,
/*以太网模块*/
kGpioType_W5500Mosi,
kGpioType_W5500Mosi,
kGpioType_W5500Miso,
kGpioType_W5500Clk,
kGpioType_W5500Cs,
kGpioType_W5500Rst,
kGpioType_W5500Int,
kGpioType_W5500Rst,
kGpioType_W5500Int,
kGpioType_End ,
}GpioType;

View File

@ -14,14 +14,15 @@
#include "drv_ads8688.h"
#define CUR_FILTER_ENABLE (0u)
#define ADCIC_SAMPLE_CNT (4u)
#define ADCIC_SAMPLE_CNT (20u)
#define MCP3208_SAMPLE_CNT (10u)
ADS8688_STATIC_INIT(ads8688, kSpiDev_2, kGpioType_ADC_Cs);
typedef enum
{
kAdIc_Hv1,
kAdIc_HvBat,
kAdIc_HvBat,
kAdIc_Cur,
kAdIc_HvIso,
kAdIc_HvIsoNagtive,
@ -83,7 +84,7 @@ void bms_init_current(void)
cur_item.shunt_volt = get_eeprom_data(kEep_ChgCurDir_ShuntRatedVolt, kEepromDataType_Low);
cur_item.prop[0].filter = cur_item.prop[1].filter = 0;
// 上位机下发时缩小10倍
// 上位机下发时缩小10倍,分流器量程 乘了 10
cur_item.prop[0].scale = get_eeprom_data(kEep_CurSensor2_1Range, kEepromDataType_Low) * 10;
cur_item.prop[1].scale = get_eeprom_data(kEep_CurSensor2_1Range, kEepromDataType_High) * 10;
@ -186,17 +187,17 @@ int16_t bms_caculate_current(uint32_t base_time)
#if CUR_FILTER_ENABLE
static uint16_t dly = 0;
#endif
int32_t tmp, tmp1, current ,volval = 0;
int32_t tmp, tmp1, current ,tmp_cur ,volval = 0;
CurProp *prop;
if (cur_item.channel < kCurChannel_End)
{
prop = &cur_item.prop[cur_item.channel];
switch (prop->type)
switch (prop->type)
{
case kCurSensor_Shunt:
// 分流器 cur_hv_item.cur_volt_avg / cur_prop.shunt_volt * cur_prop.cur_scale;
//current = (int32_t)cur_hv_item.value[kAdIc_Cur] * prop->scale / cur_item.shunt_volt;
current = HighResCurTrans(cur_hv_item.value[kAdIc_Cur]);
current = (int32_t)cur_hv_item.value[kAdIc_Cur] * prop->scale / cur_item.shunt_volt;
//current = HighResCurTrans(cur_hv_item.value[kAdIc_Cur]);
break;
case kCurSensor_SigHall:
// 霍尔电流
@ -229,8 +230,8 @@ int16_t bms_caculate_current(uint32_t base_time)
break;
}
}
//测试用 SFJ 7.30
current = volval * 100 / 10;
//测试用 SFJ 7.30,2-18,注释
//current = volval * 100 / 10;
// 电流方向
current *= prop->dir;
@ -241,12 +242,18 @@ int16_t bms_caculate_current(uint32_t base_time)
{
current = 0;
}
current = (int64_t)current * get_eeprom_data(kEep_Hall1CalFactor, kEepromDataType_Full) / 1000;
//调试
bms_integral_soc(current, base_time);
//current = (int64_t)current * get_eeprom_data(kEep_Hall1CalFactor, kEepromDataType_Full) / 1000;
cur_hv_item.current = current / 10;//转为 0.1
//调试
bms_integral_soc(current, base_time);
//分流器最大量程350
if (current > 3600 || current < -3600)
{
current = 0;
}
cur_hv_item.current = current / 10;
#if CUR_FILTER_ENABLE
dly += base_time;
@ -282,59 +289,131 @@ uint32_t HighVolTrans(uint16_t voldata)
AdjustValue adIc_adjust_value[kAdIc_End];
uint16_t adIc_reg_map[kAdIc_End] = {MAN_Ch_0, MAN_Ch_1, MAN_Ch_2, MAN_Ch_3, MAN_Ch_4};
uint16_t zero_calc(uint16_t value)
{
if(value > 32700 && value < 32799)
{
return 0;
}
else if(value < 20)
{
return 0;
}
else if(value > 60000)
{
return 0;
}
else
{
return value;
}
}
void get_ad_sample(void)
{
static uint16_t outputdata[16] = {0};
int32_t i =0;
uint16_t ad =0;
static uint16_t outputdata[16] = {0};
int32_t i =0,dir = 1;
int64_t temp_calc;
//uint16_t ad =0;
uint16_t ad = 0,value = 0;
#if ADC_AUTO_MODE
//auto scan mode
drv_enter_auto_rst_mode_Data(outputdata, 6);
#else
//auto scan mode
drv_enter_auto_rst_mode_Data(outputdata, 6);
outputdata[i] = drv_get_ads8688_ch_data(MAN_Ch_0);
i += 1;
outputdata[i] = drv_get_ads8688_ch_data(MAN_Ch_1);
i += 1;
outputdata[i] = drv_get_ads8688_ch_data(MAN_Ch_2);
i += 1;
outputdata[i] = drv_get_ads8688_ch_data(MAN_Ch_3);
i += 1;
outputdata[i] = drv_get_ads8688_ch_data(MAN_Ch_4);
i += 1;
outputdata[i] = drv_get_ads8688_ch_data(MAN_Ch_5);
i += 1;
#endif
for (i = 0; i < kAdIc_End; i++)
{
//ad = drv_get_ads8688_ch_data(adIc_reg_map[i]);
cur_hv_item.ad_buf[i][cur_hv_item.ad_buf_pos[i]++] = drv_ads8688_value(outputdata[i]);
ad = cur_hv_item.ad_avg[i] = kit_get_int32_avg_filter_max_min(cur_hv_item.ad_buf[i], ADCIC_SAMPLE_CNT);
if (i == kAdIc_HvIso)
{
//cur_hv_item.value[i] = HighVolTrans2(ad)/100;
bms_set_iso_volt_ad(kIsoVolt_Other, ad);
}
if(i == kAdIc_HvIsoNagtive)
{
}
if (i == kAdIc_HvBat)
{
cur_hv_item.value[i] = (ad / 100) * 512 * 10 / (0x01 << 16); //单位是mv
bms_set_iso_volt_ad(kIsoVolt_TotalVolt, cur_hv_item.value[i]);
}
if(i == kAdIc_Hv1)
{
cur_hv_item.value[i] = (ad / 100) * 512 * 10 / (0x01 << 16); //单位是mv
}
if(i == kAdIc_Cur)
{
ad = ad - adIc_adjust_value[i].zero;
ad = (10 * ad / 82000) * 512 * 1000/ (0x01 << 16); //单位是mv
// 防止eeprom中没有设置电压校准系数
if (get_eeprom_data(kEep_Volt1CalFactor, kEepromDataType_Full) <= 900 || get_eeprom_data(kEep_Volt1CalFactor, kEepromDataType_Full) >= 1100)
//ad = drv_get_ads8688_ch_data(adIc_reg_map[i]);
//0漂处理
if(i == kAdIc_Cur)
{
bsp_eeprom_save_data(kEep_Volt1CalFactor, 1000, kEepromDataType_Full);
outputdata[i] = zero_calc(outputdata[i]);
}
cur_hv_item.value[i] = ad / 1000 * adIc_adjust_value[i].rate *get_eeprom_data(kEep_Volt1CalFactor, kEepromDataType_Full) / 1000;//转为V
}
cur_hv_item.ad_buf[i][cur_hv_item.ad_buf_pos[i]++] = drv_ads8688_value(outputdata[i]);
cur_hv_item.ad_avg[i] = kit_get_int32_avg_filter_max_min(cur_hv_item.ad_buf[i], ADCIC_SAMPLE_CNT);
if (cur_hv_item.ad_buf_pos[i] >= ADCIC_SAMPLE_CNT)
{
cur_hv_item.ad_buf_pos[i] = 0;
}
if(cur_hv_item.ad_avg[i] < 0)
{
dir = -1;
}
// if(i == kAdIc_Cur)
// {
// if(cur_hv_item.ad_avg[i] < 0)
// {
// ad = 32769 - KIT_ABS(cur_hv_item.ad_avg[i]);
// }
// }
ad = KIT_ABS(cur_hv_item.ad_avg[i]);
if (i == kAdIc_HvIso)
{
//cur_hv_item.value[i] = HighVolTrans2(ad)/100;
bms_set_iso_volt_ad(kIsoVolt_Other, dir * ad);
}
if(i == kAdIc_HvIsoNagtive)
{
}
if (i == kAdIc_HvBat)
{
temp_calc = (int64_t)376 * ad * 512 * 10 / (0x01 << 15);
cur_hv_item.value[i] = dir * temp_calc / 100;
bms_set_iso_volt_ad(kIsoVolt_TotalVolt, cur_hv_item.value[i]);
}
if(i == kAdIc_Hv1)
{
temp_calc = (int64_t)376 * ad * 512 * 10 / (0x01 << 15);
cur_hv_item.value[i] = dir * temp_calc / 100;
}
if(i == kAdIc_Cur)
{
//ad = ad - adIc_adjust_value[i].zero;
//ad = (ad * 5120 * 10 / (0x01 << 15)) / 82; //单位是mv
// temp_calc = (int64_t)ad * 15625 / 10000;
// ad = temp_calc / 100; //单位是0.1 mv
if(cur_hv_item.ad_avg[i] < 0)
{
ad = 32769 - KIT_ABS(cur_hv_item.ad_avg[i]);
}
ad = (ad * 2560 * 10 * 100 / (0x01 << 15)) / 82; //单位是0.1 mv
// 防止eeprom中没有设置电压校准系数
if (get_eeprom_data(kEep_Volt1CalFactor, kEepromDataType_Full) <= 900 || get_eeprom_data(kEep_Volt1CalFactor, kEepromDataType_Full) >= 1100)
{
bsp_eeprom_save_data(kEep_Volt1CalFactor, 1000, kEepromDataType_Full);
}
cur_hv_item.value[i] = ad * dir;/// 1000 * adIc_adjust_value[i].rate *get_eeprom_data(kEep_Volt1CalFactor, kEepromDataType_Full) / 1000;//转为V
}
if (cur_hv_item.ad_buf_pos[i] >= ADCIC_SAMPLE_CNT)
{
cur_hv_item.ad_buf_pos[i] = 0;
}
}
}
}
int16_t bms_poll_cur_hv(uint32_t base_time)
@ -432,10 +511,12 @@ const uint32_t adIc_default_rate[kAdIc_End] = {1, 1, 1, 1, 1};
//
void bms_init_cur_hv(void)
{
static uint8_t errcnt = 0;
uint32_t i = 0, cnt = 30;
#ifdef ADS_8688_EN
while(drv_ads8688_Init())
while(drv_ads8688_Init() && errcnt < 30)
{
errcnt++;
OSTimeDly(20);
}

View File

@ -13,10 +13,8 @@ extern "C" {
typedef enum
{
kHvType_Iso,
kHvType_Bat,
kHvType_Hv1,
kHvType_Hv2,
kHvType_Bat,
kHvType_End,
}HvType;

View File

@ -17,15 +17,18 @@ DiParamItem di_param_item[kDiType_End];
//辅助触点1
//di_signal->di_item.status, di->di_iteml.type
void ord_di_do_feedback_func(uint32_t base_time, DiStatus di_signal, DiType di)
{
if(di < kDiType_End)
{
if(bms_get_do_status_by_idx(di - kDiType_Do1Feedback) != di_signal)
{
//I don't know what's the meaning of this line.Whatever I change the 5000 to what , it is always enter the " if " and set the fault level.
di_param_item[di].dly += base_time;
if(di_param_item[di].dly >= 5000)
{
//这里会写进错误--反馈异常,这里的一级代表三级错误
bms_set_fault_level(kFaultCode_Feedback, kFaultLevel_First, kFaultHandle_AlarmIdx);
}
}
@ -93,8 +96,9 @@ void ord_di_breaker1_fun(uint32_t base_time, DiStatus di_signal, DiType di)
{
if((di < kDiType_End) && (di_signal == kDiStatus_Trigger))
{
//这里会写进错误--反馈异常,这里的三级代表一级错误
di_param_item[di].dly += base_time;
bms_set_fault_level(kFaultCode_Feedback, kFaultLevel_Third, kFaultHandle_CutNoRelIdx);
bms_set_fault_level(kFaultCode_Feedback, kFaultLevel_Third, kFaultHandle_CutNoRelIdx);
}
}

View File

@ -13,7 +13,7 @@ DoLogicStatus logic_cmd_ctrl(uint32_t base_time)
if(bms_get_circuit_cmd_status()== kCircuitStatus_On && bms_is_dis_allow() == true && bms_is_chg_allow() == true)
{
bms_crtl_do_status(kDoType_Positive, kDoCtrlStatus_On, 100);
bms_crtl_do_status(kDoType_Negative, kDoCtrlStatus_On, 100);
bms_crtl_do_status(kDoType_Negative, kDoCtrlStatus_On, 100);
status = kDoLogicStatus_On;
}
break;

View File

@ -92,7 +92,7 @@ bool logic_adhesion_check(uint32_t base_time, DoType type)
void logic_open_check(uint32_t base_time)
{
uint16_t tv, hv, rate;
DoErrSrc do_err_src = bms_get_do_err_src(kDoType_Positive);
DoErrSrc do_err_src = bms_get_do_err_src(kDoType_Chg);
FaultLevel fault = kFaultLevel_Normal;
static uint16_t dly;
@ -161,8 +161,8 @@ void logic_same_circuit_ctrl(uint32_t base_time)
//kEep_IsSoftReset高低只能清楚一个否则断电下带无法保存0
if(((bms_get_run_status() != kRunStatus_Init) && (bms_get_circuit_cmd_status() == kCircuitStatus_On)) || (dly >= 10000))
{
bms_crtl_do_status(kDoType_Positive, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_Negative, kDoCtrlStatus_On, 100);
bms_crtl_do_status(kDoType_Chg, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_On, 100);
dly = 0;
status = kDoLogicStatus_On;
}
@ -177,7 +177,7 @@ void logic_same_circuit_ctrl(uint32_t base_time)
//增加init状态防止预充中反复检测粘连 建议增加多次检测
//Gary 2024-07-25 连续粘连3秒才报粘连故障
dly += base_time;
if(logic_adhesion_check(base_time, kDoType_Positive) == true)
if(logic_adhesion_check(base_time, kDoType_Chg) == true)
{
dly = 0;
status = kDoLogicStatus_Off;
@ -189,22 +189,22 @@ void logic_same_circuit_ctrl(uint32_t base_time)
if (prechg_max_cnt == 0) //读取配置:不预充
{
status = kDoLogicStatus_On;
bms_crtl_do_status(kDoType_Negative, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_Positive, kDoCtrlStatus_On, 100);
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_Chg, kDoCtrlStatus_On, 100);
}
else //读取配置:预充
{
if (prechg_cnt++ < prechg_max_cnt) //判断预充次数
{
status = kDoLogicStatus_Prechg;
//bms_crtl_do_status(kDoType_Positive, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY); //闭合总正继电器
bms_crtl_do_status(kDoType_Negative, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY);
//bms_crtl_do_status(kDoType_Chg, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY); //闭合总正继电器
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_PreChg, kDoCtrlStatus_On, 100);
}
else
{
bms_crtl_do_status(kDoType_Negative, kDoCtrlStatus_Off, 100);
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_Off, 100);
bms_set_fault_level(kFaultCode_PreChg, kFaultLevel_Third, kFaultHandle_CutNoRelIdx);
}
}
@ -215,15 +215,15 @@ void logic_same_circuit_ctrl(uint32_t base_time)
if ((bms_is_dis_allow() == false) || (bms_is_chg_allow() == false))
{
prechg_cnt = 0;
status = kDoLogicStatus_Off;
status = kDoLogicStatus_Off;
bms_crtl_do_status(kDoType_PreChg, kDoCtrlStatus_Off, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_Negative, kDoCtrlStatus_Off, 100);
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_Off, 100);
}
else if (dly >= prechg_time)//预充超时
{
{
dly = 0;
status = kDoLogicStatus_PrechgFail;
bms_crtl_do_status(kDoType_PreChg, kDoCtrlStatus_Off, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_PreChg, kDoCtrlStatus_Off, RELAY_CTRL_NO_DLY);
}
else
{
@ -237,7 +237,7 @@ void logic_same_circuit_ctrl(uint32_t base_time)
dly = 0;
prechg_cnt = 0;
status = kDoLogicStatus_On;
bms_crtl_do_status(kDoType_Positive, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY); //闭合总正继电器
bms_crtl_do_status(kDoType_Chg, kDoCtrlStatus_On, RELAY_CTRL_NO_DLY); //闭合总正继电器
bms_crtl_do_status(kDoType_PreChg, kDoCtrlStatus_Off, 500); //延时500ms断开预充继电器
}
}
@ -271,8 +271,8 @@ void logic_same_circuit_ctrl(uint32_t base_time)
{
dly = 0;
status = kDoLogicStatus_WaitAdhesion;
bms_crtl_do_status(kDoType_Positive, kDoCtrlStatus_Off, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_Negative, kDoCtrlStatus_Off, 100);
bms_crtl_do_status(kDoType_Chg, kDoCtrlStatus_Off, RELAY_CTRL_NO_DLY);
bms_crtl_do_status(kDoType_Dis, kDoCtrlStatus_Off, 100);
}
break;
case kDoLogicStatus_WaitAdhesion:
@ -296,8 +296,8 @@ void logic_same_circuit_poll(uint32_t base_time, uint8_t idx)
CircuitStatus circuit_st = kCircuitStatus_On;
logic_same_circuit_ctrl(base_time);
pos_rly_st = bms_get_do_status_by_type(kDoType_Positive);
neg_rly_st = (bms_is_do_config(kDoType_Negative) == true) ? bms_get_do_status_by_type(kDoType_Negative) : kDoStatus_On;
pos_rly_st = bms_get_do_status_by_type(kDoType_Chg);
neg_rly_st = (bms_is_do_config(kDoType_Dis) == true) ? bms_get_do_status_by_type(kDoType_Dis) : kDoStatus_On;
//neg_rly_st = kDoStatus_On;
if(((pos_rly_st != kDoStatus_On) && (pos_rly_st != kDoStatus_ForceOn))

View File

@ -4,6 +4,7 @@
* @brief TaskEntry
* @version V1.0.0
* @remark
* @date 20250209
* @copyright
******************************************************************************/
#include "task_register.h"

View File

@ -149,7 +149,7 @@ bool bms_is_chg_circuit_allow(void)
res = (bms_get_main_ctrl_strategy() == kDoCtrlStrategy_DiffCircuit) ? (run_item.run_status == kRunStatus_Chg) : (run_item.run_status != kRunStatus_Init);
if((res != true) || (bms_get_fault_relay_off_bit_by_status(kRunStatus_Chg) != 0)
|| (bms_get_signal(kSignalIdx_LowVoltSleep) == kSignalStatus_High)|| (bms_get_signal(kSignalIdx_StandbySleep) == kSignalStatus_High))
{
{
res = false;
}
return res;

View File

@ -146,8 +146,8 @@ uint16_t soh_init(uint16_t cycle, uint32_t dis_cap, uint32_t charge_cap)
{
uint16_t soh_loss1 = 0; //充放电次数计算出的SOH损耗百分比
uint16_t soh_loss2 = 0; //累计放电安时计算出的SOH损耗百分比
uint32_t rated_cap = get_eeprom_data(kEep_RatedCapacity, kEepromDataType_Full);
uint16_t cycle_70 = get_eeprom_data(kEep_SOHSeventyCycle, kEepromDataType_Full);
uint32_t rated_cap = get_eeprom_data(kEep_RatedCapacity, kEepromDataType_Full); //2800
uint16_t cycle_70 = get_eeprom_data(kEep_SOHSeventyCycle, kEepromDataType_Full);//3000
if(cycle <= 10)
{
@ -207,7 +207,7 @@ void cap_data_update(uint16_t base_time)
if (run_status == kRunStatus_Chg)
{
chg_dly += KIT_SECOND_CONVERT(1);
if(chg_dly >= KIT_MINUTE_CONVERT(6))
if(chg_dly >= KIT_MINUTE_CONVERT(6))//
{
chg_dly -= KIT_MINUTE_CONVERT(6);
@ -303,7 +303,7 @@ void soc_run_calibrate(int16_t current, uint16_t base_time)
static uint16_t dis_dly = 0;
static uint16_t chg_dly = 0;
uint8_t temp = 0;
//放电
if((current < 0) && (sox_item.dis_adjust_flag == false) &&
(bms_get_statistic_data(kStatisticData_MinVolt) <= 3000) &&
@ -368,11 +368,11 @@ void soc_exterme_calibrate(int16_t current, uint16_t base_time)
{
case kSocAdjustStep_Wait:
avg_volt = bms_get_statistic_data(kStatisticData_AvgVolt);
total_volt = bms_get_statistic_data(kStatisticData_AccVolt) / 100;
total_volt = bms_get_statistic_data(kStatisticData_AccVolt)/ 100;
if (((bms_get_statistic_data(kStatisticData_MinVolt) <= get_eeprom_data(kEep_FullDisVolt, kEepromDataType_Full))
&& (avg_volt <= get_eeprom_data(kEep_FullDisAvgVolt, kEepromDataType_Full))
&& (bms_get_ex_data(kExType_CellVolt) == kExStatus_None))
|| (total_volt <= get_eeprom_data(kEep_FullDisTotalVolt, kEepromDataType_Full))
|| (total_volt <= get_eeprom_data(kEep_FullDisTotalVolt, kEepromDataType_Full)/100)
|| ((sox_item.soc_req_st == kSocStatus_Empty) && (sox_item.is_bsu_adjust == false)))
{
full_dly = 0;
@ -463,15 +463,16 @@ void bms_init_soc(void)
{
uint32_t soc;
uint64_t tmp_64u;
int32_t year, mon, day;
int32_t year, mon, day;
soc = get_eeprom_data(kEep_SOC, kEepromDataType_Full);
//soc = bms_check_pwr_on_ocv(soc);
sox_item.soc_kEep_99 = true;
sox_item.soc_kEep_1 = true;
if (soc == 0)
{
sox_item.soc_kEep_1 = false;
sox_item.soc_kEep_1 = false;
}
else if (soc == SOX_MAX_SOC_VALUE)
{
@ -504,6 +505,7 @@ void bms_init_soc(void)
sox_item.rated_cap = tmp_64u;
sox_item.soc_1_cap = (SOX_DIS_kEep_SOC * tmp_64u) / SOX_MAX_SOC_VALUE;
sox_item.soc_99_cap = (SOX_CHG_kEep_SOC * tmp_64u) / SOX_MAX_SOC_VALUE;
sox_item.calculate_cap = (soc * tmp_64u) / SOX_MAX_SOC_VALUE;
sox_item.cycle = get_eeprom_data(kEep_CycleTimes, kEepromDataType_Full);
@ -553,12 +555,16 @@ void bms_integral_soc(int32_t current, uint16_t base_time)
uint16_t soc = sox_item.soc;
uint16_t integral_time = 0, total_volt;
uint32_t tmp_32u = 0;
cap_data_update(base_time);
soc_exterme_calibrate(current, base_time);
if(sox_item.adjust_step != kSocAdjustStep_Wait)
return;
// /*soc test add 2-19
// current = 168;
// soc_run_calibrate(168, base_time);
// */
tmp_32u = kit_time_get_tick();
integral_time = kit_time_get_interval(sox_item.last_tick, tmp_32u);
sox_item.last_tick = tmp_32u;
@ -637,7 +643,7 @@ void bms_integral_soc(int32_t current, uint16_t base_time)
tmp_32u = SOX_MAX_SIGNAL_INTEGRAL;
sox_item.tmp_dis_cap += tmp_32u;
//单位 kWms
//单位 kWms--
sox_item.tmp_dis_energy += tmp_32u * total_volt / 10000;
if(sox_item.calculate_cap > 0)

View File

@ -23,26 +23,26 @@ typedef enum
typedef enum
{
kCumulateData_DayDisTime,
kCumulateData_DayDisTime, //0
kCumulateData_DayChgTime,
kCumulateData_SigDisTime,
kCumulateData_SigDisCap,
kCumulateData_SigDisEnergy,
kCumulateData_SigChgTime,
kCumulateData_SigChgTime, //5
kCumulateData_SigChgCap,
kCumulateData_SigChgEnergy,
kCumulateData_DayDisCap,
kCumulateData_DayDisEnergy,
kCumulateData_DayChgCap,
kCumulateData_DayChgCap, //10
kCumulateData_DayChgEnergy,
kCumulateData_AccDisTime,
kCumulateData_AccDisCap,
kCumulateData_AccDisEnergy,
kCumulateData_AccChgTime,
kCumulateData_AccChgCap,
kCumulateData_AccChgCap, //16
kCumulateData_AccChgEnergy,
kCumulateData_End,
}CumulateData;

View File

@ -53,7 +53,7 @@ typedef enum
void bms_analyse_chg_sop(uint32_t base_time)
{
static uint16_t dly = 0;
bool is_forbid_chg;
bool is_forbid_chg;// 充电禁止标志
uint16_t fault_cur, end_cur, fault_power, end_power, req_volt, total_volt;
uint16_t soc, min_temp, max_temp;
int32_t min_temp_cur, max_temp_cur;
@ -61,7 +61,7 @@ void bms_analyse_chg_sop(uint32_t base_time)
soc = bms_get_soc() / 100;
min_temp = (int32_t)bms_get_statistic_data(kStatisticData_MinTemp) /10 - 50;
max_temp = (int32_t)bms_get_statistic_data(kStatisticData_MaxTemp) /10 - 50;
total_volt = bms_get_statistic_data(kStatisticData_TotalVolt) > 300 ? bms_get_statistic_data(kStatisticData_TotalVolt):300;
total_volt = bms_get_statistic_data(kStatisticData_TotalVolt) > 300 ? bms_get_statistic_data(kStatisticData_TotalVolt):300;//534
if(get_eeprom_data(kEep_ChgDisMode_HighVoltStrategy, kEepromDataType_High) == kChgMode_CP)
{
@ -75,7 +75,7 @@ void bms_analyse_chg_sop(uint32_t base_time)
}
else
{
end_power = sop_item.rate_data[kSopData_ChgPower];
end_power = sop_item.rate_data[kSopData_ChgPower];//50
end_cur = (uint32_t)sop_item.rate_data[kSopData_ChgPower] * 10000/total_volt;
}
}

View File

@ -5,9 +5,27 @@
#include "statistic_manager.h"
#include "table_comm.h"
#include "kit_time.h"
#include "hv_adc_manager.h"
uint32_t statistic_data[kStatisticData_End];
typedef struct {
uint8_t bmu_num;
uint16_t min_voltage;
uint16_t max_voltage;
} voltage_range_t;
// 高压堆叠范围对照表所有电压值已×10
const voltage_range_t voltage_ranges[] = {
{1, 490, 550},
{2, 980, 1100},
{3, 1470, 1650},
{4, 1960, 2200},
{5, 2450, 2750},
{6, 2940, 3300},
{7, 3430, 3850},
{8, 3920, 4400}
};
uint32_t bms_get_statistic_data(StatisticData idx)
{
@ -32,7 +50,7 @@ static void bms_statistic_cell_volt(void)
{
// if(bms_is_bmu_online(i) == true)
// {
valid_num += bms_get_bmu_data(i, kBmuData_CellNum);
valid_num += bms_get_bmu_data(i, kBmuData_CellNum);
//单位 mV
pack_volt = bms_get_bmu_statistic_data(i, kBmuStatistic_TotalVolt);
sum_value += pack_volt;
@ -220,10 +238,34 @@ static void bms_statistic_cell_temp(void)
kit_time_dly_ms(2);
}
void update_bmu_number()
{
if (bms_get_bmu_num() <= 8)
{
uint16_t acc_volt = bms_get_high_volt(kHvType_Bat);
for (uint8_t i = 0; i < sizeof(voltage_ranges)/sizeof(voltage_ranges[0]); i++)
{
if (acc_volt >= voltage_ranges[i].min_voltage && acc_volt <= voltage_ranges[i].max_voltage)
{
if (bms_get_bmu_num() != voltage_ranges[i].bmu_num)
{
bms_set_bmu_num(voltage_ranges[i].bmu_num);
bms_set_bmu_volt_num(voltage_ranges[i].bmu_num);
bms_set_bmu_temp_num(voltage_ranges[i].bmu_num);
break;
}
}
}
}
}
void bms_poll_statistic(uint32_t base_time)
{
bms_statistic_cell_volt();
bms_statistic_cell_temp();
update_bmu_number();
}

View File

@ -17,6 +17,7 @@ const uint8_t tcp_server_task_name[W5500_MODBUS_NUM][14] =
void poll_1ms_task_init(void);
void poll_10ms_task_init(void);
void poll_mqtt_init(void);
bool is_first_run = false;
@ -27,8 +28,8 @@ void task_1ms_handler(uint32_t base_time)
{
a++;
}
KIT_DEBUG_PRINTF("cur_hv init start \r\n");
bms_poll_cur_hv(base_time);
KIT_DEBUG_PRINTF("cur_hv init start \r\n");
bms_poll_cur_hv(base_time);
}
void task_can1_handler(uint32_t base_time)
@ -40,8 +41,8 @@ void task_can1_handler(uint32_t base_time)
SN_BMS_INIT_CALL user_task_call;
void task_10ms_handler(uint32_t base_time)
{
// static uint32_t cout10ms = 0;
//cout10ms++;
// static uint32_t cout10ms = 0;
// cout10ms++;
bms_poll_signal(base_time);
#ifdef LIB_CREAT
@ -49,26 +50,34 @@ void task_10ms_handler(uint32_t base_time)
#endif
}
void task_mqtt_handler(uint32_t base_time)
{
mqtt_publish_bms_data(base_time);
}
void bms_poll_bmu_handler(uint32_t base_time)
{
bms_poll_bmu(base_time);
task_mqtt_handler(base_time);
}
void task_100ms_handler(uint32_t base_time)
{
static uint32_t cout100ms = 0;
cout100ms++;
static uint32_t cout100ms = 0;
cout100ms++;
bms_poll_iso(base_time);
//bms_poll_adc(base_time);
// bms_poll_adc(); THis was originally commented.
bms_poll_adc(base_time);
bms_poll_statistic(base_time);
bms_poll_run_status(base_time);
bms_poll_run_status(base_time);
bms_poll_sop(base_time);
bms_poll_soh(base_time);
// task_mqtt_handler(base_time);
is_first_run = true;
}
GLOBAL_TASK_VARS_CCM(poll_1ms_task, 4, 10, 5000, 400, poll_1ms_task_init, task_1ms_handler, NULL);
GLOBAL_TASK_VARS_CCM(poll_1ms_task, 4, 100, 5000, 400, poll_1ms_task_init, task_1ms_handler, NULL);
GLOBAL_TASK_VARS_CCM(poll_100ms_task, 1, 100, 2000, 400, NULL, task_100ms_handler, NULL);
GLOBAL_TASK_VARS_CCM(poll_10ms_task, 3, 100, 2000, 400, poll_10ms_task_init, task_10ms_handler, NULL);
@ -81,6 +90,8 @@ GLOBAL_TASK_VARS_CCM(modbus_rtu_task3, 8, 50, 5000, 400, NULL,
GLOBAL_TASK_VARS_CCM(ord_comm_can_task, 5, 100, 5000, 400, NULL, task_can1_handler, NULL);
GLOBAL_TASK_VARS_CCM(bms_poll_bmu_task, 9, 100, 5000, 400, bms_bmu_init, bms_poll_bmu_handler, NULL);
GLOBAL_TASK_VARS_CCM(bms_poll_mqtt_task, 9, 1000, 5000, 400, poll_mqtt_init, task_mqtt_handler, NULL);
#define BMU_FINISH_BIT (0u)
#define SIGNAL_FINISH_BIT (1u)
@ -97,56 +108,64 @@ void poll_1ms_task_init(void)
CPU_IntDisMeasMaxCurReset();
#endif
bms_init_gpio();
bms_init_gpio();
bms_init_eeprom();
//bms_init_adc();
// bms_init_adc(); THis was originally commented.
bms_init_adc();
bms_init_tag();
bms_init_run();
bms_init_comm();
bms_init_comm();
// 2-17 new add
// task_dido_ctrl_handle(1000);
bms_init_di_do(bmsCircuitCtrl, kDoCtrlStrategy_End, doLogicArray);
bsp_create_task(&poll_10ms_task, (uint8_t *)"10ms");
KIT_DEBUG_PRINTF("cur_hv init start \r\n");
// KIT_DEBUG_PRINTF("cur_hv init start \r\n");
//debug here is no more run
// debug here is no more run
bms_init_cur_hv();
KIT_DEBUG_PRINTF("cur_hv init ok \r\n");
// KIT_DEBUG_PRINTF("cur_hv init ok \r\n");
while(KIT_GET_BIT_32(is_data_ok, BMU_FINISH_BIT) == 0)
{
bsp_task_delay_ms(10);
}
//耗时初始化 ≈300ms 确保信号正常
KIT_DEBUG_PRINTF("signal init start \r\n");
// 耗时初始化 ≈300ms 确保信号正常
// KIT_DEBUG_PRINTF("signal init start \r\n");
bms_poll_statistic(0);
bms_init_signal();
//刷新信号策略 确保例如常闭等需要立即闭合do输出
// 刷新信号策略 确保例如常闭等需要立即闭合do输出
task_dido_ctrl_handle(1000);
KIT_DEBUG_PRINTF("signal init ok \r\n");
// KIT_DEBUG_PRINTF("signal init ok \r\n");
KIT_SET_BIT_MASK_32(is_data_ok, SIGNAL_FINISH_BIT);
bsp_create_task(&ord_ctrl_task, (uint8_t *)"ctrl");
bsp_create_task(&ord_ctrl_task, (uint8_t *)"ctrl");
poll_mqtt_init();
}
void poll_10ms_task_init(void)
{
uint8_t i = 0;
uint8_t i = 0;
bms_init_fdb();
//耗时初始化 等待从机上电并初始化完成 ≈500ms且请求两轮数据 ≈1300ms(最大)
// 耗时初始化 等待从机上电并初始化完成 ≈500ms且请求两轮数据 ≈1300ms(最大)
KIT_DEBUG_PRINTF("bmu init start \r\n");
//bms_init_chain_bmu();
// bms_init_chain_bmu();
KIT_DEBUG_PRINTF("bmu init ok \r\n");
bms_poll_statistic(0);
//SOC初始化需要统计数据
// SOC初始化需要统计数据
bms_init_soc();
//掉电中断在SOC初始化完成后打开防止存入未初始化值
drv_misc_cfg_pwr_off_interrupt(APP_CFG_INT_PRIO_PWR_OFF, kPwrOffVolt_2_9, bms_pwr_off_save);
// 掉电中断在SOC初始化完成后打开防止存入未初始化值
drv_misc_cfg_pwr_off_interrupt(APP_CFG_INT_PRIO_PWR_OFF, kPwrOffVolt_2_9, bms_pwr_off_save);
KIT_SET_BIT_MASK_32(is_data_ok, BMU_FINISH_BIT);
//while(KIT_GET_BIT_32(is_data_ok, SIGNAL_FINISH_BIT) == 0)
// next line is originally commented.
while(KIT_GET_BIT_32(is_data_ok, SIGNAL_FINISH_BIT) == 0)
{
bsp_task_delay_ms(10);
}
@ -156,12 +175,16 @@ void poll_10ms_task_init(void)
bms_init_sop();
bms_init_iso();
//bsp_create_task(&poll_100ms_task, (uint8_t *)"100ms");
bsp_create_task(&bms_poll_bmu_task, (uint8_t *)"100ms");
drv_rtc_init();
// bsp_create_task(&poll_100ms_task, (uint8_t *)"100ms");,THis was originally commented.
bsp_create_task(&poll_100ms_task, (uint8_t *)"100ms");
bsp_create_task(&bms_poll_bmu_task, (uint8_t *)"100ms");
bsp_create_task(&ord_comm_can_task, (uint8_t *)"100ms");
bsp_create_task(&modbus_rtu_task1, (uint8_t *)"inter_modbus");
bsp_create_task(&modbus_rtu_task1, (uint8_t *)"inter_modbus");
bsp_create_task(&modbus_rtu_task2, (uint8_t *)"exter1_modbus");
bsp_create_task(&modbus_rtu_task3, (uint8_t *)"exter2_modbus");
bsp_create_task(&modbus_rtu_task3, (uint8_t *)"exter2_modbus");
/*
bms_w5500_net_protocol();
@ -178,6 +201,25 @@ void poll_10ms_task_init(void)
*/
}
void poll_mqtt_init(void)
{
static uint16_t qfc41d_init_count = 0;
while (drv_qfc41d_init() && qfc41d_init_count < 2)
{
drv_wdog_feed();
kit_time_dly_ms(100);
qfc41d_init_count++;
}
// // MQTT ?????
// while (drv_mqtt_init() && mqtt_init_count < 10)
// {
// drv_wdog_feed();
// kit_time_dly_ms(100);
// mqtt_init_count++;
// }
}
/*****************************************************************************
* @brief ucosϵͳÖÐϻص÷

View File

@ -38,7 +38,7 @@ typedef enum
#define DEVICE_HW_MAJOR_VER (1u) //5
#define DEVICE_HW_MINOR_VER (0u) //5
#define DEVICE_HW_BUILD_VER (0u) //6
#define DEVICE_HW_VERSION (((DEVICE_HW_MAJOR_VER&0x1f)<<11)+((DEVICE_HW_MINOR_VER&0x1f)<<6)+(DEVICE_HW_BUILD_VER&0x3f))
//#define DEVICE_HW_VERSION (((DEVICE_HW_MAJOR_VER&0x1f)<<11)+((DEVICE_HW_MINOR_VER&0x1f)<<6)+(DEVICE_HW_BUILD_VER&0x3f))
/*********************************软件版本号*************************************/
#define DEVICE_V_MAJOR_VER (2u) //4
@ -50,9 +50,13 @@ typedef enum
#define DEVICE_C_MINOR_VER (3u) //4
//主干默认版本B0 上述记录即可
#define DEVICE_SW_BUILD_VER (1u)
//#define DEVICE_SW_BUILD_VER (1u)
//#define DEVICE_SW_VERSION ((DEVICE_V_MAJOR_VER << 8) | (DEVICE_V_MINOR_VER))
#define DEVICE_SW_VERSION 1
#define DEVICE_SW_BUILD_VER (0u)
#define DEVICE_HW_VERSION 1
#define DEVICE_SW_VERSION ((DEVICE_V_MAJOR_VER << 8) | (DEVICE_V_MINOR_VER))
#define DEVICE_R_VERSION ((DEVICE_R_MAJOR_VER << 8) | (DEVICE_R_MINOR_VER))
#define DEVICE_C_VERSION ((DEVICE_C_MAJOR_VER << 8) | (DEVICE_C_MINOR_VER))
typedef enum

Binary file not shown.

File diff suppressed because one or more lines are too long

View File

@ -10,15 +10,15 @@
<TargetName>stm32f407</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pArmCC>5060960::V5.06 update 7 (build 960)::.\ARM_Compiler_5.06u7</pArmCC>
<pCCUsed>5060960::V5.06 update 7 (build 960)::.\ARM_Compiler_5.06u7</pCCUsed>
<pArmCC>5050106::V5.05 update 1 (build 106)::ARMCC</pArmCC>
<pCCUsed>5050106::V5.05 update 1 (build 106)::ARMCC</pCCUsed>
<uAC6>0</uAC6>
<TargetOption>
<TargetCommonOption>
<Device>STM32F407ZGTx</Device>
<Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.3.0.0</PackID>
<PackURL>https://www.keil.com/pack/</PackURL>
<PackID>Keil.STM32F4xx_DFP.2.16.0</PackID>
<PackURL>http://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000,0x00020000) IRAM2(0x10000000,0x00010000) IROM(0x08000000,0x00100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE</Cpu>
<FlashUtilSpec></FlashUtilSpec>
<StartupFile></StartupFile>
@ -50,7 +50,7 @@
<InvalidFlash>1</InvalidFlash>
</TargetStatus>
<OutputDirectory>.\Objects\</OutputDirectory>
<OutputName>BCU_APP</OutputName>
<OutputName>BCU14</OutputName>
<CreateExecutable>1</CreateExecutable>
<CreateLib>0</CreateLib>
<CreateHexFile>1</CreateHexFile>
@ -83,7 +83,7 @@
<AfterMake>
<RunUserProg1>1</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name>fromelf --m32combined --output=@L.s19 .\Objects\@L.axf</UserProg1Name>
<UserProg1Name>D:\CodeHvStack\BCU\app\stm32fxxx_app\hex2bin.exe D:\CodeHvStack\BCU\app\stm32fxxx_app\prj\Objects\BCU14.hex</UserProg1Name>
<UserProg2Name></UserProg2Name>
<UserProg1Dos16Mode>0</UserProg1Dos16Mode>
<UserProg2Dos16Mode>0</UserProg2Dos16Mode>
@ -213,7 +213,7 @@
<Ra2Chk>0</Ra2Chk>
<Ra3Chk>0</Ra3Chk>
<Im1Chk>1</Im1Chk>
<Im2Chk>0</Im2Chk>
<Im2Chk>1</Im2Chk>
<OnChipMemories>
<Ocm1>
<Type>0</Type>
@ -341,7 +341,7 @@
<MiscControls></MiscControls>
<Define>STM32F40_41xxx,APP_START_ADDR = 0x08020000,UCOS2,BSE1B,ADS_8688_EN</Define>
<Undefine></Undefine>
<IncludePath>..\app;..\..\..\library\bsp;..\..\..\library\core;..\..\..\library\kit;..\..\..\library\drv_peripheral;..\ord;..\..\..\library\drv_stm32f4xx;..\..\..\library\J1939;..\protocol;..\..\..\library\ucos\uC-OS2\Source;..\..\..\library\ucos\uC-OS2\Ports\ARM-Cortex-M\ARMv7-M\ARM;..\..\..\library\ucos\uC-OS2\Cfg\Template;..\..\..\library\ucos\uC-CPU\ARM-Cortex-M\ARMv7-M\ARM;..\..\..\library\ucos\uC-CPU\Cfg\Template;..\..\..\library\ucos\uC-CPU\Template;..\..\..\library\ucos\uC-CPU;..\..\..\library\ucos\uC-LIB;..\..\..\library\ucos\uC-LIB\Cfg\Template;..\..\..\library\ucos\uC-LIB\Ports\ARM-Cortex-M4\RealView;..\..\..\library\ucos;..\..\..\library\segger\Config;..\..\..\library\segger\Sample\uCOS-II;..\..\..\library\segger\Sample\uCOS-II\Config;..\..\..\library\segger\SEGGER;..\table</IncludePath>
<IncludePath>..\app;..\..\..\library\bsp;..\..\..\library\core;..\..\..\library\kit;..\..\..\library\drv_peripheral;..\ord;..\..\..\library\drv_stm32f4xx;..\..\..\library\J1939;..\protocol;..\..\..\library\ucos\uC-OS2\Source;..\..\..\library\ucos\uC-OS2\Ports\ARM-Cortex-M\ARMv7-M\ARM;..\..\..\library\ucos\uC-OS2\Cfg\Template;..\..\..\library\ucos\uC-CPU\ARM-Cortex-M\ARMv7-M\ARM;..\..\..\library\ucos\uC-CPU\Cfg\Template;..\..\..\library\ucos\uC-CPU\Template;..\..\..\library\ucos\uC-CPU;..\..\..\library\ucos\uC-LIB;..\..\..\library\ucos\uC-LIB\Cfg\Template;..\..\..\library\ucos\uC-LIB\Ports\ARM-Cortex-M4\RealView;..\..\..\library\ucos;..\..\..\library\segger\Config;..\..\..\library\segger\Sample\uCOS-II;..\..\..\library\segger\Sample\uCOS-II\Config;..\..\..\library\segger\SEGGER;..\table;..\..\..\library\cjson</IncludePath>
</VariousControls>
</Cads>
<Aads>
@ -363,7 +363,7 @@
</VariousControls>
</Aads>
<LDads>
<umfTarg>1</umfTarg>
<umfTarg>0</umfTarg>
<Ropi>0</Ropi>
<Rwpi>0</Rwpi>
<noStLib>0</noStLib>
@ -372,7 +372,7 @@
<TextAddressRange>0x08000000</TextAddressRange>
<DataAddressRange>0x20000000</DataAddressRange>
<pXoBase></pXoBase>
<ScatterFile>.\BCU_APP.sct</ScatterFile>
<ScatterFile>.\stm32f407_app.sct</ScatterFile>
<IncludeLibs></IncludeLibs>
<IncludeLibsPath></IncludeLibsPath>
<Misc></Misc>
@ -634,6 +634,16 @@
<FileType>1</FileType>
<FilePath>..\..\..\library\drv_peripheral\drv_w5500.c</FilePath>
</File>
<File>
<FileName>drv_eg25gminipice.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\library\drv_peripheral\drv_eg25gminipice.c</FilePath>
</File>
<File>
<FileName>drv_qfc41d.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\library\drv_peripheral\drv_qfc41d.c</FilePath>
</File>
</Files>
</Group>
<Group>
@ -776,31 +786,31 @@
<FileType>1</FileType>
<FilePath>..\app\dido_manager.c</FilePath>
</File>
<File>
<FileName>eeprom_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\eeprom_manager.c</FilePath>
</File>
<File>
<FileName>fault_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\fault_manager.c</FilePath>
</File>
<File>
<FileName>ocv_tables.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\ocv_tables.c</FilePath>
</File>
<File>
<FileName>fault_register.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\fault_register.c</FilePath>
</File>
<File>
<FileName>gpio_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\gpio_manager.c</FilePath>
</File>
<File>
<FileName>hv_adc_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\hv_adc_manager.c</FilePath>
</File>
<File>
<FileName>gpio_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\gpio_manager.c</FilePath>
</File>
<File>
<FileName>iso_check.c</FileName>
<FileType>1</FileType>
@ -832,9 +842,9 @@
<FilePath>..\app\logic_same_circuit_ctrl.c</FilePath>
</File>
<File>
<FileName>ocv_tables.c</FileName>
<FileName>eeprom_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\ocv_tables.c</FilePath>
<FilePath>..\app\eeprom_manager.c</FilePath>
</File>
<File>
<FileName>run_status.c</FileName>
@ -861,16 +871,16 @@
<FileType>1</FileType>
<FilePath>..\app\statistic_manager.c</FilePath>
</File>
<File>
<FileName>version_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\version_manager.c</FilePath>
</File>
<File>
<FileName>bmu_adbms1818.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\bmu_adbms1818.c</FilePath>
</File>
<File>
<FileName>version_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\version_manager.c</FilePath>
</File>
</Files>
</Group>
<Group>
@ -1130,6 +1140,21 @@
<FileType>1</FileType>
<FilePath>..\protocol\protocol_modbus_bcu.c</FilePath>
</File>
<File>
<FileName>protocol_mqtt_bcu.c</FileName>
<FileType>1</FileType>
<FilePath>..\protocol\protocol_mqtt_bcu.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>Cjson</GroupName>
<Files>
<File>
<FileName>cJSON.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\library\cjson\cJSON.c</FilePath>
</File>
</Files>
</Group>
</Groups>
@ -1145,8 +1170,8 @@
<TargetCommonOption>
<Device>STM32F407VGTx</Device>
<Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.3.0.0</PackID>
<PackURL>https://www.keil.com/pack/</PackURL>
<PackID>Keil.STM32F4xx_DFP.2.16.0</PackID>
<PackURL>http://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000,0x00020000) IRAM2(0x10000000,0x00010000) IROM(0x08000000,0x00100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE</Cpu>
<FlashUtilSpec></FlashUtilSpec>
<StartupFile></StartupFile>
@ -1693,6 +1718,16 @@
<FileType>1</FileType>
<FilePath>..\..\..\library\drv_peripheral\drv_w5500.c</FilePath>
</File>
<File>
<FileName>drv_eg25gminipice.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\library\drv_peripheral\drv_eg25gminipice.c</FilePath>
</File>
<File>
<FileName>drv_qfc41d.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\library\drv_peripheral\drv_qfc41d.c</FilePath>
</File>
</Files>
</Group>
<Group>
@ -1733,31 +1768,31 @@
<FileType>1</FileType>
<FilePath>..\app\dido_manager.c</FilePath>
</File>
<File>
<FileName>eeprom_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\eeprom_manager.c</FilePath>
</File>
<File>
<FileName>fault_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\fault_manager.c</FilePath>
</File>
<File>
<FileName>ocv_tables.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\ocv_tables.c</FilePath>
</File>
<File>
<FileName>fault_register.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\fault_register.c</FilePath>
</File>
<File>
<FileName>gpio_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\gpio_manager.c</FilePath>
</File>
<File>
<FileName>hv_adc_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\hv_adc_manager.c</FilePath>
</File>
<File>
<FileName>gpio_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\gpio_manager.c</FilePath>
</File>
<File>
<FileName>iso_check.c</FileName>
<FileType>1</FileType>
@ -1789,9 +1824,9 @@
<FilePath>..\app\logic_same_circuit_ctrl.c</FilePath>
</File>
<File>
<FileName>ocv_tables.c</FileName>
<FileName>eeprom_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\ocv_tables.c</FilePath>
<FilePath>..\app\eeprom_manager.c</FilePath>
</File>
<File>
<FileName>run_status.c</FileName>
@ -1818,16 +1853,16 @@
<FileType>1</FileType>
<FilePath>..\app\statistic_manager.c</FilePath>
</File>
<File>
<FileName>version_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\version_manager.c</FilePath>
</File>
<File>
<FileName>bmu_adbms1818.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\bmu_adbms1818.c</FilePath>
</File>
<File>
<FileName>version_manager.c</FileName>
<FileType>1</FileType>
<FilePath>..\app\version_manager.c</FilePath>
</File>
</Files>
</Group>
<Group>
@ -2018,6 +2053,21 @@
<FileType>1</FileType>
<FilePath>..\protocol\protocol_modbus_bcu.c</FilePath>
</File>
<File>
<FileName>protocol_mqtt_bcu.c</FileName>
<FileType>1</FileType>
<FilePath>..\protocol\protocol_mqtt_bcu.c</FilePath>
</File>
</Files>
</Group>
<Group>
<GroupName>Cjson</GroupName>
<Files>
<File>
<FileName>cJSON.c</FileName>
<FileType>1</FileType>
<FilePath>..\..\..\library\cjson\cJSON.c</FilePath>
</File>
</Files>
</Group>
</Groups>

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +1,45 @@
[BREAKPOINTS]
ForceImpTypeAny = 0
ShowInfoWin = 1
EnableFlashBP = 2
BPDuringExecution = 0
FForceImpTypeAny = 0
ShowInfoWin = 1
EnableFlashBP = 2
BPDuringExecution = 0
orceImpTypeAny = 0
[CFI]
CFISize = 0x00
CFIAddr = 0x00
CCFISize = 0x00
CFIAddr = 0x00
FISize = 0x00
[CPU]
MonModeVTableAddr = 0xFFFFFFFF
MOverrideMemMap = 0
AllowSimulation = 1
ScriptFile=""
onModeVTableAddr = 0xFFFFFFFF
MonModeDebug = 0
MaxNumAPs = 0
LowPowerHandlingMode = 0
OverrideMemMap = 0
AllowSimulation = 1
ScriptFile=""
[FLASH]
CacheExcludeSize = 0x00
CacheExcludeAddr = 0x00
MinNumBytesFlashDL = 0
SkipProgOnCRCMatch = 1
VerifyDownload = 1
AllowCaching = 1
EnableFlashDL = 2
Override = 0
Device="ARM7"
CCacheExcludeSize = 0x00
CacheExcludeAddr = 0x00
MinNumBytesFlashDL = 0
SkipProgOnCRCMatch = 1
VerifyDownload = 1
AllowCaching = 1
EnableFlashDL = 2
Override = 1
Device="Unspecified"
acheExcludeSize = 0x00
[GENERAL]
WorkRAMSize = 0x00
WorkRAMAddr = 0x00
RAMUsageLimit = 0x00
WWorkRAMSize = 0x00
WorkRAMAddr = 0x00
RAMUsageLimit = 0x00
orkRAMSize = 0x00
[SWO]
SWOLogFile=""
SSWOLogFile=""
WOLogFile=""
[MEM]
RdOverrideOrMask = 0x00
RdOverrideAndMask = 0xFFFFFFFF
RdOverrideAddr = 0xFFFFFFFF
WrOverrideOrMask = 0x00
WrOverrideAndMask = 0xFFFFFFFF
WrOverrideAddr = 0xFFFFFFFF
RRdOverrideOrMask = 0x00
RdOverrideAndMask = 0xFFFFFFFF
RdOverrideAddr = 0xFFFFFFFF
WrOverrideOrMask = 0x00
WrOverrideAndMask = 0xFFFFFFFF
WrOverrideAddr = 0xFFFFFFFF
dOverrideOrMask = 0x00

View File

@ -0,0 +1,22 @@
; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08020000 0x00100000 { ; load region size_region
ER_IROM1 0x08020000 0x00100000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
.ANY (+XO)
}
RW_IRAM1 0x20000000 0x0001C000 { ; 112KB SRAM1
.ANY (+RW +ZI)
}
RW_SRAM2 0x2001C000 0x00004000 { ; 16KB SRAM2
*(.sram2)
}
RW_SRAM3 0x10000000 0x00010000 { ; 64KB CCM RAM
*(.ccmram)
}
}

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@ typedef enum
{
kCanProtocal_None, //使用CAN并机的时候需要将外can协议设置为闲置
kCanProtocal_Bcu,
kCanProtocal_Bcu_invt, //英威腾协议
kCanProtocal_Bcu_Pylon, //pylon协议
kCanProtocal_End,
}CanProtocal;
@ -60,7 +60,8 @@ typedef void (*CanProtocalCall)(can_dev_e can);
CanProtocalCall protocol_can_init_array[kCanProtocal_End] =
{
protocol_can_none_init,
protocol_can_bcu_init,
// protocol_can_bcu_init,
protocol_pylon_can_init,
};
/************************************************modbus*****************************************************/
@ -139,9 +140,9 @@ void protocol_comm_init(void)
for(i = 0; i < kcan_dev_e_End;i++)
{
protocol = get_eeprom_data(kEep_InterCanProtocol_Baudrate + i, kEepromDataType_High);
protocol = get_eeprom_data(kEep_InterCanProtocol_Baudrate, kEepromDataType_High);
//测试
protocol = 1;
//protocol = 1;
if((protocol < kCanProtocal_End) && (protocol_can_init_array[protocol] != NULL))
{
protocol_can_init_array[protocol](i);
@ -192,7 +193,7 @@ static uint32_t inter_modbus_count = 0,inter2_modbus_count = 0,inter3_modbus_cou
void modbus_rtu_inter_handler(uint32_t base_time)
{
inter_modbus_count++;
bsp_modbus_poll(modbus_rtu_array[kModbusIdx_Inter], true);
//bsp_modbus_poll(modbus_rtu_array[kModbusIdx_Inter], true);
}
@ -206,7 +207,7 @@ void modbus_rtu_extern_handler(uint32_t base_time)
void modbus_rtu_externII_handler(uint32_t base_time)
{
inter3_modbus_count++;
bsp_modbus_poll(modbus_rtu_array[kModbusIdx_Exter2], true);
// bsp_modbus_poll(modbus_rtu_array[kModbusIdx_Exter2], true);
}
typedef void (* UintArgCall) (uint32_t arg);

View File

@ -10,6 +10,7 @@ extern "C" {
#include "bsp_modbus.h"
#include "drv_can.h"
#include "fault_manager.h"
typedef void (*CanCommReceive)(CanMsg *msg, can_dev_e can);
@ -29,9 +30,12 @@ void protocol_can_set_call(can_dev_e can, CanCommReceive rx, CanCommSend tx, Can
void protocol_modbus_bcu_init(void * const mb_item,uint16_t addr);
void protocol_modbus_demo(void * const mb_item,uint16_t addr);
void protocol_can_bcu_init(can_dev_e can);
//void protocol_can_bcu_init(can_dev_e can);
void protocol_pylon_can_init(can_dev_e can);
void protocol_can_invt_pcs_init(can_dev_e can);
//根据位,转换告警的位
uint16_t set_bit_based_on_source_pylon(uint8_t status, FaultLevel alarmLevel);
void bms_analyse_model_data(void);
uint16_t bms_read_model_data(uint8_t *buf);

View File

@ -102,11 +102,9 @@ uint16_t bcu_total_msg_fill(uint16_t start_addr, uint8_t reg_num, uint8_t *buf)
READ_FC03_F04_BEGIN();
//1 动力电池组总电压
READ_FC03_F04_ITEM(1, bms_get_statistic_data(kStatisticData_TotalVolt));
//READ_FC03_F04_ITEM(1, 5000);
//READ_FC03_F04_ITEM(1, test99+=10);
//2 动力电池组总电流
READ_FC03_F04_ITEM(2, bms_get_show_current() + 211);
READ_FC03_F04_ITEM(2, bms_get_show_current());
//3 SOC
//READ_FC03_F04_ITEM(3,get_eeprom_data(kEep_SOC,kEepromDataType_Full) / 100);
READ_FC03_F04_ITEM(3, bms_get_soc() / 100);
@ -117,7 +115,7 @@ uint16_t bcu_total_msg_fill(uint16_t start_addr, uint8_t reg_num, uint8_t *buf)
//6 额定总压
READ_FC03_F04_ITEM(6, get_eeprom_data(kEep_RatedTotalVolt,kEepromDataType_Full));
//7 额定容量
READ_FC03_F04_ITEM(7, get_eeprom_data(kEep_RatedCapacity,kEepromDataType_Full));
READ_FC03_F04_ITEM(7, get_eeprom_data(kEep_RatedCapacity,kEepromDataType_Full) );
//8 剩余容量
READ_FC03_F04_ITEM(8, (uint32_t)bms_get_soc()*get_eeprom_data(kEep_RatedCapacity, kEepromDataType_Full)/10000);
//9 额定电量
@ -128,12 +126,14 @@ uint16_t bcu_total_msg_fill(uint16_t start_addr, uint8_t reg_num, uint8_t *buf)
READ_FC03_F04_ITEM(11, bms_get_bmu_num());
//12 在线从机总数
READ_FC03_F04_ITEM(12, bms_get_bmu_online_num());
//13 电池总数
READ_FC03_F04_ITEM(13, get_eeprom_data(kEep_CellNum, kEepromDataType_Full));
//13 电池总数 电芯总数
//READ_FC03_F04_ITEM(13, get_eeprom_data(kEep_CellNum, kEepromDataType_Full));
READ_FC03_F04_ITEM(13, bms_get_cell_num());
//14 在线电池总数
READ_FC03_F04_ITEM(14, bms_get_statistic_data(kStatisticData_OnlineCellNum));
//15 温感总数
READ_FC03_F04_ITEM(15, get_eeprom_data(kEep_TempNum, kEepromDataType_Full));
//READ_FC03_F04_ITEM(15, get_eeprom_data(kEep_TempNum, kEepromDataType_Full));
READ_FC03_F04_ITEM(15, bms_get_temp_num());
//16 在线温感总数
READ_FC03_F04_ITEM(16, bms_get_statistic_data(kStatisticData_OnlineTempNum));
//17 最大允许放电电流
@ -448,8 +448,8 @@ uint16_t bcu_total_cfg_fill(uint16_t start_addr, uint8_t reg_num, uint8_t *buf)
uint16_t address = 0,data = 0;
int32_t year,mon,day,hour,min,sec;
uint32_t addr = 0;
//drv_rtc_get_date(&year, &mon, &day);
//drv_rtc_get_time(&hour, &min, &sec);
drv_rtc_get_date(&year, &mon, &day);
drv_rtc_get_time(&hour, &min, &sec);
for(address = start_addr; address < start_addr + reg_num; address++)
{
@ -714,13 +714,13 @@ uint16_t bcu_total_cfg_fill(uint16_t start_addr, uint8_t reg_num, uint8_t *buf)
case 3146: // 预充超时时间s
data = get_eeprom_data(kEep_PreChgTimeout_Count , (EepromDataType)(1 - (address % 2)));
break;
case 3147: // HV电压比例(%
case 3148: // 预充电压比例(%
case 3147: // 预充电压比例(%
case 3148: // 预充类型
data = get_eeprom_data(kEep_PreChgVoltType_Rate , (EepromDataType)(1 - (address % 2)));
break;
case 3149: // 系统时间s
data = 0;
//drv_rtc_set_tick(bcu_holding_reg.sys_time);
drv_rtc_set_tick(bcu_holding_reg.sys_time);
break;
case 3150: // 系统时间s
data = year;
@ -782,10 +782,10 @@ BspMdExCode bcu_modbus_485_0x03_fun(uint16_t start_addr, uint16_t reg_num, uint8
{
BspMdExCode err = kBspMdEx_None;
//kit_time_dly_ms(50);
if((start_addr >= 3000) && (start_addr + reg_num <= 3169))
{
*len = bcu_total_cfg_fill(start_addr, reg_num, buf);
}
if((start_addr >= 3000) && (start_addr + reg_num <= 3169))
{
*len = bcu_total_cfg_fill(start_addr, reg_num, buf);
}
else if((start_addr >= 4000) && ((start_addr + reg_num ) <= 4999))
{
hmi_fill_modbus_cfg(fill_buf);
@ -834,6 +834,20 @@ BspMdExCode bcu_modbus_485_0x04_fun(uint16_t start_addr, uint16_t reg_num, uint8
}
return err;
}
/*
modbus读取数据接口和读取并发送单个数据到mqtt的代码
3000 3
3010 1
3017 1
3041 1
3068 2
3092 1
3156 1
4000 72
4198 72
+
*/
void bcu_data_set_0x06_msg(uint16_t address,uint16_t data)
{
@ -946,7 +960,7 @@ void bcu_data_set_0x06_msg(uint16_t address,uint16_t data)
break;
case 3041: //SOC设置
bms_set_soc(data);
bsp_eeprom_save_data(kEep_SOC, data,kEepromDataType_Full);
//bsp_eeprom_save_data(kEep_SOC, data,kEepromDataType_Full);
break;
case 3042: //SOE设置 //soc就是soe暂时替换
bms_set_soc(data);
@ -1271,9 +1285,21 @@ BspMdExCode bcu_modbus_485_0x10_fun(uint16_t start_addr, uint16_t reg_num, uint8
bcu_data_set_0x06_msg(start_addr + i, data);
}
}
//@wangk , 2-25, add 0x10function(4000~4449)
else if((start_addr >= 4000) && (start_addr <= 4449))
{
uint16_t *reg_data = (uint16_t *)buf;
for (uint16_t i = 0; i < reg_num; i++)
{
uint16_t reg_value = (reg_data[i] >> 8) | (reg_data[i] << 8);
uint16_t offset_addr = start_addr - 4000 + i;
hmi_write_modbus_cfg(offset_addr, reg_value);
}
}
else
{
err = kBspMdEx_InvalidAddr;
err = kBspMdEx_InvalidAddr;
}
return err;
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,47 @@
/******************************************************************************
* @file protocol_mqtt_bcu.h
* @brief protocol_mqtt_bcu.h
* @version V1.0
* @author Gary
* @copyright
******************************************************************************/
#ifndef PROTOCOL_MQTT_BCU_H_
#define PROTOCOL_MQTT_BCU_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "cJSON.h"
#include "drv_qfc41d.h"
#include "drv_rtc.h"
typedef struct {
const char* key; // JSON 中的键,比如 "BCU_2"
uint8_t groupId; // mqtt因为json长度限制这里面用于分组传输,从0开始
uint16_t input; // get_val的入参用于获取key对应的数据
uint32_t (*get_val)(uint16_t); // 对应值的获取函数
} devPointMap;
typedef struct {
const char* key; // JSON 中的键,比如 "BCU_"后面不带数字数据后面通过BCU_pointId组合
uint16_t pointId; // 用于记录开始的测点号见bcu模型
uint16_t startCellIndex; // 开始的电压序号(入参)
uint16_t endCellIndex; // 结束的电压序号(入参)
uint32_t (*get_val)(uint16_t); // 对应值的获取函数
} devCellPointMap;
extern const devPointMap bms_points[];
extern const devCellPointMap bms_volt_points[];
extern const devCellPointMap bms_temp_points[];
void mqtt_publish_bms_data(uint32_t basetime);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -24,8 +24,6 @@ const uint16_t table_ntc1_CWFH708_H713[BSP_NTC_TABLE_LEN] =
538, 51, 49, 47, 44, 42, 40, 37
};
typedef struct
{
uint16_t rate;

View File

@ -10,14 +10,14 @@
<TargetName>stm32f407</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pArmCC>5060960::V5.06 update 7 (build 960)::.\ARMCC</pArmCC>
<pCCUsed>5060960::V5.06 update 7 (build 960)::.\ARMCC</pCCUsed>
<pArmCC>5050106::V5.05 update 1 (build 106)::ARMCC</pArmCC>
<pCCUsed>5050106::V5.05 update 1 (build 106)::ARMCC</pCCUsed>
<uAC6>0</uAC6>
<TargetOption>
<TargetCommonOption>
<Device>STM32F407ZGTx</Device>
<Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.2.14.0</PackID>
<PackID>Keil.STM32F4xx_DFP.2.16.0</PackID>
<PackURL>http://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000,0x00020000) IRAM2(0x10000000,0x00010000) IROM(0x08000000,0x00100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE</Cpu>
<FlashUtilSpec></FlashUtilSpec>
@ -81,7 +81,7 @@
<nStopB2X>0</nStopB2X>
</BeforeMake>
<AfterMake>
<RunUserProg1>1</RunUserProg1>
<RunUserProg1>0</RunUserProg1>
<RunUserProg2>0</RunUserProg2>
<UserProg1Name>fromelf --m32combined --output=BxE1C_BOOT.s19 .\Objects\BxE1C_BOOT.axf</UserProg1Name>
<UserProg2Name></UserProg2Name>
@ -139,7 +139,7 @@
</Flash1>
<bUseTDR>1</bUseTDR>
<Flash2>BIN\UL2CM3.DLL</Flash2>
<Flash3></Flash3>
<Flash3>"" ()</Flash3>
<Flash4></Flash4>
<pFcarmOut></pFcarmOut>
<pFcarmGrp></pFcarmGrp>
@ -187,6 +187,7 @@
<RvdsVP>2</RvdsVP>
<RvdsMve>0</RvdsMve>
<RvdsCdeCp>0</RvdsCdeCp>
<nBranchProt>0</nBranchProt>
<hadIRAM2>1</hadIRAM2>
<hadIROM2>0</hadIROM2>
<StupSel>8</StupSel>

File diff suppressed because it is too large Load Diff

View File

@ -1,39 +1,45 @@
[BREAKPOINTS]
ForceImpTypeAny = 0
ShowInfoWin = 1
EnableFlashBP = 2
BPDuringExecution = 0
FForceImpTypeAny = 0
ShowInfoWin = 1
EnableFlashBP = 2
BPDuringExecution = 0
orceImpTypeAny = 0
[CFI]
CFISize = 0x00
CFIAddr = 0x00
CCFISize = 0x00
CFIAddr = 0x00
FISize = 0x00
[CPU]
MonModeVTableAddr = 0xFFFFFFFF
MOverrideMemMap = 0
AllowSimulation = 1
ScriptFile=""
onModeVTableAddr = 0xFFFFFFFF
MonModeDebug = 0
MaxNumAPs = 0
LowPowerHandlingMode = 0
OverrideMemMap = 0
AllowSimulation = 1
ScriptFile=""
[FLASH]
CacheExcludeSize = 0x00
CacheExcludeAddr = 0x00
MinNumBytesFlashDL = 0
SkipProgOnCRCMatch = 1
VerifyDownload = 1
AllowCaching = 1
EnableFlashDL = 2
Override = 0
Device="ARM7"
CCacheExcludeSize = 0x00
CacheExcludeAddr = 0x00
MinNumBytesFlashDL = 0
SkipProgOnCRCMatch = 1
VerifyDownload = 1
AllowCaching = 1
EnableFlashDL = 2
Override = 1
Device="Unspecified"
acheExcludeSize = 0x00
[GENERAL]
WorkRAMSize = 0x00
WorkRAMAddr = 0x00
RAMUsageLimit = 0x00
WWorkRAMSize = 0x00
WorkRAMAddr = 0x00
RAMUsageLimit = 0x00
orkRAMSize = 0x00
[SWO]
SWOLogFile=""
SSWOLogFile=""
WOLogFile=""
[MEM]
RdOverrideOrMask = 0x00
RdOverrideAndMask = 0xFFFFFFFF
RdOverrideAddr = 0xFFFFFFFF
WrOverrideOrMask = 0x00
WrOverrideAndMask = 0xFFFFFFFF
WrOverrideAddr = 0xFFFFFFFF
RRdOverrideOrMask = 0x00
RdOverrideAndMask = 0xFFFFFFFF
RdOverrideAddr = 0xFFFFFFFF
WrOverrideOrMask = 0x00
WrOverrideAndMask = 0xFFFFFFFF
WrOverrideAddr = 0xFFFFFFFF
dOverrideOrMask = 0x00

View File

@ -588,8 +588,8 @@ void SystemInit(void)
/* Configure the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings ----------------------------------*/
SetSysClock();
//SystemClock_Config();
//SetSysClock();
SystemClock_Config();
/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */

File diff suppressed because it is too large Load Diff

View File

@ -1,40 +1,45 @@
[BREAKPOINTS]
ForceImpTypeAny = 0
ShowInfoWin = 1
EnableFlashBP = 2
BPDuringExecution = 0
FForceImpTypeAny = 0
ShowInfoWin = 1
EnableFlashBP = 2
BPDuringExecution = 0
orceImpTypeAny = 0
[CFI]
CFISize = 0x00
CFIAddr = 0x00
CCFISize = 0x00
CFIAddr = 0x00
FISize = 0x00
[CPU]
MonModeVTableAddr = 0xFFFFFFFF
MOverrideMemMap = 0
AllowSimulation = 1
ScriptFile=""
onModeVTableAddr = 0xFFFFFFFF
MonModeDebug = 0
MaxNumAPs = 0
LowPowerHandlingMode = 0
OverrideMemMap = 0
AllowSimulation = 1
ScriptFile=""
[FLASH]
EraseType = 0x00
CacheExcludeSize = 0x00
CacheExcludeAddr = 0x00
MinNumBytesFlashDL = 0
SkipProgOnCRCMatch = 1
VerifyDownload = 1
AllowCaching = 1
EnableFlashDL = 2
Override = 0
Device="ARM7"
ECacheExcludeSize = 0x00
CacheExcludeAddr = 0x00
MinNumBytesFlashDL = 0
SkipProgOnCRCMatch = 1
VerifyDownload = 1
AllowCaching = 1
EnableFlashDL = 2
Override = 1
Device="Unspecified"
raseType = 0x00
[GENERAL]
WorkRAMSize = 0x00
WorkRAMAddr = 0x00
RAMUsageLimit = 0x00
WWorkRAMSize = 0x00
WorkRAMAddr = 0x00
RAMUsageLimit = 0x00
orkRAMSize = 0x00
[SWO]
SWOLogFile=""
SSWOLogFile=""
WOLogFile=""
[MEM]
RdOverrideOrMask = 0x00
RdOverrideAndMask = 0xFFFFFFFF
RdOverrideAddr = 0xFFFFFFFF
WrOverrideOrMask = 0x00
WrOverrideAndMask = 0xFFFFFFFF
WrOverrideAddr = 0xFFFFFFFF
RRdOverrideOrMask = 0x00
RdOverrideAndMask = 0xFFFFFFFF
RdOverrideAddr = 0xFFFFFFFF
WrOverrideOrMask = 0x00
WrOverrideAndMask = 0xFFFFFFFF
WrOverrideAddr = 0xFFFFFFFF
dOverrideOrMask = 0x00

File diff suppressed because one or more lines are too long

View File

@ -10,15 +10,15 @@
<TargetName>stm32f407</TargetName>
<ToolsetNumber>0x4</ToolsetNumber>
<ToolsetName>ARM-ADS</ToolsetName>
<pArmCC>5060960::V5.06 update 7 (build 960)::.\ARM_Compiler_5.06u7</pArmCC>
<pCCUsed>5060960::V5.06 update 7 (build 960)::.\ARM_Compiler_5.06u7</pCCUsed>
<pArmCC>5050106::V5.05 update 1 (build 106)::ARMCC</pArmCC>
<pCCUsed>5050106::V5.05 update 1 (build 106)::ARMCC</pCCUsed>
<uAC6>0</uAC6>
<TargetOption>
<TargetCommonOption>
<Device>STM32F407VGTx</Device>
<Vendor>STMicroelectronics</Vendor>
<PackID>Keil.STM32F4xx_DFP.3.0.0</PackID>
<PackURL>https://www.keil.com/pack/</PackURL>
<PackID>Keil.STM32F4xx_DFP.2.16.0</PackID>
<PackURL>http://www.keil.com/pack/</PackURL>
<Cpu>IRAM(0x20000000,0x00020000) IRAM2(0x10000000,0x00010000) IROM(0x08000000,0x00100000) CPUTYPE("Cortex-M4") FPU2 CLOCK(12000000) ELITTLE</Cpu>
<FlashUtilSpec></FlashUtilSpec>
<StartupFile></StartupFile>

View File

@ -56,7 +56,7 @@ const uint8_t PRINT_PEC = DISABLED; //!< This is to ENABLED or DISABLED print
register reads and the array lengths must be based
on the number of ICs on the stack
******************************************************/
cell_asic BMS_IC[TOTAL_IC]; //!< Global Battery Variable
cell_asic BMS_IC[TOTAL_IC] __attribute__((section (".ccmram"))); //!< Global Battery Variable
/*************************************************************************
Set configuration register. Refer to the data sheet

View File

@ -86,7 +86,7 @@ typedef struct
uint16_t * data_buf;
const EepromDataFormat * format;
flash_Item_t *flash;
AreaItem static_area;
AreaItem dynamic_area;
}EEpromItem;

3164
library/cjson/cJSON.c Normal file

File diff suppressed because it is too large Load Diff

306
library/cjson/cJSON.h Normal file
View File

@ -0,0 +1,306 @@
/*
Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#ifndef cJSON__h
#define cJSON__h
#ifdef __cplusplus
extern "C"
{
#endif
#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
#define __WINDOWS__
#endif
#ifdef __WINDOWS__
/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
For *nix builds that support visibility attribute, you can define similar behavior by
setting default visibility to hidden by adding
-fvisibility=hidden (for gcc)
or
-xldscope=hidden (for sun cc)
to CFLAGS
then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
*/
#define CJSON_CDECL __cdecl
#define CJSON_STDCALL __stdcall
/* export symbols by default, this is necessary for copy pasting the C and header file */
#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_EXPORT_SYMBOLS
#endif
#if defined(CJSON_HIDE_SYMBOLS)
#define CJSON_PUBLIC(type) type CJSON_STDCALL
#elif defined(CJSON_EXPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
#elif defined(CJSON_IMPORT_SYMBOLS)
#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
#endif
#else /* !__WINDOWS__ */
#define CJSON_CDECL
#define CJSON_STDCALL
#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
#else
#define CJSON_PUBLIC(type) type
#endif
#endif
/* project version */
#define CJSON_VERSION_MAJOR 1
#define CJSON_VERSION_MINOR 7
#define CJSON_VERSION_PATCH 18
#include <stddef.h>
/* cJSON Types: */
#define cJSON_Invalid (0)
#define cJSON_False (1 << 0)
#define cJSON_True (1 << 1)
#define cJSON_NULL (1 << 2)
#define cJSON_Number (1 << 3)
#define cJSON_String (1 << 4)
#define cJSON_Array (1 << 5)
#define cJSON_Object (1 << 6)
#define cJSON_Raw (1 << 7) /* raw json */
#define cJSON_IsReference 256
#define cJSON_StringIsConst 512
/* The cJSON structure: */
typedef struct cJSON
{
/* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
struct cJSON *next;
struct cJSON *prev;
/* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
struct cJSON *child;
/* The type of the item, as above. */
int type;
/* The item's string, if type==cJSON_String and type == cJSON_Raw */
char *valuestring;
/* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
int valueint;
/* The item's number, if type==cJSON_Number */
double valuedouble;
/* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
char *string;
} cJSON;
typedef struct cJSON_Hooks
{
/* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
void *(CJSON_CDECL *malloc_fn)(size_t sz);
void (CJSON_CDECL *free_fn)(void *ptr);
} cJSON_Hooks;
typedef int cJSON_bool;
/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_NESTING_LIMIT
#define CJSON_NESTING_LIMIT 1000
#endif
/* Limits the length of circular references can be before cJSON rejects to parse them.
* This is to prevent stack overflows. */
#ifndef CJSON_CIRCULAR_LIMIT
#define CJSON_CIRCULAR_LIMIT 10000
#endif
/* returns the version of cJSON as a string */
CJSON_PUBLIC(const char*) cJSON_Version(void);
/* Supply malloc, realloc and free functions to cJSON */
CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLength(const char *value, size_t buffer_length);
/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
CJSON_PUBLIC(cJSON *) cJSON_ParseWithLengthOpts(const char *value, size_t buffer_length, const char **return_parse_end, cJSON_bool require_null_terminated);
/* Render a cJSON entity to text for transfer/storage. */
CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting. */
CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
/* Delete a cJSON entity and all subentities. */
CJSON_PUBLIC(void) cJSON_Delete(cJSON *item);
/* Returns the number of items in an array (or object). */
CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
/* Get item "string" from object. Case insensitive. */
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
/* Check item type and return its value */
CJSON_PUBLIC(char *) cJSON_GetStringValue(const cJSON * const item);
CJSON_PUBLIC(double) cJSON_GetNumberValue(const cJSON * const item);
/* These functions check the type of an item */
CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
/* These calls create a cJSON item of the appropriate type. */
CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
/* raw json */
CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
/* Create a string where valuestring references a string so
* it will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
/* Create an object/array that only references it's elements so
* they will not be freed by cJSON_Delete */
CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
/* These utilities create an Array of count items.
* The parameter count cannot be greater than the number of elements in the number array, otherwise array access will be out of bounds.*/
CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char *const *strings, int count);
/* Append item to the specified array/object. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
* WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
* writing to `item->string` */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
CJSON_PUBLIC(cJSON_bool) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
/* Update array items. */
CJSON_PUBLIC(cJSON_bool) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
/* Duplicate a cJSON item */
CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
* need to be released. With recurse!=0, it will duplicate any children connected to the item.
* The item->next and ->prev pointers are always zero on return from Duplicate. */
/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
* case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
/* Minify a strings, remove blank characters(such as ' ', '\t', '\r', '\n') from strings.
* The input pointer json cannot point to a read-only address area, such as a string constant,
* but should point to a readable and writable address area. */
CJSON_PUBLIC(void) cJSON_Minify(char *json);
/* Helper functions for creating and adding items to an object at the same time.
* They return the added item or NULL on failure. */
CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
/* When assigning an integer value, it needs to be propagated to valuedouble too. */
#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
/* helper for the cJSON_SetNumberValue macro */
CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
/* Change the valuestring of a cJSON_String object, only takes effect when type of object is cJSON_String */
CJSON_PUBLIC(char*) cJSON_SetValuestring(cJSON *object, const char *valuestring);
/* If the object is not a boolean type this does nothing and returns cJSON_Invalid else it returns the new type*/
#define cJSON_SetBoolValue(object, boolValue) ( \
(object != NULL && ((object)->type & (cJSON_False|cJSON_True))) ? \
(object)->type=((object)->type &(~(cJSON_False|cJSON_True)))|((boolValue)?cJSON_True:cJSON_False) : \
cJSON_Invalid\
)
/* Macro for iterating over an array or object */
#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
CJSON_PUBLIC(void) cJSON_free(void *object);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -39,7 +39,7 @@
; <o> Stack Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Stack_Size EQU 0x00000400
Stack_Size EQU 0x00001000
AREA STACK, NOINIT, READWRITE, ALIGN=3
Stack_Mem SPACE Stack_Size
@ -50,7 +50,7 @@ __initial_sp
; <o> Heap Size (in Bytes) <0x0-0xFFFFFFFF:8>
; </h>
Heap_Size EQU 0x00000400
Heap_Size EQU 0x00002000
AREA HEAP, NOINIT, READWRITE, ALIGN=3
__heap_base

View File

@ -518,8 +518,8 @@ void SystemInit(void)
/* Configure the System clock source, PLL Multiplier and Divider factors,
AHB/APBx prescalers and Flash settings ----------------------------------*/
//SetSysClock();
SystemClock_Config();
SetSysClock();
//SystemClock_Config();
/* Configure the Vector Table location add offset address ------------------*/
#ifdef VECT_TAB_SRAM
@ -573,6 +573,7 @@ void SystemCoreClockUpdate(void)
#endif /* STM32F412xG || STM32F413_423xx || STM32F446xx */
/* Get SYSCLK source -------------------------------------------------------*/
tmp = RCC->CFGR & RCC_CFGR_SWS;
//tmp = RCC_CFGR_SWS_HSE;
switch (tmp)
{
@ -711,7 +712,7 @@ void SystemClock_Config(void)
RCC->CFGR |= RCC_CFGR_PPRE2_DIV2;
/* PCLK1 = HCLK / 4 */
RCC->CFGR |= RCC_CFGR_PPRE1_DIV4;
RCC->CFGR |= RCC_CFGR_PPRE1_DIV8;
/* Configure the main PLL for 168 MHz using HSI */
RCC->PLLCFGR = (16 << 0) // PLL_M = 16 (HSI = 16 MHz input for PLL)

View File

@ -611,6 +611,72 @@ int8_t parse_cells(uint8_t current_ic, // Current IC
return (pec_error);
}
/* Helper function that parses voltage measurement registers */
int8_t drv_parse_temp_data(uint8_t current_ic, // Current IC
uint8_t cell_reg, // Type of register
uint8_t cell_data[], // Unparsed data
uint16_t *cell_codes, // Parsed data
uint8_t *ic_pec // PEC error
)
{
uint8_t BYT_IN_REG = 6;
uint8_t CELL_IN_REG = 3;
int8_t pec_error = 0;
uint16_t parsed_cell;
uint16_t received_pec;
uint16_t data_pec;
uint8_t data_counter = current_ic * NUM_RX_BYT; // data counter
for (uint8_t current_cell = 0; current_cell < CELL_IN_REG; current_cell++) // This loop parses the read back data into the register codes, it
{ // loops once for each of the 3 codes in the register
parsed_cell = cell_data[data_counter] + (cell_data[data_counter + 1] << 8); // Each code is received as two bytes and is combined to
// create the parsed code
if(cell_reg == 1)
{
cell_codes[current_cell + ((cell_reg - 1) * CELL_IN_REG)] = parsed_cell;
}
else if(cell_reg == 2)
{
if(current_cell < 2)
{
cell_codes[current_cell + 3] = parsed_cell;
}
}
else if(cell_reg == 3)
{
cell_codes[current_cell + 5] = parsed_cell;
}
else if(cell_reg == 4)
{
if(current_cell < 1)
{
cell_codes[current_cell + 8] = parsed_cell;
}
}
data_counter = data_counter + 2; // Because the codes are two bytes, the data counter
// must increment by two for each parsed code
}
received_pec = (cell_data[data_counter] << 8) | cell_data[data_counter + 1]; // The received PEC for the current_ic is transmitted as the 7th and 8th
// after the 6 cell voltage data bytes
data_pec = pec15_calc(BYT_IN_REG, &cell_data[(current_ic)*NUM_RX_BYT]);
if (received_pec != data_pec)
{
pec_error = 1; // The pec_error variable is simply set negative if any PEC errors
ic_pec[cell_reg - 1] = 1;
}
else
{
ic_pec[cell_reg - 1] = 0;
}
data_counter = data_counter + 2;
return (pec_error);
}
/*Reads and parses the ADBMS181x cell voltage registers.
The function is used to read the parsed Cell voltages codes of the ADBMS181x.
This function will send the requested read commands parse the data
@ -767,7 +833,7 @@ int8_t ADBMS1818_rdaux(uint8_t reg, // Determines which GPIO voltage register
{
c_ic = total_ic - current_ic - 1;
}
pec_error = parse_cells(current_ic, gpio_reg, data,
pec_error = drv_parse_temp_data(current_ic, gpio_reg, data,
&ic[c_ic].aux.a_codes[0],
&ic[c_ic].aux.pec_match[0]);
}
@ -787,7 +853,7 @@ int8_t ADBMS1818_rdaux(uint8_t reg, // Determines which GPIO voltage register
{
c_ic = total_ic - current_ic - 1;
}
pec_error = parse_cells(current_ic, reg, data,
pec_error = drv_parse_temp_data(current_ic, reg, data,
&ic[c_ic].aux.a_codes[0],
&ic[c_ic].aux.pec_match[0]);
}

View File

@ -28,40 +28,67 @@ uint8_t drv_ads8688_spi_send_rev(uint8_t data)
// 返回TURE则说明初始化正常否则错误
bool drv_ads8688_Init(void)
{
uint8_t i = 0;
uint8_t i = 0, value = 0;
drv_spi_init(kSpiDev_2, kSpiFreq_Div256, kSpiMode_C0E1, SpiFrame_MSBFirst, kGpioType_ADC_Clk, kGpioType_ADC_Miso, kGpioType_ADC_Mosi);
//drv_ads8688_Reset();// hardware reset
drv_enter_pwrdn_mode();
OSTimeDly(20);
drv_reset_ads8688();
kit_time_dly_ms(20);
drv_enter_standby_mode();
OSTimeDly(20);
drv_reset_ads8688();
OSTimeDly(20);
drv_set_ch_range(Channel_0_Input_Range,VREF_25_25);
drv_set_ch_range(Channel_1_Input_Range,VREF_25_25);
drv_set_ch_range(Channel_2_Input_Range,VREF_25_25);
drv_set_ch_range(Channel_3_Input_Range,VREF_25_25);
drv_set_ch_range(Channel_4_Input_Range,VREF_25_25);
drv_set_ch_range(Channel_5_Input_Range,VREF_25_25);
kit_time_dly_ms(20);
drv_set_ch_pwrdn(Channel_6_Input_Range);
drv_set_ch_pwrdn(Channel_7_Input_Range);
//drv_enter_pwrdn_mode();
//OSTimeDly(20);
drv_ads8688_write_reg(AUTO_SEQ_EN, 0x3F);
drv_ads8688_write_reg(AUTO_SEQ_EN, 0xFF);
kit_time_dly_ms(10);
i = drv_ads8688_read_reg(AUTO_SEQ_EN);
drv_ads8688_write_reg(Feature_Select, 0x28);
kit_time_dly_ms(20);
if (i != 0x3F)
{
return true;
}
else
{
drv_enter_auto_rst_mode(); // ½øÈë×Ô¶¯É¨Ãèģʽ
OSTimeDly(20);
return false;
}
drv_set_ch_range(Channel_0_Input_Range,VREF_125_125);
drv_set_ch_range(Channel_1_Input_Range,VREF_125_125);
drv_set_ch_range(Channel_2_Input_Range,VREF_0625_0625);
drv_set_ch_range(Channel_3_Input_Range,VREF_125_125);
drv_set_ch_range(Channel_4_Input_Range,VREF_125_125);
drv_set_ch_range(Channel_5_Input_Range,VREF_125_125);
drv_set_ch_range(Channel_6_Input_Range,VREF_125_125);
drv_set_ch_range(Channel_7_Input_Range,VREF_125_125);
//value = drv_ads8688_read_reg(Channel_0_Input_Range);
drv_set_ch_pwrdn(0xC0);
//
#if ADC_AUTO_MODE
{
drv_ads8688_write_reg(AUTO_SEQ_EN, 0x3F);
i = drv_ads8688_read_reg(AUTO_SEQ_EN);
if (i != 0x3F)
{
return true;
}
else
{
drv_enter_auto_rst_mode(); // ½øÈë×Ô¶¯É¨Ãèģʽ
OSTimeDly(20);
return false;
}
}
#else
{
drv_manual_chn_mode(MAN_Ch_0);
drv_manual_chn_mode(MAN_Ch_1);
drv_manual_chn_mode(MAN_Ch_2);
drv_manual_chn_mode(MAN_Ch_3);
drv_manual_chn_mode(MAN_Ch_4);
drv_manual_chn_mode(MAN_Ch_5);
return false;
}
#endif
}
void drv_ads8688_Reset(void) // hardware reset
@ -107,7 +134,8 @@ void drv_reset_ads8688(void) //
// 退出此模式需执行AUTO_RST或者MAN_CH_n命令且需要等待至少20us以保证正常数据的AD转换
void drv_enter_standby_mode(void)
{
drv_ads8688_write_cmd_reg(STDBY);
//drv_ads8688_write_cmd_reg(STDBY);
drv_ads8688_write_cmd_reg(NO_OP);
}
// 进入PWR_DN模式且命令发送后CS立刻置高不读数据帧
@ -156,7 +184,7 @@ uint16_t drv_manual_chn_mode_Data(void)
datah = drv_ads8688_spi_send_rev(0xFF);
datal = drv_ads8688_spi_send_rev(0xFF);
drv_set_ads8688_cs(kGpioStatus_High);
kit_time_dly_ms(10);
return (datah << 8 | datal);
}
@ -177,17 +205,16 @@ void drv_ads8688_write_reg(uint8_t Addr, uint8_t data)
}
// Program Register读操作
uint8_t drv_ads8688_read_reg(uint8_t Addr)
uint16_t drv_ads8688_read_reg(uint8_t Addr)
{
uint8_t data = 0;
uint8_t datah = 0,datal = 0;
drv_set_ads8688_cs(kGpioStatus_Low);
drv_ads8688_spi_send_rev(Addr << 1 | READ);
data = drv_ads8688_spi_send_rev(0xFF);
data = drv_ads8688_spi_send_rev(0xFF);
datah = drv_ads8688_spi_send_rev(0xFF);
datal = drv_ads8688_spi_send_rev(0xFF);
drv_set_ads8688_cs(kGpioStatus_High);
return data;
return datal + (datah << 8);
}
void drv_set_auto_scan_sequence(uint8_t seq) // 设置自动扫描序列通道
@ -198,11 +225,13 @@ void drv_set_auto_scan_sequence(uint8_t seq) //
void drv_set_ch_pwrdn(uint8_t chn) // 设置通道n为Power Down
{
drv_ads8688_write_reg(0X02, chn);
}
void drv_set_ch_range(uint8_t ch, uint8_t range) // 设置各个通道的范围
{
drv_ads8688_write_reg(ch, range);
kit_time_dly_ms(20);
}
int16_t drv_ads8688_value(uint16_t value)

View File

@ -84,7 +84,8 @@ kGpioType_ADC_Cs
#define VREF_0_25 0X05
#define VREF_0_125 0X06
typedef struct
#define ADC_AUTO_MODE 0
typedef struct
{
uint8_t cs;
SpiDev spi;
@ -112,7 +113,7 @@ void drv_enter_auto_rst_mode(void);
void drv_enter_auto_rst_mode_Data(uint16_t* outputdata, uint8_t chnum);
void drv_ads8688_write_reg(uint8_t Addr,uint8_t data);
uint8_t drv_ads8688_read_reg(uint8_t Addr);
uint16_t drv_ads8688_read_reg(uint8_t Addr);
void drv_set_auto_scan_sequence(uint8_t seq);
void drv_set_ch_pwrdn(uint8_t chn);
void drv_set_ch_range(uint8_t ch,uint8_t range);

View File

@ -0,0 +1,190 @@
/******************************************************************************
* @file drv_eg25gminipice.c
* @brief drv_eg25gminipice.c drivers
* @version V1.0
* @author Gary
* @copyright
******************************************************************************/
#include "drv_eg25gminipice.h"
#define UART2_BAUDRATE 115200
#define MAX_RETRY 3
//4G实例化
static uint8_t sim_rec_buf[MAX_RECV_LEN] = {0};
LTE4G_STATIC_INIT(sim_item, 1, 0, 0, 1024,sim_rec_buf);
void drv_sim_push_data(Lte4GItem* item, uint8_t *buf, uint16_t len)
{
uint16_t i = 0;
if((item != NULL) && (item->buf_pos + len < item->buf_size))
{
for (i = 0; i < len; i++)
{
item->buf[item->buf_pos++] = buf[i];
}
}
}
void drv_uart2_Init(void)
{
RCC->APB1ENR |= RCC_APB1ENR_USART2EN; // 使能 USART2 时钟
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; // 使能 GPIOA 时钟
GPIOA->MODER |= (2 << (2 * 2)) | (2 << (3 * 2)); // PA2(TX), PA3(RX) 复用模式
GPIOA->AFR[0] |= (7 << (2 * 4)) | (7 << (3 * 4)); // 复用 AF7 (USART2)
USART2->BRR = SystemCoreClock / UART2_BAUDRATE;
USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_UE; // 使能串口、发送和接收
}
void drv_uart2_sendbyte(char c)
{
while (!(USART2->SR & USART_SR_TXE)); // 等待发送完成
USART2->DR = c;
}
void drv_uart2_sendString(const char *str)
{
while (*str) {
drv_uart2_sendbyte(*str++);
}
}
void drv_send_at_cmd(const char *cmd, int delay_ms)
{
drv_uart2_sendString(cmd);
drv_uart2_sendString("\r\n"); // AT 指令以 "\r\n" 结尾
kit_time_dly_ms(30);
}
void drv_eg25g_init(void)
{
drv_send_at_cmd("AT", 500); // 1. 测试 AT 指令
drv_send_at_cmd("AT+CPIN?", 500); // 2. 查询 SIM 卡状态
drv_send_at_cmd("AT+COPS=0", 500); // 3. 让模块自动选择运营商
drv_send_at_cmd("AT+CEREG?", 1000); // 4. 查询 4G 注册状态
// drv_send_at_cmd("AT+CGDCONT=1,\"IP\",\"your_apn\"", 500); // 5. 设置 APN 如果支持自动识别则不需要设置apn
drv_send_at_cmd("AT+CGACT=1,1", 1000); // 6. 激活 PDP获取 IP
drv_send_at_cmd("AT+CGPADDR=1", 500); // 7. 查询分配的 IP 地址
}
// 发送 AT 指令并等待返回值,可用于此优化初始化函数
int drv_send_at_cmd2(const char *cmd, int delay_ms)
{
for (int i = 0; i < MAX_RETRY; i++) // 失败最多重试 MAX_RETRY 次
{
drv_uart2_sendString(cmd);
drv_uart2_sendString("\r\n"); // AT 指令以 "\r\n" 结尾
kit_time_dly_ms(30);
if (sim_item.buf_pos > 0 && strstr((const char*)sim_item.buf, "OK")) // 解析返回值
{
return 1; // 成功
}
}
return 0; // 失败
}
void drv_eg25g_init2(void)
{
if (!drv_send_at_cmd2("AT", 500)) return; // 1. 测试 AT 指令
if (!drv_send_at_cmd2("AT+CPIN?", 500)) return; // 2. 查询 SIM 卡状态
if (!drv_send_at_cmd2("AT+COPS=0", 500)) return; // 3. 让模块自动选择运营商
if (!drv_send_at_cmd2("AT+CEREG?", 1000)) return; // 4. 查询 4G 注册状态
if (!drv_send_at_cmd2("AT+CGDCONT=1,\"IP\",\"your_apn\"", 500)) return; // 5. 设置 APN
if (!drv_send_at_cmd2("AT+CGACT=1,1", 1000)) return; // 6. 激活 PDP获取 IP
if (!drv_send_at_cmd2("AT+CGPADDR=1", 500)) return; // 7. 查询分配的 IP 地址
}
#define MQTT_BROKER "47.120.14.45" // 你的 MQTT 服务器地址
#define MQTT_PORT 3011 // MQTT 端口
#define MQTT_CLIENT_ID "fc41d_client" // 客户端 ID
#define MQTT_USER "user" // MQTT 用户名
#define MQTT_PASSWORD "password" // MQTT 密码
#define MQTT_TOPIC "bluesun/bms/period/11223344" // 订阅/发布的主题
#define MQTT_MESSAGE "Hello from FC41D!" // 发送的消息
#define WIFI_TIMEOUT 1000
// 连接 MQTT 服务器
uint8_t drv_mqtt_connect()
{
//1、设置 MQTT 协议的版本号为 V4
// snprintf(cmd, sizeof(cmd), "AT+QMTCFG=\"version\",1,4");
// if (!drv_at_send_cmd(cmd, "OK", WIFI_TIMEOUT))
// {
// KIT_PRINTF("Failed to set MQTT server!\r\n");
// return 1;
// }
//2、建立 MQTT 客户端与服务器之间的会话连接
char cmd[100] = {0};
snprintf(cmd, sizeof(cmd), "AT+QMTOPEN=0,\"%s\",%d",MQTT_BROKER,MQTT_PORT);
if (!drv_at_send_cmd(cmd, "OK", WIFI_TIMEOUT))
{
// KIT_PRINTF("Failed to set MQTT server!\r\n");
return 1;
}
//2、MQTT 客户端与服务器之间建立 MQTT 连接 AT+QMTCONN=<clientID>,<client_identity>,<username>,<password>
//snprintf(cmd, sizeof(cmd), "AT+QMTCONN=0,%s,%s,%s",MQTT_CLIENT_ID,MQTT_USER, MQTT_PASSWORD);
if (!drv_at_send_cmd("AT+QMTCONN=0,\"clientBCUwifi11223344\"", "OK", WIFI_TIMEOUT))
{
// KIT_PRINTF("Failed to set MQTT client credentials!\r\n");
}
if (!drv_at_send_cmd("AT+QMTSUB=0,1,\"bluesun/bms/control/11223344\",0,\"bluesun/bms/read/11223344\",0", "OK", WIFI_TIMEOUT))
{
// KIT_PRINTF("Failed to set MQTT client credentials!\r\n");
}
//
// if (!drv_at_send_cmd("AT+QMTSUB=1,1,\"bluesun/bms/read/11223344\",0,\"bluesun/bms/control/11223344\",0", "OK", WIFI_TIMEOUT))
// {
//// KIT_PRINTF("Failed to set MQTT client credentials!\r\n");
// }
// KIT_PRINTF("MQTT Connection Successful!\r\n");
return 0;
}
//void drv_mqtt_connect(void)
//{
//// drv_send_at_cmd("AT+QMTCFG=\"recv/mode\",0,0,1", 500);
// drv_send_at_cmd("AT+QMTOPEN=0,\"47.120.14.45\",3011", 5000);
// drv_send_at_cmd("AT+QMTCONN=0,\"clientBCUwifi01\"", 5000);
// drv_send_at_cmd("AT+QMTSUB=0,1,\"BCU01\",2", 5000);
//}
/*
void drv_mqtt_publish(const char *topic, const char *message)
{
char cmd[128];
sprintf(cmd, "AT+QMTPUB=0,0,0,0,\"%s\",\"%s\"", topic, message);
drv_send_at_cmd(cmd, 500);
}
*/
/*
int main(void) {
SystemInit();
drv_uart2_Init();
drv_eg25g_init();
drv_mqtt_connect();
while (1)
{
drv_mqtt_publish("sensor/data", "{\"temperature\":25.3}");
for (volatile int i = 0; i < 10000000; i++); // 发送间隔
}
}
*/

View File

@ -0,0 +1,61 @@
/******************************************************************************
* @file drv_eg25gminipice.h
* @brief drv_eg25gminipice drivers
* @version V1.0
* @author Gary
* @copyright
******************************************************************************/
#ifndef DRV_EG25GMINIPICE_H_
#define DRV_EG25GMINIPICE_H_
#include "drv_gpio.h"
#include "stm32f4xx.h"
#include "bsp_task.h"
#include "kit_time.h"
#include "kit_data.h"
#include "kit_debug.h"
#include "ucos_ii.h"
#include "string.h"
#define MAX_RECV_LEN 1024
//¶¨ÒåÄ£×é4G½á¹¹
typedef struct _Lte4GItem
{
uint8_t addr;
uint8_t comm_dev;
uint16_t buf_pos;
uint16_t buf_size;
uint8_t *buf;
} Lte4GItem;
#define LTE4G_STATIC_INIT(_name, _addr, _comm_dev, _buf_pos, _buf_size,_recv) \
Lte4GItem _name = \
{ \
(_addr), \
(_comm_dev), \
(_buf_pos),\
(_buf_size),\
(_recv),\
}
extern Lte4GItem sim_item;
void drv_uart2_Init(void);
void drv_uart2_sendbyte(char c);
void drv_uart2_sendString(const char *str);
void drv_send_at_cmd(const char *cmd, int delay_ms);
void drv_eg25g_init(void);
uint8_t drv_mqtt_connect();
//void drv_mqtt_publish(const char *topic, const char *message);
void drv_sim_push_data(Lte4GItem* item, uint8_t *buf, uint16_t len);
#endif //DRV_EG25GMINIPICE_H_

View File

@ -0,0 +1,439 @@
/******************************************************************************
* @file drv_qfc41d.c
* @brief drv_qfc41d driver
* @version V1.0
* @author Gary
* @copyright
******************************************************************************/
#include "drv_qfc41d.h"
#include "eeprom_manager.h"
uint8_t rev_buff[QFC41D_MAX_RECV_SIZE] __attribute__((section(".ccmram")));
uint8_t send_buff[QFC41D_MAX_SEND_SIZE]__attribute__((section(".ccmram")));
#define MAX_PAYLOAD_LEN 128
char cmd[1000] = {0}; //降低栈空间使用
#define TX_DMA_BUFFER_SIZE 2000
volatile uint8_t dma_tx_busy = 0;
uint8_t dma_tx_buffer[2][TX_DMA_BUFFER_SIZE] __attribute__((section(".sram2")));
volatile uint8_t current_buffer = 0; // 0表示正常缓冲区1表示高优先级缓冲区
//定义
WifiBleItem qfc41dItem = {
.dev = QFC41D_UART_PORT,
.buf_pos = 0,
.buf_size = QFC41D_MAX_RECV_SIZE,
.buf = rev_buff,
.sendCall = NULL,
};
typedef struct {
uint16_t start_addr;
uint16_t reg_num;
} RegSegment;
RegSegment segments[] = {
{3000, 3}, //BMU个数电芯总数温感总数
{3010, 1}, //Can通讯协议
{3017, 1}, //设备地址
{3041, 1}, //SOC
{3068, 2}, //SOC满放校准电压满充校准电压
{3092, 1}, //充电末端降流电压
{4000, 72}, //放电欠压值
{4198, 72} //充电过压值
};
const uint8_t segment_count = sizeof(segments) / sizeof(segments[0]);
void parse_mqtt_message(char* message)
{
// +QMTRECV: 0,31,"bluesun/bms/control/123",11,"MQ3156+1MQ"
uint16_t first = 0;
uint16_t second = 0;
uint8_t buffer[5];
uint16_t length;
uint8_t data = 0;
char data_str[6] = {0};
char* quotes[4] = {0};
int quote_count = 0;
for(char* p = message; *p && quote_count < 4; p++)
{
if(*p == '\"')
{
quotes[quote_count++] = p;
}
}
if(quote_count < 4)
{
return;
}
char* payload_start = quotes[2] + 1;
char* payload_end = quotes[3];
size_t payload_len = payload_end - payload_start;
if(payload_len >= MAX_PAYLOAD_LEN)
{
return;
}
char payload[MAX_PAYLOAD_LEN];
strncpy(payload, payload_start, payload_len);
payload[payload_len] = '\0';
char* processed = payload;
size_t len = strlen(processed);
// 去除开头"MQ"
if(len >= 2 && strncmp(processed, "MQ", 2) == 0)
{
processed += 2;
len -= 2;
}
// 去除结尾"MQ"
if(len >= 2 && strcmp(processed + len - 2, "MQ") == 0)
{
processed[len - 2] = '\0';
len -= 2;
}
char* plus_pos = strchr(processed, '+');
if(!plus_pos)
{
return;
}
*plus_pos = '\0';
first = atoi(processed);
second = atoi(plus_pos + 1);
if(strstr(message, "control") != NULL)
{
buffer[0] = (second >> 8) & 0xFF;
buffer[1] = second & 0xFF;
if (first == 3156 && second == 1)
{
bms_soft_reset_save(kSoftReset_CmdCtrl, NULL, 0);
drv_misc_reset_mcu();
}
else
{
data = bcu_modbus_485_0x06_fun(first, 1, buffer, &length);
}
if (data == 0)
{
drv_mqtt_publish_control_no_respose("ok", 2);
}
}
else if (strstr(message, "read") != NULL)
{
char data_str[650] = {0};
uint8_t is_first_data = 1; // 标记是否为第一个数据
uint8_t read_success = 1;
for (uint8_t i = 0; i < segment_count; i++)
{
uint16_t start_addr = segments[i].start_addr;
uint16_t reg_num = segments[i].reg_num;
uint16_t length = 0;
uint8_t read_buffer[150] = {0};
uint8_t err = bcu_modbus_485_0x03_fun(start_addr, reg_num, read_buffer, &length);
if (err != 0 || length != (reg_num << 1))
{
read_success = 0;
break;
}
for (uint16_t j = 0; j < reg_num; j++)
{
uint16_t value = (read_buffer[j * 2] << 8) | read_buffer[j * 2 + 1];
if (!is_first_data)
{
strcat(data_str, "+");
}
else
{
is_first_data = 0;
}
char val_str[6];
snprintf(val_str, sizeof(val_str), "%u", value);
strcat(data_str, val_str);
}
}
if (read_success && strlen(data_str) > 0)
{
drv_mqtt_publish_read_no_respose(data_str, strlen(data_str));
}
}
}
static void drv_qfc41d_push_data(WifiBleItem* item, uint8_t *buf, uint16_t len)
{
uint16_t i = 0;
if((item != NULL) && (item->buf_pos + len < item->buf_size))
{
item->buf[item->buf_pos++] = buf[i];
// 处理换行符,表示一条完整的 AT 指令返回
if (buf[i] == '\n')
{
item->buf[item->buf_pos] = '\0'; // 添加结束符
if (item->buf_pos < 100)
{
parse_mqtt_message(item->buf); // 解析消息
}
item->buf_pos = 0; // 重置索引,准备下一条数据
}
}
}
static void drv_qf41d_uart_rx_it_call(kit_ret_e res, void *data)
{
OS_TRACE_ISR_ENTER();
drv_qfc41d_push_data(&qfc41dItem, data, 1);
OS_TRACE_ISR_EXIT();
}
// 发送单个字符
void drv_wireless_send_char(char c)
{
while (!(USART2->SR & USART_SR_TXE)); // 等待发送缓冲区空
USART2->DR = c;
}
// 发送字符串
void drv_wireless_send_string(const char *str)
{
while (*str)
{
drv_wireless_send_char(*str++);
}
drv_wireless_send_char('\r'); // 发送 CR
drv_wireless_send_char('\n'); // 发送 LF
}
void drv_wireless_send_string_dma_high_priority(const char *str)
{
uint32_t start_time = kit_time_get_tick();
while (dma_tx_busy && current_buffer == 0)
{
if (kit_time_get_tick() - start_time > 180)
{
__disable_irq();
if (DMA1_Stream6->CR & DMA_SxCR_EN)
{
DMA1_Stream6->CR &= ~DMA_SxCR_EN;
while (DMA1_Stream6->CR & DMA_SxCR_EN);
DMA1->HIFCR |= DMA_HIFCR_CTCIF6 | DMA_HIFCR_CTEIF6;
}
dma_tx_busy = 0;
current_buffer = 0;
USART2->CR3 &= ~USART_CR3_DMAT;
__enable_irq();
break;
}
}
uint16_t len = 0;
while (*str && len < TX_DMA_BUFFER_SIZE - 2)
{
dma_tx_buffer[1][len++] = *str++;
}
dma_tx_buffer[1][len++] = '\r';
dma_tx_buffer[1][len++] = '\n';
__disable_irq();
// 确保DMA已停止
DMA1_Stream6->CR &= ~DMA_SxCR_EN;
while (DMA1_Stream6->CR & DMA_SxCR_EN);
DMA1_Stream6->M0AR = (uint32_t)dma_tx_buffer[1];
DMA1_Stream6->NDTR = len;
dma_tx_busy = 1;
current_buffer = 1;
DMA1_Stream6->CR |= DMA_SxCR_EN;
USART2->CR3 |= USART_CR3_DMAT;
__enable_irq();
}
void drv_wireless_send_string_dma(const char *str)
{
__disable_irq();
if (dma_tx_busy || current_buffer == 1)
{
__enable_irq();
return;
}
__enable_irq();
bsp_task_delay_ms(250);
uint16_t len = 0;
while (*str && len < TX_DMA_BUFFER_SIZE - 2)
{
dma_tx_buffer[0][len++] = *str++;
}
dma_tx_buffer[0][len++] = '\r';
dma_tx_buffer[0][len++] = '\n';
__disable_irq();
if (dma_tx_busy || current_buffer == 1)
{
__enable_irq();
return;
}
DMA1_Stream6->CR &= ~DMA_SxCR_EN;
while (DMA1_Stream6->CR & DMA_SxCR_EN);
DMA1_Stream6->M0AR = (uint32_t)dma_tx_buffer[0];
DMA1_Stream6->NDTR = len;
dma_tx_busy = 1;
current_buffer = 0;
DMA1_Stream6->CR |= DMA_SxCR_EN;
USART2->CR3 |= USART_CR3_DMAT;
__enable_irq();
}
// 发送 AT 指令并等待返回值
int drv_at_send_cmd(const char *cmd, const char *response, uint32_t timeout)
{
memset(qfc41dItem.buf, 0, QFC41D_MAX_RECV_SIZE);
qfc41dItem.buf_pos = 0; // 清空接收缓冲区索引
drv_wireless_send_string(cmd);
uint32_t start_time = kit_time_get_tick(); // 获取当前时间
while (kit_time_get_tick() - start_time < timeout)
{
if (strstr((char *)qfc41dItem.buf, response))
{
return 1; // 成功匹配返回值
}
}
return 0; // 超时未收到期望数据
}
static uint8_t drv_wifi_init()
{
if (!drv_at_send_cmd("AT", "OK", WIFI_TIMEOUT))
{
return 1 ;
}
if (!drv_at_send_cmd("AT+QSTASTOP", "OK", WIFI_TIMEOUT))
{
return 1;
}
if (!drv_at_send_cmd("AT+QSOFTAPSTOP", "OK", WIFI_TIMEOUT))
{
return 1;
}
return 0;
}
uint8_t drv_ble_init()
{
if (!drv_at_send_cmd("AT+QBLEINIT=3", "OK", WIFI_TIMEOUT))
{
return 1;
}
//设置wifi名称必须以BSM开头后缀可以加sn码
if (!drv_at_send_cmd("AT+QBLENAME=BSM11223344", "OK", WIFI_TIMEOUT))
{
return 1;
}
return 0;
}
uint8_t drv_qfc41d_init(void)
{
//初始化串口
drv_uart_init((UartDev)qfc41dItem.dev, 115200, 0 | UART_CFG_STOP_BIT_1, kGpioType_WIRELESSUart_Tx, kGpioType_WIRELESSUart_Rx);
USART2->CR1 = USART_CR1_TE | USART_CR1_RE | USART_CR1_RXNEIE | USART_CR1_UE;
//设置接收回调函数
drv_uart_set_interrupt(QFC41D_UART_PORT, kUartInterrupt_Rx, APP_CFG_INT_PRIO_UART2_RX, drv_qf41d_uart_rx_it_call);//#define SIM_UART_PORT kUartDev_2
//初始化蓝牙BLE
if (drv_ble_init() != 0)
{
return 1;
}
return 0;
}
#define MQTT_BROKER "47.120.14.45" // 你的 MQTT 服务器地址
#define MQTT_PORT 3011 // MQTT 端口
#define MQTT_CLIENT_ID "fc41d_client" // 客户端 ID
#define MQTT_USER "user" // MQTT 用户名
#define MQTT_PASSWORD "password" // MQTT 密码
#define MQTT_TOPIC "bluesun/bms/period/11223344"
#define MQTT_TOPIC_control "bluesun/bms/control/reply/11223344"
#define MQTT_TOPIC_read "bluesun/bms/read/reply/11223344"
static uint8_t drv_mqtt_subscribe()
{
snprintf(cmd, sizeof(cmd), "AT+MQTTSUB=0,1,\"%s\",2", MQTT_TOPIC);
drv_wireless_send_string(cmd);
return 0;
}
uint8_t drv_mqtt_publish(char* str,uint16_t length)
{
snprintf(cmd, sizeof(cmd), "AT+QMTPUB=1,1,2,0,%s,%d,%s",MQTT_TOPIC, length, str);
if (!drv_at_send_cmd(cmd, "OK\0", WIFI_TIMEOUT))
{
return 1;
}
return 0;
}
uint8_t drv_mqtt_publish_no_respose(char* str,uint16_t length)
{
// snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,%s,%d,%s",MQTT_TOPIC, length, str);
snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,\"%s\",%d,\"%s\"", MQTT_TOPIC, length, str);
// drv_wireless_send_string(cmd); // 未使用DMA
drv_wireless_send_string_dma(cmd); // 使用DMA
return 0;
}
uint8_t drv_mqtt_publish_control_no_respose(char* str,uint16_t length)
{
snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,\"%s\",%d,\"%s\"", MQTT_TOPIC_control, length, str);
drv_wireless_send_string_dma_high_priority(cmd);
return 0;
}
uint8_t drv_mqtt_publish_read_no_respose(char* str,uint16_t length)
{
snprintf(cmd, sizeof(cmd), "AT+QMTPUB=0,1,2,0,\"%s\",%d,\"%s\"", MQTT_TOPIC_read, length, str);
drv_wireless_send_string_dma_high_priority(cmd);
return 0;
}

View File

@ -0,0 +1,78 @@
/******************************************************************************
* @file drv_qfc41d.h
* @brief drv_qfc41d.h
* @version V1.0
* @author Gary
* @copyright
******************************************************************************/
#ifndef DRV_QFC41D_H_
#define DRV_QFC41D_H_
#include <stdio.h>
#include <stdint.h>
#include <stm32f4xx.h>
#include <string.h>
#include "drv_uart.h"
#include "kit_macro.h"
#include "ucos_ii.h"
#include "gpio_manager.h"
#include "kit_time.h"
#include "kit_debug.h"
#define QFC41D_UART_PORT kUartDev_2
#define QFC41D_MAX_SEND_SIZE 2048
#define QFC41D_MAX_RECV_SIZE 200
#define WIFI_TIMEOUT 1000
#define WIFI_CONNECT_TIMEOUT 10000
#define QFC41D_RESTART_CMD "AT+QRST"
#define QFC41D_PING_CMD "AT+QPING=<IP>"
#define QFC41D_LOW_POWER_MODE "AT+QLOWPOWER"
#define QFC41D_GET_MACK_ADDR "AT+QWLMAC"
#define QFC41D_GET_WIFISTA_STATUS "AT+QSTAST"
#define QFC41D_SET_DHCP_ENABLE "AT+QSTADHCPDEF=1"
//该命令用于设置串口波特率:AT+QSETBAND=<baud_rate>[,<save>] <baud_rate> 整型,串口波特率。<save>省略该参数则保存波特率。0:不保存波特率 1:保存波特率
#define QFC41D_SET_BATE "AT+QSETBAND=115200,1"
/* 下面命令用于模块作为外围设备时发送 GATT 数据
* AT+QBLEGATTSNTFY=<UUID>[,<hex_lngth>],<data>
* <UUID> UUID 2 16
* <hex_length> 使<data> <data> 123456 0x123456
* <data> GATT
*/
#define QFC41D_BLE_INIT "AT+QBLEINIT=2"
typedef void (*FC41DSendCall)(UartDev dev, uint8_t *buf, uint16_t len);
typedef struct
{
uint8_t dev;
uint16_t buf_pos;
uint16_t buf_size;
uint8_t *buf;
FC41DSendCall sendCall;
}WifiBleItem;
uint8_t drv_qfc41d_init(void);
// MQTT 初始化
uint8_t drv_mqtt_init();
// 发布 MQTT 消息
uint8_t drv_mqtt_publish(char* str,uint16_t length);
uint8_t drv_mqtt_publish_no_respose(char* str,uint16_t length);
uint8_t drv_mqtt_publish_control_no_respose(char* str,uint16_t length);
uint8_t drv_mqtt_publish_read_no_respose(char* str,uint16_t length);
uint8_t drv_ble_init();
#endif //DRV_QFC41D_H_

View File

@ -380,7 +380,7 @@ void drv_w5500_poll(W5500Item *item)
case SOCK_CLOSE_WAIT:
if(item->close_cnt[i]++ >= 5)
{
if((buf[0] & 0x08) == 0x08)
if((buf[0] & 0x08) == 0x08)
{
buf[0] = 0x08;
item->close_cnt[i] = 0;

View File

@ -25,6 +25,9 @@
#define DMA_STREAM3_IT_ERR ((uint32_t)0x03400000)
#define DMA_STREAM3_IT_FLAG ((uint32_t)0x0F400000)
extern volatile uint8_t dma_tx_busy;
extern volatile uint8_t current_buffer;
typedef enum
{
kDmaIdx_0,
@ -274,6 +277,31 @@ void DMA1_Stream5_IRQHandler(void)
{
}
void DMA1_Stream6_IRQHandler(void)
{
__disable_irq();
if (DMA1->HISR & DMA_HISR_TCIF6)
{
DMA1->HIFCR |= DMA_HIFCR_CTCIF6;
dma_tx_busy = 0;
USART2->CR3 &= ~USART_CR3_DMAT;
if (current_buffer == 1)
{
current_buffer = 0;
}
}
else if (DMA1->HISR & DMA_HISR_TEIF6)
{
DMA1->HIFCR |= DMA_HIFCR_CTEIF6;
dma_tx_busy = 0;
current_buffer = 0;
}
__enable_irq();
}
void DMA1_Channel6_IRQHandler(void)
{
}

View File

@ -52,15 +52,16 @@ void drv_rtc_disable_init_mode(void)
RTC->WPR = 0xFF; //使能RTC寄存器写保护
}
#define RCC_BDCR_RTCSEL_LSI (0x2U << 8) // RTCSEL[1:0] = 10, 选择 LSI 作为 RTC 时钟
//由于低速时钟起振较慢其他任务初始化后再初始化RTC
bool drv_rtc_init(void)
{
#if 0
bool res = false;
uint32_t dly = 0;
//if((RCC->BDCR & RCC_BDCR_RTCEN_POS) != RCC_BDCR_RTCEN_POS)
{
KIT_DEBUG_PRINTF("rtc init\r\n");
KIT_PRINTF("rtc init\r\n");
RCC->APB1ENR |= RCC_APB1Periph_PWR;
//使能允许写入RTC和后备寄存器
PWR->CR |= PWR_CR_DBP;
@ -71,11 +72,11 @@ bool drv_rtc_init(void)
bsp_task_delay_ms(10);
if(dly++ > 500)
{
KIT_DEBUG_PRINTF("rtc fail \r\n");
KIT_PRINTF("rtc fail \r\n");
return res;
}
}
KIT_DEBUG_PRINTF("rtc dly %d\r\n", dly);
KIT_PRINTF("rtc dly %d\r\n", dly);
RCC->BDCR |= (RCC_RTCCLKSource_LSE | RCC_BDCR_RTCEN_POS);
//RTC配置使用默认配置
//设置同步分频系数和异步分频系数默认为1Hz = 32768/(同步分频 + 1)/(异步分频 + 1)
@ -89,6 +90,38 @@ bool drv_rtc_init(void)
//PWR->CR &= ~PWR_CR_DBP_POS;
}
return res;
#endif
/* 1. 使能PWR和备份域访问 */
RCC->APB1ENR |= RCC_APB1ENR_PWREN; // 开启PWR时钟
PWR->CR |= PWR_CR_DBP; // 允许访问备份域
/* 2. 启用LSI并等待稳定 */
RCC->CSR |= RCC_CSR_LSION; // 启动内部低速时钟LSI
while ((RCC->CSR & RCC_CSR_LSIRDY) == 0); // 等待LSI准备好
/* 3. 选择LSI作为RTC时钟 */
RCC->BDCR &= ~RCC_BDCR_RTCSEL; // 清除RTC时钟选择
RCC->BDCR |= RCC_BDCR_RTCSEL_LSI; // 选择LSI为RTC时钟
RCC->BDCR |= RCC_BDCR_RTCEN; // 使能RTC
/* 4. 解锁RTC寄存器 */
RTC->WPR = 0xCA; // 先写入第一解锁码
RTC->WPR = 0x53; // 再写入第二解锁码
RTC->ISR |= RTC_ISR_INIT; // 进入初始化模式
while ((RTC->ISR & RTC_ISR_INITF) == 0); // 等待初始化完成
/* 5. 设置RTC预分频器LSI约为40kHz */
RTC->PRER = (127 << 16) | (249); // Async=127, Sync=2491Hz计数频率
RTC->CR &= ~RTC_CR_FMT; // 设置为24小时格式
RTC->ISR &= ~RTC_ISR_INIT; // 退出初始化模式
/* 6. 锁定写保护 */
RTC->WPR = 0xFF;
}
//ampm:AM/PM,0=AM/24H,1=PM.
@ -180,6 +213,7 @@ bool drv_rtc_get_date(int32_t *year, int32_t *month, int32_t *day)
uint32_t drv_rtc_get_tick(void)
{
#if 0
struct tm tmp;
uint32_t res = 0;
@ -189,10 +223,30 @@ uint32_t drv_rtc_get_tick(void)
{
tmp.tm_mon--;
tmp.tm_year = (tmp.tm_year > 2018) ? (tmp.tm_year - 1900) : 119;
res = kit_time_get_stamp(2019, &tmp);
res = mktime(&tmp);
//res = kit_time_get_stamp(2019, &tmp);
}
return res;
#endif
uint16_t year;
uint8_t month, date, hour, min, sec;
drv_get_date_time(&year, &month, &date, &hour, &min, &sec);
struct tm rtc_tm;
rtc_tm.tm_year = year - 1900;
rtc_tm.tm_mon = month - 1;
rtc_tm.tm_mday = date;
rtc_tm.tm_hour = hour;
rtc_tm.tm_min = min;
rtc_tm.tm_sec = sec;
rtc_tm.tm_isdst = -1; // 不使用夏令时
return kit_time_get_stamp(1970, &rtc_tm);
}
bool drv_rtc_set_tick(uint32_t tick)
@ -269,3 +323,54 @@ bool drv_rtc_set_ms(uint16_t ms)
return res;
}
// 设置日期时间year = 2000~2099
void drv_set_date_time(uint16_t year, uint8_t month, uint8_t date,uint8_t hour, uint8_t min, uint8_t sec)
{
if (year < 2000 || year > 2099) return; // 超出 RTC 范围
if (month == 0 || month > 12 || date == 0 || date > 31) return;
if (hour > 23 || min > 59 || sec > 59) return;
uint8_t yr = year - 2000;
// 解锁写保护
RTC->WPR = 0xCA;
RTC->WPR = 0x53;
// 进入初始化模式
RTC->ISR |= RTC_ISR_INIT;
while ((RTC->ISR & RTC_ISR_INITF) == 0);
// 设置时间BCD格式
RTC->TR = ((hour / 10) << 20) | ((hour % 10) << 16) |
((min / 10) << 12) | ((min % 10) << 8) |
((sec / 10) << 4) | (sec % 10);
// 设置日期BCD格式
RTC->DR = ((yr / 10) << 20) | ((yr % 10) << 16) |
((month / 10) << 12) | ((month % 10) << 8) |
((date / 10) << 4) | (date % 10);
RTC->ISR &= ~RTC_ISR_INIT; // 退出初始化模式
// 上锁
RTC->WPR = 0xFF;
}
// 获取当前时间
void drv_get_date_time(uint16_t *year, uint8_t *month, uint8_t *date,uint8_t *hour, uint8_t *min, uint8_t *sec)
{
uint32_t tr = RTC->TR;
uint32_t dr = RTC->DR;
*hour = ((tr >> 20) & 0x3) * 10 + ((tr >> 16) & 0xF);
*min = ((tr >> 12) & 0x7) * 10 + ((tr >> 8) & 0xF);
*sec = ((tr >> 4) & 0x7) * 10 + (tr & 0xF);
uint8_t yr_l = ((dr >> 20) & 0xF) * 10 + ((dr >> 16) & 0xF);
*year = 2000 + yr_l;
*month = ((dr >> 12) & 0x1) * 10 + ((dr >> 8) & 0xF);
*date = ((dr >> 4) & 0x3) * 10 + (dr & 0xF);
}

View File

@ -18,6 +18,11 @@ bool drv_rtc_set_ms(uint16_t ms);
uint16_t drv_rtc_get_ms(void);
uint32_t drv_rtc_get_tick(void);
// 获取当前时间
void drv_get_date_time(uint16_t *year, uint8_t *month, uint8_t *date,uint8_t *hour, uint8_t *min, uint8_t *sec);
// 设置日期时间year = 2000~2099
void drv_set_date_time(uint16_t year, uint8_t month, uint8_t date,uint8_t hour, uint8_t min, uint8_t sec);
#ifdef __cplusplus
}
#endif

View File

@ -9,19 +9,29 @@ extern "C"
#include <stdint.h>
#include <stdbool.h>
typedef enum
{
kKit_Ret_Ok = 0x00,
kKit_Ret_Error,
kKit_Ret_Null,
kKit_Ret_TimeOut,
kKit_Ret_OutRange,
/***************************ÖжÏÓÅÏȼ¶*********************/
#define APP_CFG_INT_PRIO_PWR_OFF 0u
#define APP_CFG_INT_PRIO_CAN1_RX 1u
#define APP_CFG_INT_PRIO_CAN1_TX 2u
#define APP_CFG_INT_PRIO_CAN2_RX 3u
#define APP_CFG_INT_PRIO_CAN2_TX 4u
kKit_Ret_NullPtr,
kKit_Ret_ParamErr,
kKit_Ret_CheckErr,
kKit_Ret_OverFlow,
} kit_ret_e;
#define APP_CFG_INT_PRIO_SYSTICK 5u
#define APP_CFG_INT_PRIO_UART2_RX 6u
typedef enum
{
kKit_Ret_Ok = 0x00,
kKit_Ret_Error,
kKit_Ret_Null,
kKit_Ret_TimeOut,
kKit_Ret_OutRange,
kKit_Ret_NullPtr,
kKit_Ret_ParamErr,
kKit_Ret_CheckErr,
kKit_Ret_OverFlow,
} kit_ret_e;
#define USE_BIT_ARRAY false
#define KIT_ABS(a) (((a) < 0) ? (-(a)) : (a))