/** ****************************************************************************** * @file BF8915A.c * @version V1.1.4 * @date 2021-12-20 * @brief This file provides the BF8915A functions(该文件提供BF8915A功能). */ #include "bsp_bf8915a.h" Reg_TypeDef configAArray[TOTAL_IC];//定义一个结构体为Reg_TypeDef的数据结构A数组,用于存储指令数据 uint8_t write_buffer[TOTAL_IC * 0x6U];//寄存器组中有6个8位寄存器 Reg_TypeDef configBArray[TOTAL_IC];//定义一个结构体为Reg_TypeDef的数据结构B数组,用于存储指令数据 Reg_TypeDef configCArray[TOTAL_IC];//定义一个结构体为Reg_TypeDef的数据结构C数组,用于存储指令数据 Reg_TypeDef configDArray[TOTAL_IC];//定义一个结构体为Reg_TypeDef的数据结构C数组,用于存储指令数据 ///*! // \brief SPI1_ReadWriteByte(SPI1读写一个字节) // \param[in] SPI_TxData :SPI需要发送的数据 // \retval SPI_ReceiveData:SPI接收到的数据 //*/ //uint8_t SPI1_ReadWriteByte(uint8_t TxData) //TxData 可以是8位或16位的,在启用SPI之前就确定好数据帧格式 //{ // u8 retry = 0; // while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET)//检查是否设置了指定的SPI标志。传输缓冲区空标志 //0:发送缓冲非空 等待发送缓冲器变空 // { // retry++; // if(retry>200)return 0; // } // SPI_I2S_SendData(SPI1, TxData);//通过SPI1发送数据。 // retry=0; // while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET)//等待接收数据完成,检查指定的SPI标志位设置与否:接收缓存非空标志位 // { // retry++; // if(retry>200)return 0; // } // return SPI_I2S_ReceiveData(SPI1); //返回最近接收的数据,SPI_DR寄存器里面的 //} ///*! // \brief //SPI2读写字节,此为STM32的SPI代码作为参考,客户需根据自己的主控MCU自行修改 // \param[in] SPI_TxData :SPI2需要发送的数据 // \retval SPI_ReceiveData:SPI2接收到的数据 //*/ //uint8_t SPI2_ReadWriteByte(uint8_t TxData) //{ // u8 retry=0; // while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET)//检查指定的SPI标志位设置与否:发送缓存空标志位 // { // retry++; // if(retry>200)return 0; // } // SPI_I2S_SendData(SPI2, TxData);//通过外设SPIx发送一个数据 // retry=0; // while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET)//检查指定的SPI标志位设置与否:接受缓存非空标志位 // { // retry++; // if(retry>200)return 0; // } // return SPI_I2S_ReceiveData(SPI2);//返回通过SPIx最近接收的数据 //} BOOLEAN isospi_reverse = FALSE;//改变该变量可以实现菊花链SPI正反向通信。 //FALSE:相对的正向通信,本SDK中的SPI1为相对正向通信,SPI1菊花链连接的第一颗IC看作是IC0; //TURE: 相对的反向通信,本SDK中的SPI2为相对反向通信,但也是SPI1菊花链连接的第一颗IC看作是IC0。 const uint16_t crc15Table[256] = {0x0000, 0xc599, 0xceab, 0x0b32, 0xd8cf, 0x1d56, 0x1664, 0xd3fd, 0xf407, 0x319e, 0x3aac, 0xff35, 0x2cc8, 0xe951, 0xe263, 0x27fa, 0xad97, 0x680e, 0x633c, 0xa6a5, 0x7558, 0xb0c1, 0xbbf3, 0x7e6a, 0x5990, 0x9c09, 0x973b, 0x52a2, 0x815f, 0x44c6, 0x4ff4, 0x8a6d, 0x5b2e, 0x9eb7, 0x9585, 0x501c, 0x83e1, 0x4678, 0x4d4a, 0x88d3, 0xaf29, 0x6ab0, 0x6182, 0xa41b, 0x77e6, 0xb27f, 0xb94d, 0x7cd4, 0xf6b9, 0x3320, 0x3812, 0xfd8b, 0x2e76, 0xebef, 0xe0dd, 0x2544, 0x02be, 0xc727, 0xcc15, 0x098c, 0xda71, 0x1fe8, 0x14da, 0xd143, 0xf3c5, 0x365c, 0x3d6e, 0xf8f7, 0x2b0a, 0xee93, 0xe5a1, 0x2038, 0x07c2, 0xc25b, 0xc969, 0x0cf0, 0xdf0d, 0x1a94, 0x11a6, 0xd43f, 0x5e52, 0x9bcb, 0x90f9, 0x5560, 0x869d, 0x4304, 0x4836, 0x8daf, 0xaa55, 0x6fcc, 0x64fe, 0xa167, 0x729a, 0xb703, 0xbc31, 0x79a8, 0xa8eb, 0x6d72, 0x6640, 0xa3d9, 0x7024, 0xb5bd, 0xbe8f, 0x7b16, 0x5cec, 0x9975, 0x9247, 0x57de, 0x8423, 0x41ba, 0x4a88, 0x8f11, 0x057c, 0xc0e5, 0xcbd7, 0x0e4e, 0xddb3, 0x182a, 0x1318, 0xd681, 0xf17b, 0x34e2, 0x3fd0, 0xfa49, 0x29b4, 0xec2d, 0xe71f, 0x2286, 0xa213, 0x678a, 0x6cb8, 0xa921, 0x7adc, 0xbf45, 0xb477, 0x71ee, 0x5614, 0x938d, 0x98bf, 0x5d26, 0x8edb, 0x4b42, 0x4070, 0x85e9, 0x0f84, 0xca1d, 0xc12f, 0x04b6, 0xd74b, 0x12d2, 0x19e0, 0xdc79, 0xfb83, 0x3e1a, 0x3528, 0xf0b1, 0x234c, 0xe6d5, 0xede7, 0x287e, 0xf93d, 0x3ca4, 0x3796, 0xf20f, 0x21f2, 0xe46b, 0xef59, 0x2ac0, 0x0d3a, 0xc8a3, 0xc391, 0x0608, 0xd5f5, 0x106c, 0x1b5e, 0xdec7, 0x54aa, 0x9133, 0x9a01, 0x5f98, 0x8c65, 0x49fc, 0x42ce, 0x8757, 0xa0ad, 0x6534, 0x6e06, 0xab9f, 0x7862, 0xbdfb, 0xb6c9, 0x7350, 0x51d6, 0x944f, 0x9f7d, 0x5ae4, 0x8919, 0x4c80, 0x47b2, 0x822b, 0xa5d1, 0x6048, 0x6b7a, 0xaee3, 0x7d1e, 0xb887, 0xb3b5, 0x762c, 0xfc41, 0x39d8, 0x32ea, 0xf773, 0x248e, 0xe117, 0xea25, 0x2fbc, 0x0846, 0xcddf, 0xc6ed, 0x0374, 0xd089, 0x1510, 0x1e22, 0xdbbb, 0x0af8, 0xcf61, 0xc453, 0x01ca, 0xd237, 0x17ae, 0x1c9c, 0xd905, 0xfeff, 0x3b66, 0x3054, 0xf5cd, 0x2630, 0xe3a9, 0xe89b, 0x2d02, 0xa76f, 0x62f6, 0x69c4, 0xac5d, 0x7fa0, 0xba39, 0xb10b, 0x7492, 0x5368, 0x96f1, 0x9dc3, 0x585a, 0x8ba7, 0x4e3e, 0x450c, 0x8095 };//precomputed CRC15 Table(预计算15位循环冗余校验值的表) /*! \brief Wake isoSPI up from idle state(将菊花链SPI从空闲状态唤醒) \param[in] total_ic: number of ICs in the daisy chain(菊花链中IC(8915A)的数量) \retval none */ void wakeup_idle(uint8_t total_ic) { int i =0; for (i =0; i> 8);//发送指令的PEC(检错码)的高八位 cmd[3] = (uint8_t)(cmd_pec);//发送指令的PEC(检错码)的低八位 if (isospi_reverse == FALSE)//判断选择的菊花链通信方向是相对正向还是相对反向 { cs_low();//将片选CS设置为低电平 spi_write_array(4,cmd);//将4字节数组写入SPI端口 cs_high();//将片选CS设置为高电平 } else { cs_low_reverse();//将片选CS设置为低电平 spi_write_array(4,cmd);//将4字节数组写入SPI端口 cs_high_reverse();//将片选CS设置为高电平 } } /*! \brief Generic function to write BF8915A commands and write payload data. Function calculated PEC for tx_cmd data(写BF8915A命令和写有效载荷数据的通用函数。tx_cmd数据的函数计算检错码) \param[in] total_ic : the number of ic(IC(8915A)的数量) \param[in] tx_cmd : 2 Byte array containing the BMS command to be sent(包含要发送的BMS(电池管理系统)命令的2字节数组) \param[in] write_data: Array containing the data to be written to the BMS ICs(包含要写入BMS(电池管理系统)IC(8915A)的数据数组) \retval none */ void BF8915A_write(uint8_t total_ic , uint8_t tx_cmd[2], uint8_t write_data[] ) { const uint8_t BYTES_IN_REG = 6;//寄存器组中的6个8位寄存器 const uint8_t CMD_LEN = 4+(8*total_ic);//4:cmd[0]~cmd[3];(8*total_ic):寄存器组中的6个8位寄存器 + 2个8位PEC(检错码) uint8_t *cmd;//需要发送的cmd数组 uint16_t data_pec;//计算配置寄存器数据的PEC(检错码) uint16_t cmd_pec;//计算出发送指令的PEC(检错码) uint8_t cmd_index;//用于写指令中 寄存器组中的数据 uint8_t current_ic = total_ic;// current_ic is used as the IC counter(当前IC(8915A)用作IC(8915A)计数器) uint8_t current_byte = 0;//当前需写入的寄存器组 的字节数 cmd = (uint8_t *)malloc(CMD_LEN*sizeof(uint8_t));//计算cmd数组发送数据所需的数组长度 cmd[0] = tx_cmd[0];//发送指令的高8位 cmd[1] = tx_cmd[1];//发送指令的低8位 cmd_pec = pec15_calc(2, cmd);//计算出发送指令的PEC(检错码) cmd[2] = (uint8_t)(cmd_pec >> 8);//发送指令的PEC(检错码)的高八位 cmd[3] = (uint8_t)(cmd_pec);//发送指令的PEC(检错码)的低八位 cmd_index = 4;//从4开始写入寄存器组中的数据 for (current_ic = total_ic; current_ic > 0; current_ic--) // executes for each BF8915A, this loops starts with the last IC on the stack(对每个BF8915A执行,这个循环从堆栈上的最后一个8915A开始) { //The first configuration written is received by the last IC in the daisy chain(菊花链中的最后一个IC(8915A)接收写入的第一个配置) for (current_byte = 0; current_byte < BYTES_IN_REG; current_byte++)//该循环将寄存器组中的6个8位寄存器的数据一一写入数组cmd[]中 { cmd[cmd_index] = write_data[((current_ic-1)*BYTES_IN_REG)+current_byte]; cmd_index = cmd_index + 1; } data_pec = (uint16_t)pec15_calc(BYTES_IN_REG, &write_data[(current_ic-1)*BYTES_IN_REG]);// calculating the PEC for each configuration register data(计算每个配置寄存器数据的PEC(检错码)) cmd[cmd_index] = (uint8_t)(data_pec >> 8);//配置寄存器数据的PEC(检错码)的高八位 cmd[cmd_index + 1] = (uint8_t)data_pec;//配置寄存器数据的PEC(检错码)的低八位 cmd_index = cmd_index + 2;//由于数组每个寄存器组写入后,每个IC的尾端需加2字节的PEC(检错码),因此cmd_index需每次都自增2 } if (isospi_reverse == FALSE)//判断选择的菊花链通信方向是相对正向还是相对反向 { cs_low();//将片选CS设置为低电平 spi_write_array(CMD_LEN, cmd);//将字节数组写入SPI端口 cs_high();//将片选CS设置为高电平 } else { cs_low_reverse();//将片选CS设置为低电平 spi_write_array(CMD_LEN, cmd);//将字节数组写入SPI端口 cs_high_reverse();//将片选CS设置为高电平 } free(cmd);//清空cmd数组 } /*! \brief Generic function to write BF8915A commands and read data(写BF8915A命令和读数据的通用函数). Function calculated PEC for tx_cmd data(发送指令数据的函数计算PEC(检错码)) Issues a command onto the daisy chain and reads back 6*total_ic data in the rx_data array(向菊花链发出命令,回读rx_data数组中的6倍IC(8915A)数据) \param[in] total_ic : the number of ic(IC(8915A)的数量) \param[in] tx_cmd : 2 Byte array containing the BMS command to be sent(包含要发送的BMS(电池管理系统)命令的2字节数组) \param[in] rx_data : Array that the read back data will be stored(存储回读数据的数组) \retval pec_error: 0: Data read back has matching PEC;1: Data read back has incorrect PEC(0:数据读回具有匹配的检错码 1:数据读回有不正确的检错码) */ uint8_t BF8915A_read(uint8_t total_ic , uint8_t tx_cmd[2], uint8_t *rx_data) { const uint8_t BYTES_IN_REG = 8;//寄存器组中的6个8位寄存器 + 2个8位PEC(检错码) uint8_t cmd[4];//需要发送的cmd数组 uint8_t rxDataTemp[256];//存储SPI端口读取的数据 的数组 uint8_t pec_error = 0;//检查检错码 uint16_t cmd_pec;//计算出发送指令的PEC(检错码) uint16_t data_pec;//计算配置寄存器数据的PEC(检错码) uint16_t received_pec;//存入接收到的PEC(检错码) uint8_t current_ic = 0;//current_ic is used as the IC counter(当前IC(8915A)用作IC(8915A)计数器) uint8_t current_byte = 0;//当前需读入的寄存器组 cmd[0] = tx_cmd[0];//发送指令的高8位 cmd[1] = tx_cmd[1];//发送指令的低8位 cmd_pec = pec15_calc(2, cmd);//计算出发送指令的PEC(检错码) cmd[2] = (uint8_t)(cmd_pec >> 8);//发送指令的PEC(检错码)的高八位 cmd[3] = (uint8_t)(cmd_pec);//发送指令的PEC(检错码)的低八位 if (isospi_reverse == FALSE)//判断选择的菊花链通信方向是相对正向还是相对反向 { cs_low();//将片选CS设置为低电平 spi_write_read(cmd, 4, rxDataTemp, (total_ic*BYTES_IN_REG));//Read the configuration data of all ICs on the daisy chain into rx_data[] array cs_high();//将片选CS设置为高电平 //(将菊花链上所有IC(8915A)的配置数据读入rx_data[]数组) } else { cs_low_reverse();//将片选CS设置为低电平 spi_write_read(cmd, 4, rxDataTemp, (total_ic*BYTES_IN_REG));//Read the configuration data of all ICs on the daisy chain into rx_data[] array cs_high_reverse();//将片选CS设置为高电平 //(将菊花链上所有IC(8915A)的配置数据读入rx_data[]数组) } for (current_ic = 0; current_ic < total_ic; current_ic++) //executes for each BF8915A in the daisy chain and packs the data(对菊花链中的每个BF8915A执行并打包数据) //into the r_comm array as well as check the received data for any bit errors(并检查接收到的数据是否有任何位错误) { for (current_byte = 0; current_byte < BYTES_IN_REG; current_byte++)//该循环将读回的寄存器组(6个8位寄存器)数据一一写入数组rx_data[]中 { rx_data[(current_ic*BYTES_IN_REG)+current_byte] = rxDataTemp[(current_ic*BYTES_IN_REG)+current_byte]; } received_pec = (rx_data[(current_ic*BYTES_IN_REG)+6]<<8) + rx_data[(current_ic*BYTES_IN_REG)+7];//将rx_data[]中接收到的PEC(检错码)按高低共16位存入received_pec中 data_pec = pec15_calc(6, &rx_data[current_ic*BYTES_IN_REG]);//计算接收回来的寄存器组(6个8位寄存器)中的PEC(检错码) if (received_pec != data_pec)//检查检错码是否匹配 { pec_error = 1;//检错码不正确 } } return(pec_error); } /*! \brief Calculates and returns the CRC15(计算并返回15位循环冗余校验值) \param[in] len : Number of bytes that will be used to calculate a PEC(将用于计算PEC(检错码)的字节数) \param[in] pecData: Array of data that will be used to calculate a PEC(将用于计算PEC(检错码)的数据数组) \retval The calculated pec15 as an unsigned int(计算出无符号整数的15位检错码) */ uint16_t pec15_calc(uint8_t len, uint8_t *pecData ) { uint16_t remainder,addr; uint8_t i = 0; remainder = 16;//initialize the PEC(初始化检错码) for (i = 0; i>7)^pecData[i])&0xff;//calculate PEC table address(计算检错码的表地址) remainder = (remainder<<8)^crc15Table[addr]; } return(remainder*2);//The CRC15 has a 0 in the LSB so the remainder must be multiplied by 2(15位循环冗余校验值的最低有效位为0,因此余数必须乘以2) } /*! \brief Helper function to set GPIO bits(设置GPIO位的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configAReg: Register group A(寄存器组A) \param[in] gpio_pd_en: 0: GPIO pin pull-down enable; 1: GPIO pin pull-down disable (default)(0:GPIO引脚下拉使能;1:GPIO引脚下拉禁用(默认)) \retval none */ void BF8915A_set_cfga_gpio(uint8_t nIC, Reg_TypeDef *configAReg,uint8_t gpio_pd_en) { configAReg[nIC].tx_data[0] = gpio_pd_en;//设置CFGAR0,0:GPIO引脚下拉使能;1:GPIO引脚下拉禁用 } /*! \brief Helper function to set GPIO IO_MODE(设置GPIO的IO口模式的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configAReg : Register group A(寄存器组A) \param[in] gpio_analog_en: 0: analog input;1: Ordinary GPIO(0:模拟输入;1:普通GPIO) \retval none */ void BF8915A_set_cfga_gpio_mode(uint8_t nIC, Reg_TypeDef *configAReg,uint8_t gpio_analog_en) { configAReg[nIC].tx_data[1] = gpio_analog_en;//设置CFGAR1,0:模拟输入;1:普通GPIO } void BF8915A_set_cfga_adc_init_mode(uint8_t nIC, Reg_TypeDef *configAReg,bool adc_init_mode) { if (adc_init_mode) configAReg[nIC].tx_data[2] = configAReg[nIC].tx_data[2]|(0x01<<4); else configAReg[nIC].tx_data[2] = configAReg[nIC].tx_data[2]&(~(0x01 <<4)); } /*! \brief 保留位,永远置0 \retval none */ void BF8915A_set_cfga_rsvd(uint8_t nIC, Reg_TypeDef *configAReg,BOOLEAN rsvd2,BOOLEAN rsvd1) { configAReg[nIC].tx_data[2] = configAReg[nIC].tx_data[2]&(~(0x01<<3));//保留位,永远置0 configAReg[nIC].tx_data[2] = configAReg[nIC].tx_data[2]&(~(0x01<<2));//保留位,永远置0 } /*! \brief Helper function to set osr_sel(设置ADC过采样率选择的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configAReg: Register group A(寄存器组A) \param[in] osr_sel : OSR_64 、OSR_128、OSR_256、OSR_512(ADC过采样频率选择) \retval none */ void BF8915A_set_cfga_osr_sel(uint8_t nIC, Reg_TypeDef *configAReg,BOOLEAN osr_sel) { configAReg[nIC].tx_data[2] = configAReg[nIC].tx_data[2]&(~(0x01<<1));//写0,过采样率选择64,128,256,512(四种过采样率通过指令的OSR选择) } /*! \brief Helper function to set refon(设置基准电压配置的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configAReg: Register group A(寄存器组A) \param[in] refon : 1: VREF1 remains powered on until WDT overflowsVREF1 0: VREF1 is turned off after ADC conversion (1:VREF1(基准电压)保持上电直到WDT溢出 0:ADC转换完之后VREF1关闭 (默认)) \retval none */ void BF8915A_set_cfga_refon(uint8_t nIC, Reg_TypeDef *configAReg,BOOLEAN refon) { if (refon)//设置CFGAR2的第1位 configAReg[nIC].tx_data[2] = configAReg[nIC].tx_data[2]|(0x01);//写1,VREF1(基准电压)保持上电直到WDT溢出 else configAReg[nIC].tx_data[2] = configAReg[nIC].tx_data[2]&(~(0x01));//写0,ADC转换完之后VREF1关闭 } /*! \brief Helper Function to set uv value in CFG register(在配置寄存器组的寄存器中设置欠压阈值的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configAReg: Register group A(寄存器组A) \param[in] uv : Low 8 bits of undervoltage threshold(低8位欠压阈值) \retval none */ void BF8915A_set_cfga_uv(uint8_t nIC, Reg_TypeDef *configAReg,uint16_t uv) { configAReg[nIC].tx_data[3] = 0x00FF & uv;//设置CFGAR3,欠压阈值低8位放入 configAReg[nIC].tx_data[4] = configAReg[nIC].tx_data[4]&0xF0;//将CFGAR4低4位清空 configAReg[nIC].tx_data[4] = configAReg[nIC].tx_data[4]|((0x0F00 & uv)>>8);//设置CFGAR4低4位,欠压阈值高4位放入 } /*! \brief helper function to set OV value in CFG register(在配置寄存器组的寄存器中设置过压阈值的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configAReg: Register group A(寄存器组A) \param[in] ov : Overvoltage threshold lower 4 bits(过压阈值低4位) \retval none */ void BF8915A_set_cfga_ov(uint8_t nIC, Reg_TypeDef *configAReg,uint16_t ov) { configAReg[nIC].tx_data[5] = 0x00FF & (ov>>4);//设置CFGAR5,过压阈值高8位放入 configAReg[nIC].tx_data[4] = configAReg[nIC].tx_data[4]&0x0F;//将CFGAR4高4位清空 configAReg[nIC].tx_data[4] = configAReg[nIC].tx_data[4]|((0x000F & ov)<<4);//设置CFGAR4高4位,过压阈值低4位放入 //保存CFGAR4低4位,即欠压阈值高4位 } /*! \brief Helper function to set CFGRA variable(设置配置寄存器组A变量的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configAReg : Register group A(寄存器组A) \param[in] gpio_pd_en : GPIO pin pull-down enable; 1: GPIO pin pull-down disable (default)(0:GPIO引脚下拉使能;1:GPIO引脚下拉禁用(默认)) \param[in] gpio_analog_en: 0: analog input 1: Ordinary GPIO(0:模拟输入;1:普通GPIO) \param[in] rsvd2 : 保留位,永远置0 \param[in] rsvd1 : 保留位,永远置0 \param[in] osr_sel : OSR_64 、OSR_128、OSR_256、OSR_512(ADC过采样频率选择) \param[in] refon : 1: VREF1 remains powered on until WDT overflowsVREF1 0: VREF1 is turned off after ADC conversion (1:VREF1(基准电压)保持上电直到WDT溢出 0:ADC转换完之后VREF1关闭 (默认)) \param[in] uv_th : Low 8 bits of undervoltage threshold(低8位欠压阈值) \param[in] ov_th : Overvoltage threshold lower 4 bits(过压阈值低4位) \retval none */ void BF8915A_set_cfgra(uint8_t nIC, Reg_TypeDef *configAReg, uint8_t gpio_pd_en,//写0:GPIO脚下拉使能;1:GPIO脚下拉关闭(默认)读0 :GPIO脚的值是0 ;1:GPIO脚的值是1 uint8_t gpio_analog_en,//GPIO0~7模式选择 0:模拟输入 1:普通GPIO BOOLEAN adc_inti_mode, BOOLEAN rsvd2,//保留位,永远置0 BOOLEAN rsvd1,//保留位,永远置0 BOOLEAN osr_sel,//0:过采样率选择64,128,256,512(四种过采样率通过指令的OSR选择) //这个寄存器位要和指令的OSR一起配置选择ADC过采样率 BOOLEAN refon, //VREF1(基准电压)配置 1 :VREF1保持上电直到WDT溢出 0 :ADC转换完之后VREF1关闭 (默认) uint16_t uv_th,//Under voltage Comparison Voltage(欠压阈值),根据实际情况自行设定 //Under voltage threshold ADC Code(欠电压阈值模数转换器代码): uv_th = 3000 * 65535U / 5000U. LSB = 0.0001 ---(3V) uint16_t ov_th //Over voltage Comparison Voltage(过压阈值),根据实际情况自行设定 //Over voltage threshold ADC Code(过电压阈值模数转换器代码): ov_th = 4100 * 65535U / 5000U. LSB = 0.0001 ---(4.1V) ) { BF8915A_set_cfga_gpio(nIC, configAReg, gpio_pd_en);//设置CFGAR0 BF8915A_set_cfga_gpio_mode(nIC, configAReg,gpio_analog_en);//设置CFGAR1 BF8915A_set_cfga_adc_init_mode(nIC, configAReg,adc_inti_mode); BF8915A_set_cfga_rsvd(nIC, configAReg,rsvd2,rsvd1);//保留位,永远置0 BF8915A_set_cfga_osr_sel(nIC, configAReg,osr_sel);//设置CFGAR2的第2位 BF8915A_set_cfga_refon(nIC, configAReg,refon);//设置CFGAR2的第1位 BF8915A_set_cfga_uv(nIC, configAReg,uv_th);//设置CFGAR3和CFGAR4低4位 BF8915A_set_cfga_ov(nIC, configAReg,ov_th);//设置CFGAR5和CFGAR4高4位 } /*! \brief Helper function to control discharge(控制放电的辅助功能) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configBReg: Register group B(寄存器组B) \param[in] dcc : 1: Turn on the switch of Cell x(打开x号电池的开关) 0: Turn off the switch of Cell x(关闭x号电池的开关) \retval none */ void BF8915A_set_cfgb_dcc(uint8_t nIC, Reg_TypeDef *configBReg,uint16_t dcc) { configBReg[nIC].tx_data[0] = (uint8_t)dcc;//设置CFGBR0,放电电池开关x=1~8 configBReg[nIC].tx_data[1] = (uint8_t)(dcc >> 0x8U);//设置CFGBR1,放电电池开关x=9~16 } /*! \brief Balanced duty cycle selection(均衡占空比选择) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configBReg : Register group B(寄存器组B) \param[in] bl_duty_sel: Active balancing duty cycle selection(均衡占空比选择) \retval none */ //bl_duty_sel(4位): 均衡占空比选择,占空比=(BL_DUTY_SEL+1)*10%,配置范围10%~100%,当大于9时是100%。 void BF8915A_set_cfgb_bl_duty_sel(uint8_t nIC, Reg_TypeDef *configBReg, uint8_t bl_duty_sel ) { configBReg[nIC].tx_data[2] = configBReg[nIC].tx_data[2] & 0x0F;//将CFGBR2的高4位清空 configBReg[nIC].tx_data[2] = configBReg[nIC].tx_data[2] | ((0x0F & bl_duty_sel)<<4);//设置CFGBR2高4位,均衡占空比选择 //保存CFGBR2低4位 } /*! \brief Helper function to set dcto(设置放电定时溢出值配置的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configBReg: Register group B(寄存器组B) \param[in] dcto : Discharge timing overflow value configuration(放电定时溢出值配置,详细说明如DCTO表所示) \retval none */ void BF8915A_set_cfgb_dcto(uint8_t nIC, Reg_TypeDef *configBReg, uint8_t dcto ) { configBReg[nIC].tx_data[2] = configBReg[nIC].tx_data[2] & 0xF0;//将CFGBR2的低4位清空 configBReg[nIC].tx_data[2] = configBReg[nIC].tx_data[2] | (0x0F & dcto);//设置CFGBR2低4位,放电定时溢出值配置 //保存CFGBR2高4位 } /*! \brief Helper function to set vuv_bl(设置均衡欠压阈值的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configBReg: Register group B(寄存器组B) \param[in] vuv_bl : Lower 8 bits of equalization undervoltage threshold(均衡欠压阈值的低8位) \retval none */ void BF8915A_set_cfgb_vuv_bl(uint8_t nIC, Reg_TypeDef *configBReg, uint16_t vuv_bl//均衡欠压值(12位) ) { configBReg[nIC].tx_data[3] = vuv_bl & 0xFF;//设置CFGBR3,均衡欠压阈值低8位放入 configBReg[nIC].tx_data[4] = configBReg[nIC].tx_data[4] & 0xF0;//将CFGBR4的低4位清空 configBReg[nIC].tx_data[4] = configBReg[nIC].tx_data[4] | ((vuv_bl & 0x0F00U) >> 0x8U);//设置CFGBR4低4位,均衡欠压阈值高4位放入 //保存CFGBR4高4位 } /*! \brief Helper function to set bl_dtmen(设置启用放电监测的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configBReg: Register group B(寄存器组B) \param[in] dtmen : Enable discharge monitor(启用放电监测) 1: Enable discharge monitor(启用放电监测) 0: Disable discharge monitor(禁用放电监测) \retval none */ void BF8915A_set_cfgb_bl_dtmen(uint8_t nIC, Reg_TypeDef *configBReg, BOOLEAN dtmen ) { if (dtmen)//设置CFGAR4的第5位 configBReg[nIC].tx_data[4] = configBReg[nIC].tx_data[4] | (0x01<<4);//写1,使能放电监视器 else configBReg[nIC].tx_data[4] = configBReg[nIC].tx_data[4] & (~(0x01<<4));//写0,不使能放电监视器 } /*! \brief Helper function to set CFGRB variable(设置配置寄存器组B变量的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configBReg : Register group B(寄存器组B) \param[in] dcc : 1: Turn on the switch of Cell x(打开x电池的开关) 0: Turn off the switch of Cell x(关闭x电池的开关) \param[in] bl_duty_sel: Active balancing duty cycle selection(均衡占空比选择) \param[in] dcto : Discharge timing overflow value configuration(放电定时溢出值配置) \param[in] vuv_bl : Lower 8 bits of equalization undervoltage threshold(均衡欠压阈值的低8位) \param[in] dtmen : Enable discharge monitor(使能放电监测器) 1: Enable discharge monitor(启用放电监测) 0: Disable discharge monitor(禁用放电监测) \retval none */ void BF8915A_set_cfgrb(uint8_t nIC, Reg_TypeDef *configBReg, uint16_t dcc,//放电电池开关1:打开Cell x 的开关 0:关闭Cell x 的开关 (默认) uint8_t bl_duty_sel,//均衡占空比选择 占空比=(BL_DUTY_SEL+1)*10%,配置范围10%~100%,当大于9时是100% uint8_t dcto,//放电定时溢出值配置 uint16_t vuv_bl,//均衡欠压阈值 BOOLEAN dtmen//在自动均衡下,如果DTMEN=1,当欠压(小于VUV_BL)关闭放电开关,如果DTMEN=0,不进行欠压比较 ) { BF8915A_set_cfgb_dcc(nIC, configBReg,dcc);//控制放电的辅助功能 BF8915A_set_cfgb_bl_duty_sel(nIC, configBReg,bl_duty_sel);//均衡占空比选择 BF8915A_set_cfgb_dcto(nIC, configBReg,dcto);//设置放电定时溢出值配置的辅助函数 BF8915A_set_cfgb_vuv_bl(nIC, configBReg,vuv_bl);//设置均衡欠压阈值的辅助函数 BF8915A_set_cfgb_bl_dtmen(nIC, configBReg,dtmen);//设置启用放电监测的辅助函数 } /*! \brief Helper function to set Undervoltage threshold in monitoring mode(监测模式下,设置欠压阈值的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configCReg: Register group C(寄存器组C) \param[in] vuv_m : Undervoltage threshold in monitoring mode(监测模式下的欠压阈值) \retval none */ void BF8915A_set_cfgc_vuv_m(uint8_t nIC, Reg_TypeDef *configCReg,uint16_t vuv_m) { configCReg[nIC].tx_data[0] = 0x00FF & vuv_m;//设置CFGCR0,监测模式下,欠压阈值低8位放入 configCReg[nIC].tx_data[1] = configCReg[nIC].tx_data[1]&0xF0;//将CFGCR1的低4位清空 configCReg[nIC].tx_data[1] = configCReg[nIC].tx_data[1]|((0x0F00 & vuv_m)>>8);//设置CFGCR1低4位,监测模式下,欠压阈值高4位放入 //保存CFGCR1高4位 } /*! \brief Helper function to set Overvoltage threshold in monitoring mode(监测模式下,设置过压阈值的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configCReg: Register group C(寄存器组C) \param[in] vov_m : Overvoltage threshold in monitoring mode(监测模式下的过压阈值) \retval none */ void BF8915A_set_cfgc_vov_m(uint8_t nIC, Reg_TypeDef *configCReg,uint16_t vov_m) { configCReg[nIC].tx_data[2] = 0x00FF & (vov_m>>4);//设置CFGCR2,监测模式下,过压阈值高8位放入 configCReg[nIC].tx_data[1] = configCReg[nIC].tx_data[1]&0x0F;//将CFGCR1的高4位清空 configCReg[nIC].tx_data[1] = configCReg[nIC].tx_data[1]|((0x000F & vov_m)<<4);//设置CFGCR1高4位,监测模式下,过压阈值低4位放入 //保存CFGCR1低4位 } /*! \brief Helper function to set Internal over-temperature threshold in monitoring mode(监测模式下,设置内部过温阈值的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configCReg: Register group C(寄存器组C) \param[in] itov_m : In monitoring mode, internal over-temperature threshold(监测模式下,内部过温阈值) \retval none */ void BF8915A_set_cfgc_itov_m(uint8_t nIC, Reg_TypeDef *configCReg,uint16_t itov_m) { configCReg[nIC].tx_data[3] = 0x00FF & itov_m;//设置CFGCR3,监测模式下,内部过温阈值低8位放入 configCReg[nIC].tx_data[4] = configCReg[nIC].tx_data[4]&0xF0;//将CFGCR4的低4位清空 configCReg[nIC].tx_data[4] = configCReg[nIC].tx_data[4]|((0x0F00 & itov_m)>>8);//设置CFGCR4低4位,监测模式下,内部过温阈值高4位放入 //保存CFGCR4高4位 } /*! \brief Helper function to set external over-temperature threshold in monitoring mode(监测模式下,设置外部过温阈值的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configCReg: Register group C(寄存器组C) \param[in] extov_m : In monitoring mode, external over-temperature threshold(监测模式下,外部过温阈值) \retval none */ void BF8915A_set_cfgc_extov_m(uint8_t nIC, Reg_TypeDef *configCReg,uint16_t extov_m) { configCReg[nIC].tx_data[5] = 0x00FF & (extov_m>>4);//设置CFGCR5,监测模式下,外部过温阈值高8位放入 configCReg[nIC].tx_data[4] = configCReg[nIC].tx_data[4]&0x0F;//将CFGCR4的高4位清空 configCReg[nIC].tx_data[4] = configCReg[nIC].tx_data[4]|((0x000F & extov_m)<<4);//设置CFGCR4高4位,监测模式下,外部过温阈值低4位放入 //保存CFGCR4低4位 } /*! \brief Helper function to set CFGRC variable(设置配置寄存器组C变量的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configCReg: Register group C(寄存器组C) \param[in] vuv_m : Undervoltage threshold in monitoring mode(监测模式下的欠压阈值) \param[in] vov_m : Overvoltage threshold in monitoring mode(监测模式下的过压阈值) \param[in] itov_m : Internal over-temperature threshold in monitoring mode(监测模式下,内部过温阈值) \param[in] extov_m : external over-temperature threshold in monitoring mode(监测模式下,外部过温阈值) \retval none */ void BF8915A_set_cfgrc(uint8_t nIC, Reg_TypeDef *configCReg, uint16_t vuv_m,//监测模式下的欠压阈值 uint16_t vov_m,//监测模式下的过压阈值 uint16_t itov_m,//监测模式下的内部过温阈值 uint16_t extov_m//监测模式下的外部过温阈值 ) { BF8915A_set_cfgc_vuv_m(nIC, configCReg,vuv_m);//监测模式下,设置欠压阈值的辅助函数 BF8915A_set_cfgc_vov_m(nIC, configCReg,vov_m);//监测模式下,设置过压阈值的辅助函数 BF8915A_set_cfgc_itov_m(nIC, configCReg,itov_m);//监测模式下,设置内部过温阈值的辅助函数 BF8915A_set_cfgc_extov_m(nIC, configCReg,extov_m);//监测模式下,设置外部过温阈值的辅助函数 } /*! \brief Helper function to set csel_m(设置监测模式下,电池电压监测比较选择的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDReg: Register group D(寄存器组D) \param[in] csel_m : In monitoring mode, battery voltage monitoring comparison selection cell1~cell16(在监测模式下,电池电压监测比较选择电池1 ~电池16) \retval none */ void BF8915A_set_cfgd_csel_m(uint8_t nIC, Reg_TypeDef *configDReg,uint16_t csel_m) { configDReg[nIC].tx_data[0] = 0x00FF & csel_m;//设置CFGDR0,即电池电压监测比较选择cell1~cell8 configDReg[nIC].tx_data[1] = (csel_m & 0xFF00) >> 0x8U;//设置CFGDR1,即电池电压监测比较选择cell9~cell16 } /*! \brief Helper function to set gsel_m(设置监测模式下,GPIO0~7比较选择的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDReg: Register group D(寄存器组D) \param[in] gsel_m : In monitoring mode, GPIO0~7 is compared and selected(监测模式下,GPIO0~7比较选择) \retval none */ void BF8915A_set_cfgd_gsel_m(uint8_t nIC, Reg_TypeDef *configDReg,uint8_t gsel_m) { configDReg[nIC].tx_data[2] = gsel_m;//设置CFGDR2 } /*! \brief Helper function to set isospi_wake_t(设置菊花链唤醒时间的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDReg : Register group D(寄存器组D) \param[in] isospi_wake_t: isospi wake-up time, 0: 10us; 1:20us(isospi(菊花链SPI)唤醒时间,0:10us;1:20us) \retval none */ void BF8915A_set_cfgd_isospi_wake_t(uint8_t nIC, Reg_TypeDef *configDReg,BOOLEAN isospi_wake_t) { if (isospi_wake_t)//设置CFGDR3的第8位 configDReg[nIC].tx_data[3] = configDReg[nIC].tx_data[3] | (0x01<<7);//写1 else configDReg[nIC].tx_data[3] = configDReg[nIC].tx_data[3] & (~(0x01<<7));//写0 } /*! \brief Helper function to set adc_rst_sel(设置测量第1个通道ADC复位选择的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDReg : Register group D(寄存器组D) \param[in] adc_rst_sel: 0: All measurement channels reset ADC(所有测量通道都复位ADC) 1: Only the first channel resets ADC, then 2~n channels do not reset ADC(只有第1个通道复位ADC,之后2~n通道不复位ADC) \retval none */ void BF8915A_set_cfgd_adc_rst_sel(uint8_t nIC, Reg_TypeDef *configDReg,BOOLEAN adc_rst_sel) { if (adc_rst_sel)//设置CFGDR3的第7位 configDReg[nIC].tx_data[3] = configDReg[nIC].tx_data[3] | (0x01<<6);//写1 else configDReg[nIC].tx_data[3] = configDReg[nIC].tx_data[3] & (~(0x01<<6));//写0 } /*! \brief Helper function to set time_sel_m(设置监测模式下,定时监测时间配置的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDReg: Register group D(寄存器组D) \param[in] time_sel_m: In monitoring mode, timing monitoring time configuration(监测模式下,定时监测时间配置) \retval none */ //time_sel_m(5位):监测模式下,定时监测时间配置,定时时间=(TIME_SEL_M+1)*1s(2~64s),最小配置值是1(2s) //这个时间配置和均衡周期配置共用 void BF8915A_set_cfgd_time_sel_m(uint8_t nIC, Reg_TypeDef *configDReg,uint8_t time_sel_m) { configDReg[nIC].tx_data[3] = configDReg[nIC].tx_data[3] & 0xC0U;//将CFGDR3低6位清空 configDReg[nIC].tx_data[3] = configDReg[nIC].tx_data[3] | (time_sel_m & 0x3F);//设置CFGDR3低6位 //保存CFGDR3高2位 } /*! \brief Helper function to set adc_init_t2(设置ADC测量第2~n个通道ADC初始化时间的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDReg : Register group D(寄存器组D) \param[in] adc_init_t2: ADC measurement 2~n channel ADC initialization time(ADC测量第2~n个通道ADC初始化时间) \retval none */ //ADC测量第2~n个通道ADC初始化时间,(ADC_INIT_T2+1)*20us(20~320us) void BF8915A_set_cfgd_adc_init_t2(uint8_t nIC, Reg_TypeDef *configDReg,uint8_t adc_init_t2) { configDReg[nIC].tx_data[4] = configDReg[nIC].tx_data[4] & 0x0FU;//将CFGDR4高4位清空 configDReg[nIC].tx_data[4] = configDReg[nIC].tx_data[4] | ((adc_init_t2 & 0x0F) << 0x4U);//设置CFGDR4高4位 //保存CFGDR4低4位 } /*! \brief Helper function to set adc_init_t1(设置ADC测量第1个通道ADC初始化时间的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDReg : Register group D(寄存器组D) \param[in] adc_init_t1: ADC measurement 1 channel ADC initialization time(ADC测量第1个通道ADC初始化时间) \retval none */ //ADC测量第1个通道ADC初始化时间(ADC_INIT_T1+1)*100us(100~1600us) void BF8915A_set_cfgd_adc_init_t1(uint8_t nIC, Reg_TypeDef *configDReg,uint8_t adc_init_t1) { configDReg[nIC].tx_data[4] = configDReg[nIC].tx_data[4] & 0xF0U;//将CFGDR4低4位清空 configDReg[nIC].tx_data[4] = configDReg[nIC].tx_data[4] | (adc_init_t1 & 0x0F);//设置CFGDR4低4位 //保存CFGDR4高4位 } /*! \brief Helper function to set trim2_en(设置修调2使能的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDReg: Register group D(寄存器组D) \param[in] trim2_en : Modification 2 enable, 1: enable, 0: disable(修调2使能,1:使能,0:不使能) \retval none */ void BF8915A_set_cfgd_trim2_en(uint8_t nIC, Reg_TypeDef *configDReg,BOOLEAN trim2_en) { if (trim2_en)//设置CFGDR5的第8位 configDReg[nIC].tx_data[5] = configDReg[nIC].tx_data[5] | (0x01<<7);//写1 else configDReg[nIC].tx_data[5] = configDReg[nIC].tx_data[5] & (~(0x01<<7));//写0 } /*! \brief Helper function to set trim1_en(设置修调1使能的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDReg: Register group D(寄存器组D) \param[in] trim1_en : Modification 1 enable, 1: enable, 0: disable(修调1使能,1:使能,0:不使能) \retval none */ void BF8915A_set_cfgd_trim1_en(uint8_t nIC, Reg_TypeDef *configDReg,BOOLEAN trim1_en) { if (trim1_en)//设置CFGDR5的第7位 configDReg[nIC].tx_data[5] = configDReg[nIC].tx_data[5] | (0x01<<6);//写1 else configDReg[nIC].tx_data[5] = configDReg[nIC].tx_data[5] & (~(0x01<<6));//写0 } /*! \brief Helper function to set trim1_en(设置监测模式下发生异常,上报的间隔时间的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDReg : Register group D(寄存器组D) \param[in] err_t_sel_m: When an exception occurs in the monitoring mode, the reporting interval(监测模式下发生异常,上报的间隔时间) \retval none */ //err_t_sel_m(2位):监测模式下发生异常,上报的间隔时间 00:200ms,01:400ms,10:600ms,11:800ms void BF8915A_set_cfgd_err_t_sel_m(uint8_t nIC, Reg_TypeDef *configDReg,uint8_t err_t_sel_m) { configDReg[nIC].tx_data[5] = configDReg[nIC].tx_data[5] & 0xCFU;//将CFGDR5的第6~5位清空 configDReg[nIC].tx_data[5] = configDReg[nIC].tx_data[5] | ((err_t_sel_m & 0x03) << 0x4U);//设置CFGDR5第6~5位 //保存CFGDR5第8~7位 } /*! \brief Helper function to set CFGRD variable(设置配置寄存器组D变量的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDReg: A two dimensional array of the configuration data that will be written(将要写入配置数据的二维数组) \param[in] vd33t_on_m: A two dimensional array of the configuration data that will be written(将要写入配置数据的二维数组) \retval none */ //vd33t_on_m:监测模式下,VREF1(基准电压)和VD33T的启动时间配置(5+VD33T_ON_M*10)ms,范围是5~155ms void BF8915A_set_cfgd_vd33t_on_m(uint8_t nIC, Reg_TypeDef *configDReg,uint8_t vd33t_on_m) { configDReg[nIC].tx_data[5] = configDReg[nIC].tx_data[5] & 0xF0U;//将CFGDR5的低4位清空 configDReg[nIC].tx_data[5] = configDReg[nIC].tx_data[5] | (vd33t_on_m & 0x0F);//保存CFGDR5高4位,设置CFGDR5低4位 } /*! \brief Helper function to set CFGRD variable(设置配置寄存器组D变量的辅助函数) \param[in] nIC : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDReg : Register group D(寄存器组D) \param[in] csel_m : In monitoring mode, battery voltage monitoring comparison selection cell1~cell16(在监测模式下,电池电压监测比较选择电池1~电池16) \param[in] gsel_m : In monitoring mode, GPIO0~7 comparison selection(监测模式下,GPIO0~7比较选择) \param[in] isospi_wake_t: isospi wake up time(菊花链唤醒时间) \param[in] adc_rst_sel : 0: All measurement channels reset ADC(所有测量通道都复位ADC) 1: Only the first channel resets ADC, then 2~n channels do not reset ADC(只有第1个通道复位ADC,之后2~n通道不复位ADC) \param[in] time_sel_m : In monitoring mode, timing monitoring time configuration, timing time=(TIME_SEL_M+1)*1s(2~64s), the minimum configuration value is 1(2s);This time configuration is shared with the balance period configuration (监测模式下,定时监测时间配置,定时时间=(TIME_SEL_M+1)*1s(2~64s),最小配置值是1(2s);该时间配置与均衡时期的配置共享) \param[in] adc_init_t2 : ADC measures the ADC initialization time of the second to n channels, (ADC_INIT_T2+1)*20us (20~320us)(ADC测量第2~n个通道ADC初始化时间,(ADC_INIT_T2+1)*20us(20~320us)) \param[in] adc_init_t1 : ADC measurement of the first channel ADC initialization time (ADC_INIT_T1+1)*100us (100~1600us)(ADC测量第1个通道ADC初始化时间(ADC_INIT_T1+1)*100us(100~1600us)) \param[in] trim2_en:1 : enable, 0: disable(修调2使能,1:使能,0:不使能) \param[in] trim1_en:1 : enable, 0: disable(修调1使能,1:使能,0:不使能) \param[in] err_t_sel_m : 00: 200ms, 01: 400ms, 10: 600ms, 11: 800ms(监测模式下发生异常,上报的间隔时间 00:200ms,01:400ms,10:600ms,11:800ms) \param[in] vd33t_on_m : The startup time configuration of VREF1 and VD33T (5+VD33T_ON_M*10)ms, the range is 5~155ms(监测模式下,VREF1和VD33T的启动时间配置(5+VD33T_ON_M*10)ms,范围是5~155ms) \retval none */ void BF8915A_set_cfgrd(uint8_t nIC, Reg_TypeDef *configDReg, uint16_t csel_m,//监测模式下,电池电压监测比较选择cell1~cell16 //1:相应的电池就会在监测模式下进行过欠压比较,置标志位 //0:相应的电池就会在监测模式下不进行过欠压比较,不置标志位 uint8_t gsel_m ,//监测模式下,GPIO0~7比较选择 //1:相应的电池就会在监测模式下进行过温(小于外部温度阈值)比较,置标志位 //0:相应的电池就会在监测模式下不进行过温(小于外部温度阈值)比较,不置标志位 BOOLEAN isospi_wake_t,//菊花链唤醒时间,0: 10us;1: 20us BOOLEAN adc_rst_sel,//测量第1个通道ADC复位选择,0:所有测量通道都复位ADC,1:只有第1个通道复位ADC,之后2~n通道不复位ADC uint8_t time_sel_m,//监测模式下,定时监测时间配置,定时时间=(TIME_SEL_M+1)*1s(2~64s),最小配置值是1(2s) //这个时间配置和均衡周期配置共用 uint8_t adc_init_t2,//ADC测量第2~n个通道ADC初始化时间,(ADC_INIT_T2+1)*20us(20~320us) uint8_t adc_init_t1,//ADC测量第1个通道ADC初始化时间(ADC_INIT_T1+1)*100us(100~1600us) BOOLEAN trim2_en,//修调2使能,1:使能,0:不使能 BOOLEAN trim1_en,//修调1使能,1:使能,0:不使能 uint8_t err_t_sel_m,//监测模式下发生异常,上报的间隔时间 //00:200ms,01:400ms,10:600ms,11:800ms uint8_t vd33t_on_m//监测模式下,VREF1和VD33T的启动时间配置(5+VD33T_ON_M*10)ms,范围是5~155ms ) { BF8915A_set_cfgd_csel_m(nIC, configDReg,csel_m);//设置监测模式下,电池电压监测比较选择的辅助函数 BF8915A_set_cfgd_gsel_m(nIC, configDReg,gsel_m);//设置监测模式下,GPIO0~7比较选择的辅助函数 BF8915A_set_cfgd_isospi_wake_t(nIC, configDReg,isospi_wake_t);//设置菊花链唤醒时间的辅助函数 BF8915A_set_cfgd_adc_rst_sel(nIC, configDReg,adc_rst_sel);//设置测量第1个通道ADC复位选择的辅助函数 BF8915A_set_cfgd_time_sel_m(nIC, configDReg,time_sel_m);//设置监测模式下,定时监测时间配置的辅助函数 BF8915A_set_cfgd_adc_init_t2(nIC, configDReg,adc_init_t2);//设置ADC测量第2~n个通道ADC初始化时间的辅助函数 BF8915A_set_cfgd_adc_init_t1(nIC, configDReg,adc_init_t1);//设置ADC测量第1个通道ADC初始化时间的辅助函数 BF8915A_set_cfgd_trim2_en(nIC, configDReg,trim2_en);//设置修调2使能的辅助函数 BF8915A_set_cfgd_trim1_en(nIC, configDReg,trim1_en);//设置修调1使能的辅助函数 BF8915A_set_cfgd_err_t_sel_m(nIC, configDReg,err_t_sel_m);//设置监测模式下发生异常,上报的间隔时间的辅助函数 BF8915A_set_cfgd_vd33t_on_m(nIC, configDReg,vd33t_on_m);//设置配置寄存器组D变量的辅助函数 } /*! \brief Write the BF8915A CFGRA(写BF8915A的配置寄存器组A) \param[in] total_ic : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configAData: A two dimensional array of the configuration data that will be written(将要写入配置数据的二维数组) \retval none */ void BF8915A_wrcfga(uint8_t total_ic, ConfigA_TypeDef configAData[]) { uint8_t cmd[2] = {0x00 , 0x01};//发送写BF8915A的配置寄存器组A指令的高低共16位 uint8_t write_count = 0;//数组计数器,最大为TOTAL_IC * 0x6U uint8_t c_ic = 0;//当前正在写入数组的8915A芯片序号 uint8_t current_ic = 0;//current_ic is used as the IC counter(当前IC(8915A)用作IC(8915A)计数器) uint8_t dataTemp = 0;//计数器,每6次一循环,用于计数每个寄存器组当前循环到的寄存器 for (current_ic = 0; current_ic> 0x4U); //CFGAR5的8位和CFGAR4的高4位,将CFGAR4的高4位放入12~9位,过压阈值 configAData[current_ic].rx_pec_match = configAArray[current_ic].rx_pec_match;//每个配置寄存器组A中的检错码是否匹配 } return(pec_error);//回传检查检错码的值 } /*! \brief Reads the BF8915A CFGRB register(读BF8915A的配置寄存器组B) \param[in] total_ic : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configBData: A two dimensional array that the function stores the read configuration data(该函数存储读取的是配置数据的二维数组) \retval pec_error */ uint8_t BF8915A_rdcfgb(uint8_t total_ic, ConfigB_TypeDef configBData[] ) { uint8_t cmd[2]= {0x00 , 0x06};//发送读BF8915A的配置寄存器组B指令的高低共16位 //Reg_TypeDef configBArray[TOTAL_IC];//定义一个结构体为Reg_TypeDef的数据结构B数组,用于存储指令数据 uint8_t read_buffer[256];//存储SPI端口读取的数据 的数组 uint8_t pec_error = 0;//检查检错码 uint16_t data_pec;//收到的每个配置寄存器组B中的PEC(检错码) uint16_t calc_pec;//计算收到的每个配置寄存器组B中指令数据的PEC(检错码) uint8_t c_ic = 0;//当前正在读入数组的8915A芯片序号 uint8_t current_ic = 0;//current_ic is used as the IC counter(当前IC(8915A)用作IC(8915A)计数器) uint8_t byte=0; //计数器,每8次一循环,用于计数每个寄存器组B中当前循环到的寄存器以及它的PEC(检错码) pec_error = BF8915A_read(total_ic, cmd, read_buffer);//执行写BF8915A命令和读数据,并回传检查错误码是否正确 for (current_ic = 0; current_ic> 0x4U;//CFGBR2的高4位,主动均衡占空比选择 configBData[current_ic].dcto = configBArray[current_ic].rx_data[2] & 0x0FU;//CFGBR2的低4位,放电定时溢出值配置 configBData[current_ic].vuv_bl_th = (uint16_t)configBArray[current_ic].rx_data[3] + (((uint16_t)(configBArray[current_ic].rx_data[4] & 0x0F)) << 0x8U); //CFGBR3的8位和CFGBR4的低4位,将CFGBR1的低4位放入12~9位,均衡欠压阈值 configBData[current_ic].dtmen = (BOOLEAN)((configBArray[current_ic].rx_data[4] & 0x10U) == 0x10U);//CFGBR4的第5位,使能放电监测器 configBData[current_ic].rx_pec_match = configBArray[current_ic].rx_pec_match;//每个配置寄存器组B中的检错码是否匹配 } return(pec_error);//回传检查检错码的值 } /*! \brief Reads the BF8915A CFGRC register(读BF8915A的配置寄存器组C) \param[in] total_ic : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configCData: A two dimensional array that the function stores the read configuration data(该函数存储读取的是配置数据的二维数组) \retval none */ uint8_t BF8915A_rdcfgc(uint8_t total_ic, ConfigC_TypeDef configCData[] ) { uint8_t cmd[2]= {0x00 , 0x07};//发送读BF8915A的配置寄存器组C指令的高低共16位 //Reg_TypeDef configCArray[TOTAL_IC];//定义一个结构体为Reg_TypeDef的数据结构C数组,用于存储指令数据 uint8_t read_buffer[256];//存储SPI端口读取的数据 的数组 uint8_t pec_error = 0;//检查检错码 uint16_t data_pec;//收到的每个配置寄存器组C中的PEC(检错码) uint16_t calc_pec;//计算收到的每个配置寄存器组C中指令数据的PEC(检错码) uint8_t c_ic = 0;//当前正在读入数组的8915A芯片序号 uint8_t current_ic = 0;//current_ic is used as the IC counter(当前IC(8915A)用作IC(8915A)计数器) uint8_t byte=0;//计数器,每8次一循环,用于计数每个寄存器组B中当前循环到的寄存器以及它的PEC(检错码) pec_error = BF8915A_read(total_ic, cmd, read_buffer);//执行写BF8915A命令和读数据,并回传检查错误码是否正确 for (current_ic = 0; current_ic> 0x04U); //CFGCR1的高4位和CFGCR2的8位,将CFGCR1高4位放入低4位,将CFGCR2的8位放入12~5位,监测模式下,过压阈值 configCData[current_ic].itov_m_th = configCArray[current_ic].rx_data[3] + (((uint16_t)(configCArray[current_ic].rx_data[4] & 0x0F)) << 0x8U); //CFGBC3的8位和CFGCR1的低4位,将CFGCR4的低4位放入12~9位,监测模式下,内部过温阈值 configCData[current_ic].extov_m_th = (((uint16_t)configCArray[current_ic].rx_data[5]) << 0x4U) + ((configCArray[current_ic].rx_data[4] & 0xF0) >> 0x04U); //CFGCR4的高4位和CFGCR5的8位,将CFGCR4高4位放入低4位,将CFGCR5的8位放入12~5位,监测模式下,外部过温阈值 configCData[current_ic].rx_pec_match = configCArray[current_ic].rx_pec_match;//每个配置寄存器组C中的检错码是否匹配 } return(pec_error);//回传检查检错码的值 } /*! \brief Reads the BF8915A CFGRD register(读BF8915A的配置寄存器组D) \param[in] total_ic : Number of ICs in the system(系统中IC(8915A)的数量) \param[in] configDData: A two dimensional array that the function stores the read configuration data(该函数存储读取的是配置数据的二维数组) \retval none */ uint8_t BF8915A_rdcfgd(uint8_t total_ic, ConfigD_TypeDef configDData[] ) { uint8_t cmd[2]= {0x00 , 0x08};//发送读BF8915A的配置寄存器组D指令的高低共16位 //Reg_TypeDef configDArray[TOTAL_IC];//定义一个结构体为Reg_TypeDef的数据结构D数组,用于存储指令数据 uint8_t read_buffer[256] = {0};//存储SPI端口读取的数据 的数组 uint8_t pec_error = 0;//检查检错码 uint16_t data_pec;//收到的每个配置寄存器组D中的PEC(检错码) uint16_t calc_pec;//计算收到的每个配置寄存器组D中指令数据的PEC(检错码) uint8_t c_ic = 0;//当前正在读入数组的8915A芯片序号 uint8_t current_ic = 0;//current_ic is used as the IC counter(当前IC(8915A)用作IC(8915A)计数器) uint8_t byte=0; //计数器,每8次一循环,用于计数每个寄存器组B中当前循环到的寄存器以及它的PEC(检错码) pec_error = BF8915A_read(total_ic, cmd, read_buffer);//执行写BF8915A命令和读数据,并回传检查错误码是否正确 for (current_ic = 0; current_ic> 0x4U;//CFGDR4的高4位,ADC测量第2~n个通道ADC初始化时间 configDData[current_ic].adc_init_t1 = configDArray[current_ic].rx_data[4] & 0x0F;//CFGDR4的低4位,ADC测量第1个通道ADC初始化时间 configDData[current_ic].trim2_en = (BOOLEAN)((configDArray[current_ic].rx_data[5] & 0x80) == 0x80U);//CFGDR5的第8位,修调2使能 configDData[current_ic].trim1_en = (BOOLEAN)((configDArray[current_ic].rx_data[5] & 0x40) == 0x40U);//CFGDR5的第7位,修调1使能 configDData[current_ic].err_t_sel_m = (configDArray[current_ic].rx_data[5] & 0x30) >> 0x4U; //CFGDR5的第6~5位,监测模式下发生异常,上报的间隔时间 configDData[current_ic].vd33t_on_m = configDArray[current_ic].rx_data[5] & 0x0F;//CFGDR5的低4位,监测模式下,VREF1和VD33T的启动时间配置 configDData[current_ic].rx_pec_match = configDArray[current_ic].rx_pec_match;//每个配置寄存器组D中的检错码是否匹配 } return(pec_error);//回传检查检错码的值 } /*! \brief ADCV CMD(电池电压ADC转换指令) \param[in] CLKSEL: CLKSEL_2M \param[in] OSR : OSR_64 、OSR_128、OSR_256、OSR_512(ADC过采样频率选择:0、1、2、3) \param[in] DISCP : DISCP_DISABLE、DISCP_ENABLE(放电允许位:放电允许位写0和1) \param[in] CSEL : CSEL_CH_ALL、CSEL_CH_1and9、CSEL_CH_2and10、CSEL_CH_3and11、CSEL_CH_4and12 CSEL_CH_5and13、CSEL_CH_6and14、CSEL_CH_7and15、CSEL_CH_8and16 (ADC转换的电池选择:所有电池(0)、电池1和9(1)、电池2和10(2)、电池3和11(3)、电池4和12(4) 电池5和13(5)、电池6和14(6)、电池7和15(7)、电池8和16(8)) \retval none */ void BF8915A_adcv(uint8_t CLKSEL, uint8_t OSR, uint8_t DISCP, uint8_t CSEL ) { uint8_t cmd[2] = {0U};//初始化数组cmd[] uint8_t clksel_bits = 0x0U;//设置CLKSEL的2个位 的变量 clksel_bits = (CLKSEL & 0x02) >> 1;//设置CLKSEL[1] cmd[0] = clksel_bits + (CMD_ADCV << 0x1U);//发送指令的高8位,#define CMD_ADCV 0x1U clksel_bits = (CLKSEL & 0x01) << 7;//设置CLKSEL[0] cmd[1] = clksel_bits | (OSR<<5) | (DISCP<<4) | CSEL;//发送指令的低8位,详情请参考规格书中 操作指令配置 ADCV 的指令描述 BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief CVST CMD(电池电压自测试命令) \param[in] CLKSEL: CLKSEL_2M \param[in] OSR : OSR_64 、OSR_128、OSR_2566、OSR_512(ADC过采样频率选择:0、1、2、3) \param[in] SFTEST: SELFTEST_6666 SELFTEST_9999(自测试模式选择:自测试1 自测试2) \retval none */ void BF8915A_cvst(uint8_t CLKSEL, uint8_t OSR, uint8_t SFTEST ) { uint8_t cmd[2] = {0U};//初始化数组cmd[] uint8_t clksel_bits = 0x0U;//设置CLKSEL的2个位 的变量 clksel_bits = (CLKSEL & 0x02) >> 1;//设置CLKSEL[1] cmd[0] = clksel_bits + (CMD_CVST << 0x1U);//发送指令的高8位,#define CMD_CVST 0x03U clksel_bits = (CLKSEL & 0x01) << 7;//设置CLKSEL[0] cmd[1] = clksel_bits | (OSR<<5) | (SFTEST<<4);//发送指令的低8位,详情请参考规格书中 操作指令配置 CVST 的指令描述 BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief ADOL CMD(电池重叠单元测量指令) \param[in] CLKSEL: CLKSEL_2M \param[in] OSR : OSR_64 、OSR_128、OSR_256、OSR_512(ADC过采样频率选择:0、1、2、3) \param[in] DISCP : DISCP_DISABLE、DISCP_ENABLE (放电允许位:放电允许位写0和1) \retval none */ void BF8915A_adol(uint8_t CLKSEL, uint8_t OSR, uint8_t DISCP ) { uint8_t cmd[2] = {0U};//初始化数组cmd[] uint8_t clksel_bits = 0x0U;//设置CLKSEL的2个位 的变量 clksel_bits = (CLKSEL & 0x02) >> 1;//设置CLKSEL[1] cmd[0] = clksel_bits + (CMD_ADOL << 0x1U);//发送指令的高8位,#define CMD_ADOL 0x04U clksel_bits = (CLKSEL & 0x01) << 7;//设置CLKSEL[0] cmd[1] = clksel_bits | (OSR<<5) | (DISCP<<4) | 0x01U;//发送指令的低8位,详情请参考规格书中 操作指令配置 ADOL 的指令描述 BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief ADGP CMD(GPIO ADC转换指令) \param[in] CLKSEL: CLKSEL_2M \param[in] OSR : OSR_64 、OSR_128、OSR_256、OSR_512(ADC过采样频率选择) \param[in] GSEL : GSEL_CH_ALL、 GSEL_CH_GPIO0、GSEL_CH_GPIO1、GSEL_CH_GPIO2、GSEL_CH_GPIO3 GSEL_CH_VD33T、GSEL_CH_GPIO4、GSEL_CH_GPIO5、GSEL_CH_GPIO6、GSEL_CH_GPIO7 (ADC转换的GPIO选择 :所有GPIO0~GPIO7,VD33T、GPIO0、GPIO1、GPIO2、GPIO3 VD33T、GPIO4、GPIO5、GPIO6、GPIO7) \retval none */ void BF8915A_adgp(uint8_t CLKSEL, uint8_t OSR, uint8_t GSEL ) { uint8_t cmd[2] = {0U};//初始化数组cmd[] uint8_t clksel_bits = 0x0U;//设置CLKSEL的2个位 的变量 clksel_bits = (CLKSEL & 0x02) >> 1;//设置CLKSEL[1] cmd[0] = clksel_bits + (CMD_ADGP << 0x1U);//发送指令的高8位,#define CMD_ADGP 0x05U clksel_bits = (CLKSEL & 0x01) << 7;//设置CLKSEL[0] cmd[1] = clksel_bits | (OSR<<5) | GSEL;//发送指令的低8位,详情请参考规格书中 操作指令配置 ADGP 的指令描述 BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief GPST CMD(GPIO输入自测试指令) \param[in] CLKSEL: CLKSEL_2M \param[in] OSR : OSR_64 、OSR_128、OSR_256、OSR_512(ADC过采样频率选择:0、1、2、3) \param[in] SFTEST: SELFTEST_6666 SELFTEST_9999(自测试模式选择:自测试1 自测试2) \retval none */ void BF8915A_gpst(uint8_t CLKSEL, uint8_t OSR, uint8_t SFTEST ) { uint8_t cmd[2] = {0U};//初始化数组cmd[] uint8_t clksel_bits = 0x0U;//设置CLKSEL的2个位 的变量 clksel_bits = (CLKSEL & 0x02) >> 1;//设置CLKSEL[1] cmd[0] = clksel_bits + (CMD_GPST << 0x1U);//发送指令的高8位,#define CMD_GPST 0x07U clksel_bits = (CLKSEL & 0x01) << 7;//设置CLKSEL[0] cmd[1] = clksel_bits | (OSR<<5) | (SFTEST<<4);//发送指令的低8位,详情请参考规格书中 操作指令配置 GPST 的指令描述 BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief ADSTAT CMD(测量内部设备参数指令) \param[in] CLKSEL: CLKSEL_2M \param[in] OSR : OSR_64 、OSR_128、OSR_256、OSR_512(ADC过采样频率选择:0、1、2、3) \param[in] STSEL : STATA、STATB、STATC、STATD(ADC转换的内部参数选择) \retval none */ void BF8915A_adstat(uint8_t CLKSEL, uint8_t OSR, uint8_t STSEL ) { uint8_t cmd[2] = {0U};//初始化数组cmd[] uint8_t clksel_bits = 0x0U;//设置CLKSEL的2个位 的变量 clksel_bits = (CLKSEL & 0x02) >> 1;//设置CLKSEL[1] cmd[0] = clksel_bits + (CMD_ADSTAT << 0x1U);//发送指令的高8位,#define CMD_ADSTAT 0x08U clksel_bits = (CLKSEL & 0x01) << 7;//设置CLKSEL[0] cmd[1] = clksel_bits | (OSR<<5) | STSEL;//发送指令的低8位,详情请参考规格书中 操作指令配置 ADSTAT 的指令描述 BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief STATST CMD(自测试内部设备参数指令) \param[in] CLKSEL: CLKSEL_2M \param[in] OSR : OSR_64 、OSR_128、OSR_256、OSR_512(ADC过采样频率选择:0、1、2、3) \param[in] SFTEST: SELFTEST_6666 SELFTEST_9999(自测试模式选择:自测试1 自测试2) \retval none */ void BF8915A_statst(uint8_t CLKSEL, uint8_t OSR, uint8_t SFTEST ) { uint8_t cmd[2] = {0U};//初始化数组cmd[] uint8_t clksel_bits = 0x0U;//设置CLKSEL 位 的变量 clksel_bits = (CLKSEL & 0x02) >> 1;//设置CLKSEL[1] cmd[0] = clksel_bits + (CMD_STATST << 0x1U);//发送指令的高8位,#define CMD_STATST 0x09U clksel_bits = (CLKSEL & 0x01) << 7;//设置CLKSEL[0] cmd[1] = clksel_bits | (OSR<<5) | (SFTEST<<4);//发送指令的低8位,详情请参考规格书中 操作指令配置 CMD_STATST 的指令描述 BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief ADCVGP CMD(测量电池电压和GPIO输入指令) \param[in] CLKSEL: CLKSEL_2M \param[in] OSR : OSR_64 、OSR_128、OSR_256、OSR_512(ADC过采样频率选择:0、1、2、3) \param[in] DISCP : DISCP_DISABLE、DISCP_ENABLE(放电允许位:放电允许位写0和1) \retval none */ void BF8915A_adcvgp(uint8_t CLKSEL, uint8_t OSR, uint8_t DISCP ) { uint8_t cmd[2] = {0U};//初始化数组cmd[] uint8_t clksel_bits = 0x0U;//设置CLKSEL的2个位 的变量 clksel_bits = (CLKSEL & 0x02) >> 1;//设置CLKSEL[1] cmd[0] = clksel_bits + (CMD_ADCVGP << 0x1U);//发送指令的高8位,#define CMD_ADCVGP 0x0aU clksel_bits = (CLKSEL & 0x01) << 7;//设置CLKSEL[0] cmd[1] = clksel_bits | (OSR<<5) | (DISCP<<4);//发送指令的低8位,详情请参考规格书中 操作指令配置 CMD_ADCVGP 的指令描述 BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief MNT CMD(监测指令) \param[in] CLKSEL: CLKSEL_2M \param[in] OSR : OSR_64 、OSR_128、OSR_256、OSR_512(ADC过采样频率选择:0、1、2、3) \param[in] MNMOD : MNMOD_DISABLE、MNMOD_1、MNMOD_2、MNMOD_3(监测模式选择:不进入监测模式,指令无效(00)、模式1(01)、模式2(02)、模式3(03)) \param[in] STRMN : STRMN_ENABLE、STRMN_DISABLE(监测模式使能:开启监测模式(1)、关闭监测模式(2)) \param[in] BLEN : BLEN_ON、BLEN_OFF (均衡开关总控制信号2:关闭(0)、开启(1)) \retval none */ void BF8915A_mnt(uint8_t CLKSEL, uint8_t OSR, uint8_t MNMOD, uint8_t STRMN, uint8_t BLEN ) { uint8_t cmd[2] = {0U};//初始化数组cmd[] uint8_t clksel_bits = 0x0U;//设置CLKSEL的2个 位的变量 clksel_bits = (CLKSEL & 0x02) >> 1;//设置CLKSEL[1] cmd[0] = clksel_bits + (CMD_MNT << 0x1U);//发送指令的高8位,#define CMD_MNT 0x0cU clksel_bits = (CLKSEL & 0x01) << 7;//设置CLKSEL[0] cmd[1] = clksel_bits | (OSR<<5) | (MNMOD<<3) | (STRMN << 2) | BLEN ;//发送指令的低8位,详情请参考规格书中 操作指令配置 CMD_MNT 的指令描述 BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief STRBL CMD(被动均衡指令) \param[in] CLKSEL: CLKSEL_2M \param[in] OSR : OSR_64 、OSR_128、OSR_256、OSR_512(ADC过采样频率选择) \param[in] OESEL : OESEL_ODD、OESEL_EVEN (均衡放电电池奇偶选择:奇数节(0)、偶数节(1)) \param[in] BLEN : BLEN_ON、BLEN_OFF(均衡开关总控制信号 2:开启(1)、关闭(0)) \retval none */ void BF8915A_strbl(uint8_t CLKSEL, uint8_t OSR, uint8_t OESEL, uint8_t BLEN ) { uint8_t cmd[2] = {0U};//初始化数组cmd[] uint8_t clksel_bits = 0x0U;//设置CLKSEL的2个位 的变量 clksel_bits = (CLKSEL & 0x02) >> 1;//设置CLKSEL[1] cmd[0] = clksel_bits + (CMD_STRBL << 0x1U);//发送指令的高8位,#define CMD_STRBL 0x0dU clksel_bits = (CLKSEL & 0x01) << 7;//设置CLKSEL[0] cmd[1] = clksel_bits | (OSR<<5) | (OESEL<<4) | BLEN;//发送指令的低8位,详情请参考规格书中 操作指令配置 CMD_STRBL 的指令描述 BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief Reads the raw cell voltage register data(读取原始电池电压寄存器数据) \param[in] reg : Determines which register is read back(确定回读哪个电池电压寄存器) \param[in] total_ic: the Number of ICs in the system(系统中IC(8915A)的数量) \param[in] cellData: Array of the unparsed codes(未解析代码的数组) \retval none */ void BF8915A_rdcv_reg(uint8_t reg, //Determines which cell voltage register is read back(确定回读哪个电池电压寄存器) uint8_t total_ic, uint8_t *cellData ) { const uint8_t REG_LEN = 8; //number of 6 bytes in each ICs register + 2 bytes for the PEC(每个集成电路寄存器中的6字节数加PEC(检错码)的2个字节) uint8_t cmd[4];//初始化数组cmd[] uint16_t cmd_pec;//计算出发送指令的PEC(检错码) cmd[0] = 0x00;//发送指令的高8位 cmd[1] = reg + 0x08U;//发送指令的低8位,详情在8915A.h文件中 电池电压寄存器对应的命令 cmd_pec = pec15_calc(2, cmd);//计算出发送指令的PEC(检错码) cmd[2] = (uint8_t)(cmd_pec >> 8);//发送指令的PEC(检错码)的高八位 cmd[3] = (uint8_t)(cmd_pec);//发送指令的PEC(检错码)的低八位 if (isospi_reverse == FALSE)//判断选择的菊花链通信方向是相对正向还是相对反向 { cs_low();//将片选CS设置为低电平 spi_write_read(cmd,4,cellData,(REG_LEN*total_ic));//使用SPI端口写入和读取设定数量的字节 cs_high();//将片选CS设置为高电平 } else { cs_low_reverse();//将片选CS设置为低电平 spi_write_read(cmd,4,cellData,(REG_LEN*total_ic));//使用SPI端口写入和读取设定数量的字节 cs_high_reverse();//将片选CS设置为高电平 } } /*! \brief reads BF8915A GPIO registers(读取BF8915A的GPIO寄存器) The function reads a single GPIO voltage register and stores the read data in the *data point as a byte array. This function is rarely used outside of the BF8915A_rdgv() command. (该函数读取单个GPIO电压寄存器,并将读取的数据作为字节数组存储在*data数据中。此功能很少在BF8915A_rdgv()命令之外使用。) \param[in] reg : Determines which register is read back(确定回读哪个电池电压寄存器) \param[in] total_ic: the Number of ICs in the system(系统中IC(8915A)的数量) \param[in] gpioData: Array of the unparsed codes(未解析代码的数组) \retval none */ void BF8915A_rdgv_reg(uint8_t reg, uint8_t total_ic, uint8_t *gpioData ) { const uint8_t REG_LEN = 8; // number of 6 bytes in the register + 2 bytes for the PEC(寄存器中的6字节数加上PEC(检错码)的2个字节) uint8_t cmd[4];//初始化数组cmd[] uint16_t cmd_pec;//计算出发送指令的PEC(检错码) cmd[0] = 0x00;//发送指令的高8位 cmd[1] = reg + 0x0EU;//发送指令的低8位,详情在8915A.h文件中 GPIOG电压 cmd_pec = pec15_calc(2, cmd);//计算出发送指令的PEC(检错码) cmd[2] = (uint8_t)(cmd_pec >> 8);//发送指令的PEC(检错码)的高八位 cmd[3] = (uint8_t)(cmd_pec);//发送指令的PEC(检错码)的低八位 if (isospi_reverse == FALSE)//判断选择的菊花链通信方向是相对正向还是相对反向 { cs_low();//将片选CS设置为低电平 spi_write_read(cmd,4,gpioData,(REG_LEN*total_ic));//使用SPI端口写入和读取设定数量的字节 cs_high();//将片选CS设置为高电平 } else { cs_low_reverse();//将片选CS设置为低电平 spi_write_read(cmd,4,gpioData,(REG_LEN*total_ic));//使用SPI端口写入和读取设定数量的字节 cs_high_reverse();//将片选CS设置为高电平 } } /*! \brief Reads BF8915A stat registers(读取BF8915A状态寄存器) \param[in] reg : Determines which register is read back(确定回读哪个寄存器) \param[in] total_ic: the Number of ICs in the system(系统中IC(8915A)的数量) \param[in] statData: Array of the unparsed codes(未解析代码的数组) \retval none */ void BF8915A_rdstat_reg(uint8_t reg, uint8_t total_ic, uint8_t *statData ) { const uint8_t REG_LEN = 8;//number of 6 bytes in the register + 2 bytes for the PEC(寄存器中的6字节数加上PEC(检错码)的2个字节) uint8_t cmd[4];//初始化数组cmd[] uint16_t cmd_pec;//计算出发送指令的PEC(检错码) cmd[0] = 0x00;//发送指令的高8位 cmd[1] = reg + 0x11;//发送指令的低8位,详情在8915A.h文件中 状态寄存器RDSTAT cmd_pec = pec15_calc(2, cmd);//计算出发送指令的PEC(检错码) cmd[2] = (uint8_t)(cmd_pec >> 8);//发送指令的PEC(检错码)的高八位 cmd[3] = (uint8_t)(cmd_pec);//发送指令的PEC(检错码)的低八位 if (isospi_reverse == FALSE)//判断选择的菊花链通信方向是相对正向还是相对反向 { cs_low();//将片选CS设置为低电平 spi_write_read(cmd,4,statData,(REG_LEN*total_ic));//使用SPI端口写入和读取设定数量的字节 cs_high();//将片选CS设置为高电平 } else { cs_low_reverse();//将片选CS设置为低电平 spi_write_read(cmd,4,statData,(REG_LEN*total_ic));//使用SPI端口写入和读取设定数量的字节 cs_high_reverse();//将片选CS设置为高电平 } } /*! \brief Helper function that parses voltage measurement registers(解析电压测量寄存器的辅助函数) \param[in] current_ic: Number of ics in current cycle(当前循环的IC(8915A)数) \param[in] cell_reg : Controls which cell voltage register is read back(控制回读哪个单体电压寄存器) \param[in] cell_data : Number of bytes of data received(接收到数据的字节数,6个数据+2个PEC(检错码)) \param[in] cell_codes: cell voltage value(电池电压值) \param[in] ic_pec : If a PEC error was detected during most recent read cmd(如果在最近的读取cmd(指令)期间检测到PEC(检错码)错误) \retval pec_error */ uint8_t parse_cells(uint8_t current_ic, uint8_t cell_reg, uint8_t cell_data[], uint16_t *cell_codes, uint8_t *ic_pec ) { const uint8_t BYT_IN_REG = 6;//寄存器组中的6个8位寄存器 uint8_t CELL_IN_REG = 3;//每个电压寄存器组中的 3个电压值 uint8_t pec_error = 0;//检查检错码 uint16_t parsed_cell;//单个电压值 uint16_t received_pec;//收到的每个寄存器组中的PEC(检错码) uint16_t data_pec;//计算收到的每个寄存器组中指令数据的PEC(检错码) uint8_t data_counter = current_ic*NUM_RX_BYT; //data counter(数据计数器) uint8_t current_cell = 0;//每个电压寄存器组当前循环到的单体电池电压 for (current_cell = 0; current_cell < CELL_IN_REG; current_cell++) // This loop parses the read back data into cell voltages, it loops once for each of the 3 cell voltage codes in the register { //(这个循环将读回的数据解析成电压,对寄存器中的每3个电压码循环一次) parsed_cell = cell_data[data_counter] + ((uint16_t)cell_data[data_counter + 1] << 8);//Each cell codes is received as two bytes and is combined to create the parsed cell voltage code //(每个电压代码被接收为两个字节,并且被组合以创建解析的单体电压代码) cell_codes[current_cell + ((cell_reg - 1) * CELL_IN_REG)] = parsed_cell;//将解析出的单个电压码依次存放在数组cell_codes[]中 data_counter = data_counter + 2;//Because cell voltage codes are two bytes the data counter must increment by two for each parsed cell code //(因为单体电压码是两个字节,所以对于每个解析的电池码,数据计数器必须增加2) if(cell_reg == CVFR)//#define CVFR 0x06U { current_cell = 0x3U;//存放电池电压的结构体数组有16个元素,此处代码为了防止数组解析CVFR(电池电压寄存器组F)时,数组溢出问题 } } if(cell_reg == CVFR)//若寄存器为CVFR,则只需循环一次即可跳出循环 { data_counter = data_counter + 4; } 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 //(接收到的current_ic(当前IC(8915A)数量)的PEC(检错码)作为6个单体电压数据字节之后的第7个和第8个字节发送) data_pec = pec15_calc(BYT_IN_REG, &cell_data[(current_ic) * NUM_RX_BYT]);//计算接收回来的寄存器组(6个8位寄存器)中的PEC(检错码) if (received_pec != data_pec)//检查检错码是否匹配 { pec_error = 1; //The pec_error variable is simply set 1 if any PEC errors(如果有任何pec错误,pec_error变量简单地设置为1) ic_pec[cell_reg-1]=1;//将cellVoltage[c_ic].pec_match[0]中的值置1 } else { ic_pec[cell_reg-1]=0;//检错码正确,将cellVoltage[c_ic].pec_match[0]中的值置0 } data_counter=data_counter+2;//Because the transmitted PEC code is 2 bytes long the data_counter must be incremented by 2 bytes to point to the next ICs state voltage data //(因为传输的PEC(检错码)代码是2字节长,所以数据计数器必须增加2字节才能指向下一个8915A状态电压数据) return(pec_error);//回传检查检错码的值 } /*! \brief Reads and parses the BF8915A cell voltage registers(读取并解析BF8915A电池电压寄存器) \param[in] reg : Controls which cell voltage register is read back(控制回读哪个电池电压寄存器) \param[in] total_ic : the Number of ICs in the system(系统中IC(8915A)的数量) \param[in] CellVoltage_TypeDef: CellVoltage Struct(电池电压结构) \retval the time of pec_error(pec_error的数) */ uint8_t BF8915A_rdcv(uint8_t reg, uint8_t total_ic, CellVoltage_TypeDef *cellVoltage ) { uint8_t pec_error = 0;//检查检错码 uint8_t *cell_data;//初始化一个8位的指针cell_data uint8_t c_ic = 0;//当前正在读入数组的8915A芯片序号 uint8_t cell_reg = 1;//电池电压寄存器计数器 uint8_t current_ic = 0;//current_ic is used as the IC counter(当前IC(8915A)用作IC(8915A)计数器) cell_data = (uint8_t *) malloc((NUM_RX_BYT*total_ic)*sizeof(uint8_t));//#define NUM_RX_BYT 0x8U(接收到数据的字节数,6个字节数据+2个PEC(检错码)字节) if (reg == 0)//如果选择读取所有电池电压 { for (cell_reg = 1; cell_reg < NUM_CV_REG + 1; cell_reg++) //#define NUM_CV_REG 6U,对每个BF8915A电池电压寄存器执行一次 { BF8915A_rdcv_reg(cell_reg, total_ic,cell_data );//读取原始电池电压寄存器数据 for (current_ic = 0; current_ic < total_ic; current_ic++)//该循环作用为读取并解析每个BF8915A所选择的电池电压寄存器 { if (isospi_reverse == FALSE)//判断选择的菊花链通信方向是相对正向还是相对反向 { c_ic = current_ic;//选择正序将电池电压放入数组 } else { c_ic = total_ic - current_ic - 1;//选择倒序将电池电压放入数组 } pec_error = pec_error + parse_cells(current_ic,cell_reg, cell_data, &cellVoltage[c_ic].cellVoltage[0], &cellVoltage[c_ic].pec_match[0]);//解析电压测量寄存器的辅助函数,并回传检查检错码的值 } } } else//如果不选择读取所有电池电压 { BF8915A_rdcv_reg(reg, total_ic,cell_data);//读取原始电池电压寄存器数据 for (current_ic = 0; current_ic 0) && (stat_reg < 4))//如果读取的寄存器为STATA、STATB、STATC { for (current_gpio = 0; current_gpio < GPIO_IN_REG; current_gpio++) // This loop parses the read back data into state voltages, it loops once for each of the 3 state voltage codes in the register { //(这个循环将读回的数据解析为状态电压,它对寄存器中的3个状态电压代码中的每一个循环一次) parsed_stat = dataPtr[data_counter] + (dataPtr[data_counter+1]<<8);//Each state codes is received as two bytes and is combined to create the parsed state voltage code //(每个状态码被接收为两个字节,并且被组合来创建解析的状态电压代码) stateReg[c_ic].stat_codes[current_gpio + (stat_reg - 1) * GPIO_IN_REG] = parsed_stat;//将解析出的单个电压码依次存放在数组stateReg[c_ic].stat_codes[]中 data_counter=data_counter+2;//Because cell voltage codes are two bytes the data counter must increment by two for each parsed cell code //(因为单体电压码是两个字节,所以对于每个解析的电池码,数据计数器必须增加2) if((reg == STATC) &&(current_gpio == 0x1U)) //此处判断未了防止读STATC时,导致StateReg_TypeDef结构体中stat_codes[]数组溢出问题 { current_gpio = GPIO_IN_REG;//寄存器为STATC且已经循环到第二次,跳过一次循环 data_counter = data_counter+2;//Because cell voltage codes are two bytes the data counter must increment by two for each parsed cell code //(因为单体电压码是两个字节,所以对于每个解析的电池码,数据计数器必须增加2) } } } else if (stat_reg == 4)//如果读取的寄存器为STATD { stateReg[c_ic].uvOvFlags[0] = dataPtr[data_counter++];//STDR0的8位,Cell1~Cell4的欠/过压标志 stateReg[c_ic].uvOvFlags[1] = dataPtr[data_counter++];//STDR1的8位,Cell5~Cell8的欠/过压标志 stateReg[c_ic].uvOvFlags[2] = dataPtr[data_counter++];//STDR2的8位,Cell9~Cell12的欠/过压标志 stateReg[c_ic].uvOvFlags[3] = dataPtr[data_counter++];//STDR3的8位,Cell12~Cell16的欠/过压标志 stateReg[c_ic].cfg_err = ((dataPtr[data_counter] & 0x40) >> 0x6U);//STDR4的第7位,配置字校验出错标志(包括奇偶异或校验和ECC校验) stateReg[c_ic].pec_err = ((dataPtr[data_counter] & 0x20) >> 0x5U);//STDR4的第6位,指令数据的PEC校验出错标志 stateReg[c_ic].extov = ((dataPtr[data_counter] & 0x10) >> 0x4U);//STDR4的第5位,监测模式下,外部温度(gpio)过温标志 stateReg[c_ic].itov = ((dataPtr[data_counter] & 0x08) >> 0x3U);//STDR4的第4位,监测模式下,内部温度(vtemp)过温标志 stateReg[c_ic].htov2 = ((dataPtr[data_counter] & 0x04) >> 0x2U);//STDR4的第3位,硬件温度(95℃)过温标志 stateReg[c_ic].htov1 = ((dataPtr[data_counter] & 0x02) >> 0x1U);//STDR4的第2位,硬件温度(125℃)过温标志 stateReg[c_ic].mux_fail = (dataPtr[data_counter++] & 0x01);//STDR4的第1位,开关译码测试结果 stateReg[c_ic].mode_state = ((dataPtr[data_counter] & 0xC0U) >> 0x6U);//STDR5的第8~7位,模式状态寄存器 stateReg[c_ic].rst_state = (dataPtr[data_counter++] & 0x3FU);//STDR5的第6~1位,复位标志寄存器 stateReg[c_ic].cellOvFlag = 0x00U;//电池欠压标志位,每个位用来标志每个电池的欠压标志位 stateReg[c_ic].cellUvFlag = 0x00U;//电池过压标志位,每个位用来标志每个电池的过压标志位 for(stateD_byte = 0;stateD_byte < 4;stateD_byte ++)//状态寄存器的字节循环 { for(stateD_bit = 0;stateD_bit < 4;stateD_bit ++)//状态寄存器的位循环 { if((stateReg[c_ic].uvOvFlags[stateD_byte] & (0x01 << (stateD_bit * 0x2U))) == (0x01 << stateD_bit * 0x2U))//判断该Cellx的欠压标志位是否为1 stateReg[c_ic].cellUvFlag |= 0x0001 << ((stateD_byte * 0x4U) + stateD_bit);//该Cellx的欠压标志位置1 else stateReg[c_ic].cellUvFlag &= ~(0x0001 << ((stateD_byte * 0x4U) + stateD_bit));//该Cellx的欠压标志位置0 if((stateReg[c_ic].uvOvFlags[stateD_byte] & (0x01 << (stateD_bit * 0x2U + 0x1U))) == (0x01 << (stateD_bit * 0x2U + 0x1U)))//判断该Cellx的过压标志位是否为1 stateReg[c_ic].cellOvFlag |= 0x0001 << ((stateD_byte * 0x4U) + stateD_bit);//该Cellx的过压标志位置1 else stateReg[c_ic].cellOvFlag &= ~(0x0001 << ((stateD_byte * 0x4U) + stateD_bit));//该Cellx的过压标志位置0 } } } received_pec = (dataPtr[data_counter]<<8)+ dataPtr[data_counter+1];//接收到的当前IC(8915A)的PEC(检错码)作为6个状态电压数据字节之后的第7个和第8个字节发送 data_pec = pec15_calc(BYT_IN_REG, &dataPtr[current_ic*NUM_RX_BYT]);//计算接收回来的寄存器组(6个8位寄存器)中的PEC(检错码) if (received_pec != data_pec)//检查检错码是否匹配 { pec_error = 1; //如果有任何PEC(检错码)错误,pec_error变量简单地设置为1 stateReg[c_ic].pec_match[stat_reg-1]=1;//stateReg[c_ic].pec_match[stat_reg-1]中的检错码值置1 } else { stateReg[c_ic].pec_match[stat_reg-1]=0;//stateReg[c_ic].pec_match[stat_reg-1]中的检错码值置0 } data_counter = data_counter + 2;//Because the transmitted PEC code is 2 bytes long the data_counter must be incremented by 2 bytes to point to the next ICs state voltage data //(因为传输的PEC(检错码)代码是2字节长,所以数据计数器必须增加2字节才能指向下一个集成电路状态电压数据) } } } else { BF8915A_rdstat_reg(reg, total_ic, dataPtr);//Reads the raw status register data into the dataPtr[] array(将原始状态寄存器数据读入dataPtr[]数组) for (current_ic = 0 ; current_ic < total_ic; current_ic++) //该循环作用为读取并解析每个BF8915A所选择的状态电压寄存器 { if (isospi_reverse == FALSE)//判断选择的菊花链通信方向是相对正向还是相对反向 { c_ic = current_ic;//选择正序将电池电压放入数组 } else { c_ic = total_ic - current_ic - 1;//选择倒序将电池电压放入数组 } if ((reg > 0) && (reg <4))//如果读取的寄存器为STATA、STATB、STATC { for (current_gpio = 0; current_gpio< GPIO_IN_REG; current_gpio++) //This loop parses the read back data into state voltages, it loops once for each of the 3 state voltage codes in the register { //(这个循环将读回的数据解析为状态电压,它对寄存器中的3个状态电压码中的每一个循环一次) parsed_stat = dataPtr[data_counter] + (dataPtr[data_counter+1]<<8);//Each state codes is received as two bytes and is combined to create the parsed state voltage code //(每个状态码被接收为两个字节,并且被组合来创建解析的状态电压代码) stateReg[c_ic].stat_codes[current_gpio + (reg - 1) * GPIO_IN_REG] = parsed_stat; data_counter = data_counter+2;//Because state voltage codes are two bytes the data counter must increment by two for each parsed state voltage code //(因为状态电压码是两个字节,所以对于每个解析的状态电压码,数据计数器必须增加2) if((reg == STATC) &&(current_gpio == 0x1U)) //此处判断未了防止读STATC时,导致StateReg_TypeDef结构体中stat_codes[]数组溢出问题 { current_gpio = GPIO_IN_REG;//若寄存器为STATC且已经循环到第二次,则跳过一次循环 data_counter = data_counter+2;//Because cell voltage codes are two bytes the data counter must increment by two for each parsed cell code //(因为单体电压码是两个字节,所以对于每个解析的电池码,数据计数器必须增加2) } } } else if (reg == 4)//如果读取的寄存器为STATD { stateReg[c_ic].uvOvFlags[0] = dataPtr[data_counter++];//STDR0的8位,Cell1~Cell4的欠/过压标志 stateReg[c_ic].uvOvFlags[1] = dataPtr[data_counter++];//STDR1的8位,Cell5~Cell8的欠/过压标志 stateReg[c_ic].uvOvFlags[2] = dataPtr[data_counter++];//STDR2的8位,Cell9~Cell12的欠/过压标志 stateReg[c_ic].uvOvFlags[3] = dataPtr[data_counter++];//STDR3的8位,Cell12~Cell16的欠/过压标志 stateReg[c_ic].cfg_err = ((dataPtr[data_counter] & 0x40) >> 0x6U);//STDR4的第7位,配置字校验出错标志(包括奇偶异或校验和ECC校验) stateReg[c_ic].pec_err = ((dataPtr[data_counter] & 0x20) >> 0x5U);//STDR4的第6位,指令数据的PEC校验出错标志 stateReg[c_ic].extov = ((dataPtr[data_counter] & 0x10) >> 0x4U);//STDR4的第5位,监测模式下,外部温度(gpio)过温标志 stateReg[c_ic].itov = ((dataPtr[data_counter] & 0x08) >> 0x3U);//STDR4的第4位,监测模式下,内部温度(vtemp)过温标志 stateReg[c_ic].htov2 = ((dataPtr[data_counter] & 0x04) >> 0x2U);//STDR4的第3位,硬件温度(95℃)过温标志 stateReg[c_ic].htov1 = ((dataPtr[data_counter] & 0x02) >> 0x1U);//STDR4的第2位,硬件温度(125℃)过温标志 stateReg[c_ic].mux_fail = (dataPtr[data_counter++] & 0x01);//STDR4的第1位,开关译码测试结果 stateReg[c_ic].mode_state = ((dataPtr[data_counter] & 0xC0U) >> 0x6U);//STDR5的第8~7位,模式状态寄存器 stateReg[c_ic].rst_state = (dataPtr[data_counter++] & 0x3FU);//STDR5的第6~1位,复位标志寄存器 for(stateD_byte = 0;stateD_byte < 4;stateD_byte ++)//状态寄存器的字节循环 { for(stateD_bit = 0;stateD_bit < 4;stateD_bit ++)//状态寄存器的位循环 { if((stateReg[c_ic].uvOvFlags[stateD_byte] & (0x01 << (stateD_bit * 0x2U))) == (0x01 << stateD_bit * 0x2U))//判断该Cellx的欠压标志位是否为1 stateReg[c_ic].cellUvFlag |= 0x0001 << ((stateD_byte * 0x4U) + stateD_bit);//该Cellx的欠压标志位置1 else stateReg[c_ic].cellUvFlag &= ~(0x0001 << ((stateD_byte * 0x4U) + stateD_bit));//该Cellx的欠压标志位置0 if((stateReg[c_ic].uvOvFlags[stateD_byte] & (0x01 << (stateD_bit * 0x2U + 0x1U))) == (0x01 << (stateD_bit * 0x2U + 0x1U)))//判断该Cellx的过压标志位是否为1 stateReg[c_ic].cellOvFlag |= 0x0001 << ((stateD_byte * 0x4U) + stateD_bit);//该Cellx的过压标志位置1 else stateReg[c_ic].cellOvFlag &= ~(0x0001 << ((stateD_byte * 0x4U) + stateD_bit));//该Cellx的过压标志位置0 } } } received_pec = (dataPtr[data_counter]<<8)+ dataPtr[data_counter+1];//The received PEC for the current_ic is transmitted as the 7th and 8th after the 6 gpio voltage data bytes //(接收到的集成电路计数器的检错码作为6个GPIO电压数据字节之后的第7个和第8个字节发送) data_pec = pec15_calc(BYT_IN_REG, &dataPtr[current_ic*NUM_RX_BYT]);//计算接收回来的寄存器组(6个8位寄存器)中的PEC(检错码) if (received_pec != data_pec)//检查检错码是否匹配 { pec_error = 1;//如果有任何PEC(检错码)错误,pec_error变量简单地设置为1 stateReg[c_ic].pec_match[reg-1]=1;//stateReg[c_ic].pec_match[stat_reg-1]中的检错码值置1 } data_counter = data_counter + 2;//Because the transmitted PEC code is 2 bytes long the data_counter must be incremented by 2 bytes to point to the next ICs state voltage data //(因为传输的PEC(检错码)代码是2字节长,所以数据计数器必须增加2字节才能指向下一个集成电路状态电压数据) } } free(dataPtr);//清空指针 return (pec_error);//回传检查检错码的值 } /*! \brief Clear Cell Register(清除电池电压寄存器) \param[in] none \retval none */ void BF8915A_clrcell(void) { uint8_t cmd[2]= {0x00 , 0x81}; BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief Clear GPIO Register(清除GPIO寄存器) \param[in] none \retval none */ void BF8915A_clrgp(void) { uint8_t cmd[2]= {0x00 , 0x82}; BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief Clear STATE Register(清除状态寄存器) \param[in] none \retval none */ void BF8915A_clrstat(void) { uint8_t cmd[2]= {0x00 , 0x83}; BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 } /*! \brief PLADC CMD(轮询ADC转换状态指令) \param[in] none \retval none */ uint8_t BF8915A_pladc(void) { uint8_t cmd[4];//初始化数组cmd[] uint8_t adc_state = 0xFF;//初始化adc_state uint16_t cmd_pec;//计算出发送指令的PEC(检错码) cmd[0] = 0x00;//发送指令的高8位 cmd[1] = 0x84;//发送指令的低8位 cmd_pec = pec15_calc(2, cmd);//计算出发送指令的PEC(检错码) cmd[2] = (uint8_t)(cmd_pec >> 8);//发送指令的PEC(检错码)的高八位 cmd[3] = (uint8_t)(cmd_pec);//发送指令的PEC(检错码)的低八位 if (isospi_reverse == FALSE)//判断选择的菊花链通信方向是相对正向还是相对反向 { cs_low();//将片选CS设置为低电平 spi_write_array(4,cmd);//将字节数组写入SPI端口 adc_state = SPI1_ReadWriteByte(0xFF);//返回SPI接收到的数据 if(adc_state == 0xff) { cs_high();//将片选CS设置为高电平 } } else { cs_low_reverse();//将片选CS设置为低电平 spi_write_array(4,cmd);//将字节数组写入SPI端口 adc_state = SPI2_ReadWriteByte(0xFF);//返回SPI接收到的数据 if(adc_state == 0xff) { cs_high_reverse();//将片选CS设置为高电平 } } return(adc_state);//回传SPI接收到的数据 } /*! \brief soft reset(软件复位) \param[in] none \retval none */ void BF8915A_softrst(void) { uint8_t cmd[2]= {0x00 , 0x55}; BF8915A_cmd(cmd);//编写BF8915A命令的通用函数。函数为cmd数据计算了检错码 }