parent
009a4d1cf5
commit
fd1027523b
|
@ -77,9 +77,23 @@
|
||||||
#define SRST 0x0027 //Soft reset
|
#define SRST 0x0027 //Soft reset
|
||||||
|
|
||||||
#define DIAGN 0x0715 // Diagnos MUX and Poll Status
|
#define DIAGN 0x0715 // Diagnos MUX and Poll Status
|
||||||
|
|
||||||
|
|
||||||
#define WRCOMM 0x0721 // Write COMM Register Group
|
#define WRCOMM 0x0721 // Write COMM Register Group
|
||||||
#define RDCOMM 0x0722 // Read COMM Register Group
|
#define RDCOMM 0x0722 // Read COMM Register Group
|
||||||
#define STCOMM 0x0723 // Start I2C/SPI Communication
|
#define STCOMM 0x0723 // Start I2C/SPI Communication
|
||||||
|
#define I2C_SEND_START 0b0110 << 4
|
||||||
|
#define I2C_SEND_STOP 0b0001 << 4
|
||||||
|
#define I2C_SEND 0b0000 << 4
|
||||||
|
#define I2C_SEND_NOTRANSFER 0b0111 << 4
|
||||||
|
#define I2C_SEND_ACK 0b0000
|
||||||
|
#define I2C_SEND_NACK 0b1000
|
||||||
|
#define I2C_SEND_NACK_STOP 0b1001
|
||||||
|
#define I2C_RECV_ACK 0b0111
|
||||||
|
#define I2C_RECV_NACK 0b1111
|
||||||
|
#define I2C_RECV_ACK_STOP 0b0001
|
||||||
|
#define I2C_RECV_NACK_STOP 0b1001
|
||||||
|
|
||||||
#define MUTE 0x0028 // Mute Discharge
|
#define MUTE 0x0028 // Mute Discharge
|
||||||
#define UNMUTE 0x0029 // Unmute Discharge
|
#define UNMUTE 0x0029 // Unmute Discharge
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,10 @@ static inline HAL_StatusTypeDef __readCMD(uint16_t command, uint8_t * buffer, si
|
||||||
#define readCMD(command, buffer, buflen) \
|
#define readCMD(command, buffer, buflen) \
|
||||||
__readCMD(command, buffer, buflen, CMD_BUFFER_SIZE(buflen))
|
__readCMD(command, buffer, buflen, CMD_BUFFER_SIZE(buflen))
|
||||||
|
|
||||||
HAL_StatusTypeDef pollCMD(uint16_t command);
|
HAL_StatusTypeDef __pollCMD(uint16_t command, uint8_t waitTime);
|
||||||
|
|
||||||
|
#define pollCMD(command) \
|
||||||
|
__pollCMD(command, (N_BMS * 2) + 1) //poll is only valid after 2 * N_BMS clock cycles, +1 for safety, see datasheet page 55
|
||||||
|
|
||||||
|
|
||||||
void mcuAdbmsCSLow();
|
void mcuAdbmsCSLow();
|
||||||
|
|
|
@ -316,3 +316,75 @@ HAL_StatusTypeDef amsReadCellVoltages(Cell_Module (*module)[N_BMS]) {
|
||||||
|
|
||||||
return HAL_OK;
|
return HAL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Each selected BMS must have a corresponding address, and the data array for that BMS must be at least datalens[i] bytes long
|
||||||
|
HAL_StatusTypeDef amsSendI2C(uint8_t addresses[static N_BMS], uint8_t * data[static N_BMS], uint8_t datalens[static N_BMS], uint32_t bms_mask) {
|
||||||
|
uint8_t buffer[CMD_BUFFER_SIZE(COMM_GROUP_SIZE)] = {};
|
||||||
|
|
||||||
|
//COMM register works in 3 bytes max per go, interleaved with control information
|
||||||
|
|
||||||
|
uint8_t max_datalen = 0;
|
||||||
|
for (size_t i = 0; i < N_BMS; i++) {
|
||||||
|
if (datalens[i] > max_datalen) {
|
||||||
|
max_datalen = datalens[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < N_BMS; i++) {
|
||||||
|
size_t offset = BUFFER_BMS_OFFSET(i, COMM_GROUP_SIZE);
|
||||||
|
|
||||||
|
if (!(bms_mask & (1 << i))) {
|
||||||
|
buffer[offset + 0] = I2C_SEND_NOTRANSFER;
|
||||||
|
buffer[offset + 2] = I2C_SEND_NOTRANSFER;
|
||||||
|
buffer[offset + 4] = I2C_SEND_NOTRANSFER;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t packet_count = ((max_datalen + 1) / 3) + ((max_datalen + 1) % 3 != 0); //number of 3 byte packets needed to send all data
|
||||||
|
|
||||||
|
for (size_t i = 0; i < (packet_count * 3); i++) { //i - 1 is the number of data bytes sent so far (1 byte for the address)
|
||||||
|
for (size_t j = 0; j < N_BMS; j++) {
|
||||||
|
size_t offset = BUFFER_BMS_OFFSET(j, COMM_GROUP_SIZE);
|
||||||
|
if (!(bms_mask & (1 << j))) continue; //skip BMS that are not selected
|
||||||
|
|
||||||
|
if (i == 0) {
|
||||||
|
buffer[offset + 0] = I2C_SEND_START;
|
||||||
|
buffer[offset + 1] = addresses[j];
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//add data to the buffer
|
||||||
|
|
||||||
|
//case 1: the last group of 3 bytes contained the last data byte, so we need to send a stop
|
||||||
|
if (datalens[j] - (int)i == -1) {
|
||||||
|
buffer[offset + ((i % 3) * 2)] = I2C_SEND_STOP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//case 2: we are more than one byte past the end, so we don't need to send any data
|
||||||
|
if (datalens[j] - (int)i < -1) {
|
||||||
|
buffer[offset + ((i % 3) * 2)] = I2C_SEND_NOTRANSFER;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
//case 3: we are still sending data
|
||||||
|
buffer[offset + ((i % 3) * 2)] = I2C_SEND;
|
||||||
|
buffer[offset + ((i % 3) * 2) + 1] = data[j][i - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
//send the data
|
||||||
|
if (i % 3 == 0 && i != 0) {
|
||||||
|
CHECK_RETURN(writeCMD(WRCOMM, buffer, COMM_GROUP_SIZE));
|
||||||
|
|
||||||
|
__pollCMD(STCOMM, 72); //wait 72 cycles for the I2C transfer to complete (datasheet page 43)
|
||||||
|
//TODO: not sure if this is correct for a daisy chain
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//send the last packet
|
||||||
|
CHECK_RETURN(writeCMD(WRCOMM, buffer, COMM_GROUP_SIZE));
|
||||||
|
__pollCMD(STCOMM, 72);
|
||||||
|
|
||||||
|
return HAL_OK;
|
||||||
|
}
|
||||||
|
|
|
@ -212,17 +212,15 @@ HAL_StatusTypeDef ___readCMD(uint16_t command, uint8_t * buffer, size_t arglen)
|
||||||
return HAL_OK;
|
return HAL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
//check poll command - no data PEC sent back
|
//check poll command - no data PEC sent back, waitTime is in SPI clock cycles
|
||||||
HAL_StatusTypeDef pollCMD(uint16_t command) {
|
HAL_StatusTypeDef __pollCMD(uint16_t command, uint8_t waitTime) {
|
||||||
uint8_t buffer[4 + (N_BMS * 2) + 1] = {}; //poll is only valid after 2 * N_BMS clock cycles (datasheet page 55)
|
uint8_t buffer[4 + (waitTime / 8) + 1] = {}; //8 cycles per byte, +1 as we round up
|
||||||
//being conservative and adding 1 byte for the poll response
|
|
||||||
|
|
||||||
buffer[0] = (command >> 8) & 0xFF;
|
buffer[0] = (command >> 8) & 0xFF;
|
||||||
buffer[1] = (command) & 0xFF;
|
buffer[1] = (command) & 0xFF;
|
||||||
calculateCommandPEC(buffer, 4);
|
calculateCommandPEC(buffer, 4);
|
||||||
|
|
||||||
mcuAdbmsCSLow();
|
mcuAdbmsCSLow();
|
||||||
HAL_StatusTypeDef status = mcuSPITransmitReceive(buffer, buffer, 4 + (N_BMS * 2) + 1);
|
HAL_StatusTypeDef status = mcuSPITransmitReceive(buffer, buffer, sizeof buffer);
|
||||||
mcuAdbmsCSHigh();
|
mcuAdbmsCSHigh();
|
||||||
|
|
||||||
if (status != HAL_OK) return status;
|
if (status != HAL_OK) return status;
|
||||||
|
|
Loading…
Reference in New Issue