/* * SPI_Communication.c * * Created on: Jun 16, 2022 * Author: max */ #include "SPI_Communication.h" #include "stm32g4xx_hal.h" #include "stm32g4xx_hal_spi.h" #include #define GET_ERROR_RESPONSE_LEN 14 #define GET_TS_STATE_RESPONSE_LEN 23 static volatile int spi_transfer_state = 0; uint8_t spitxbuf[1024]; uint8_t spirxbuf[1024]; SlaveHandler slaves[NUMBEROFSLAVES] = {0}; uint16_t min_voltage = 0, max_voltage = 0, min_temp = 0, max_temp = 0; ErrorFlagHandler spierrorflags = {0}; TSHandler ctrltsstate = {0}; uint8_t spibusy = 0; uint8_t actualTSState = 0; SPI_HandleTypeDef* stmspi; void InitSPI(SPI_HandleTypeDef* spi) { stmspi = spi; // HAL_SPI_DeInit(spi); } // uint8_t transmittoSlave(uint16_t length) { // if (length > 1024) // return 0xFE; // if (waitforSlave() == 0) { // HAL_StatusTypeDef status = HAL_SPI_Transmit(stmspi, spitxbuf, length, // 10); return (uint8_t)status; // } // return 0xFF; // } // uint8_t receivefromSlave(uint16_t length) { // if (length > 1024) // return 0xFE; // if (waitforSlave() == 0) { // HAL_StatusTypeDef status = HAL_SPI_Receive(stmspi, spirxbuf, length, 10); // return (uint8_t)status; // } // return 0xFF; // } // uint8_t slaveSendCommand(uint8_t command) { // if (HAL_GPIO_ReadPin(InterSTM_IRQ_Line_GPIO_Port, InterSTM_IRQ_Line_Pin) == // 0x01) // return 1; // HAL_SPI_Transmit(stmspi, &command, 1, 10); // return 0; // } // void sendShuntdata() { // if (slaveSendCommand(SEND_SHUNTDATA) == 0) { // spitxbuf[0] = (uint8_t)(shuntvoltage3 >> 24) & 0xFF; // spitxbuf[1] = (uint8_t)(shuntvoltage3 >> 16) & 0xFF; // spitxbuf[2] = (uint8_t)(shuntvoltage3 >> 8) & 0xFF; // spitxbuf[3] = (uint8_t)(shuntvoltage3)&0xFF; // spitxbuf[4] = (uint8_t)(shuntvoltage2 >> 24) & 0xFF; // spitxbuf[5] = (uint8_t)(shuntvoltage2 >> 16) & 0xFF; // spitxbuf[6] = (uint8_t)(shuntvoltage2 >> 8) & 0xFF; // spitxbuf[7] = (uint8_t)(shuntvoltage2)&0xFF; // spitxbuf[8] = (uint8_t)(shuntcurrent >> 24) & 0xFF; // spitxbuf[9] = (uint8_t)(shuntcurrent >> 16) & 0xFF; // spitxbuf[10] = (uint8_t)(shuntcurrent >> 8) & 0xFF; // spitxbuf[11] = (uint8_t)(shuntcurrent)&0xFF; // transmittoSlave(12); // } // } // void sendTSstate(uint8_t targetstate) { // if (slaveSendCommand(SET_TSSTATE) == 0) { // spitxbuf[0] = targetstate; // transmittoSlave(1); // } // } // void getTSstate() { // if (slaveSendCommand(GET_TSSTATE)) { // if (receivefromSlave(20) == HAL_OK) { // ctrltsstate.currentTSState = spirxbuf[0]; // ctrltsstate.targetTSState = spirxbuf[1]; // ctrltsstate.relaisSupplyVoltage = spirxbuf[2] << 8 | spirxbuf[3]; // ctrltsstate.shutdownCircuitVoltage = spirxbuf[4] << 8 | spirxbuf[5]; // ctrltsstate.negativeAIRCurrent = spirxbuf[6] << 8 | spirxbuf[7]; // ctrltsstate.positiveAIRCurrent = spirxbuf[8] << 8 | spirxbuf[9]; // ctrltsstate.preChargeAIRCurrent = spirxbuf[10] << 8 | spirxbuf[11]; // ctrltsstate.CtrlBatteryVoltageBatterySide = // (spirxbuf[12] << 24) | (spirxbuf[13] << 16) | (spirxbuf[14] << 8) | // (spirxbuf[15]); // ctrltsstate.CtrlBatteryVoltageVehicleSide = // (spirxbuf[16] << 24) | (spirxbuf[17] << 16) | (spirxbuf[18] << 8) | // (spirxbuf[19]); // } // } // } // void getError() { // if (slaveSendCommand(GET_ERROR) == 0) { // if (receivefromSlave(12) == HAL_OK) { // errorflags.errorcode = spirxbuf[0]; // errorflags.errorargs[0] = spirxbuf[1]; // errorflags.errorargs[1] = spirxbuf[2]; // errorflags.errorargs[2] = spirxbuf[3]; // errorflags.errorargs[3] = spirxbuf[4]; // errorflags.errorargs[4] = spirxbuf[5]; // errorflags.errorargs[5] = spirxbuf[6]; // errorflags.errorargs[6] = spirxbuf[7]; // errorflags.errorargs[7] = spirxbuf[8]; // errorflags.AMS_ERROR_LED = (spirxbuf[9] >> 7) & 0x01; // errorflags.IMD_ERROR_LED = (spirxbuf[9] >> 6) & 0x01; // errorflags.IMD_ERROR = (spirxbuf[9] >> 5) & 0x01; // errorflags.HV_Inactive = (spirxbuf[9] >> 4) & 0x01; // errorflags.TS_no_voltage_error = (spirxbuf[9] >> 3) & 0x01; // errorflags.negative_AIR_error = (spirxbuf[9] >> 2) & 0x01; // errorflags.positive_AIR_or_PC_error = (spirxbuf[9] >> 1) & 0x01; // errorflags.positive_AIR_and_PC_open = spirxbuf[9] & 0x01; // errorflags.negative_AIR_open = spirxbuf[10] & 0x01; // } // } // } // void getMeasurements() { // if (slaveSendCommand(GET_MEASUREMENTS) == 0) { // if (receivefromSlave(NUMBEROFSLAVES * 89) == HAL_OK) { // for (int n = 0; n < NUMBEROFSLAVES; n++) { // slaves[n].slaveID = spirxbuf[n * 89]; // slaves[n].timestamp = // (spirxbuf[n * 89 + 1] << 24) | (spirxbuf[n * 89 + 2] << 16) | // (spirxbuf[n * 89 + 3] << 8) | (spirxbuf[n * 89 + 4]); // for (int i = 0; i < NUMBEROFCELLS; i++) { // slaves[n].cellVoltages[i] = // ((uint16_t)spirxbuf[n * 89 + 5 + 2 * i] << 8) | // spirxbuf[n * 89 + 6 + 2 * i]; // } // for (int i = 0; i < NUMBEROFTEMPS; i++) { // slaves[n].cellTemps[i] = // ((uint16_t)spirxbuf[n * 89 + 25 + 2 * i] << 8) | // spirxbuf[n * 89 + 26 + 2 * i]; // } // } // } // } // } // void toggleSlaveStatusLED() { slaveSendCommand(TOGGLE_STATUS_LED); } uint8_t waitforSlave() { uint32_t starttime = HAL_GetTick(); while ((starttime + SLAVE_TIMEOUT) > HAL_GetTick()) { if (HAL_GPIO_ReadPin(InterSTM_IRQ_Line_GPIO_Port, InterSTM_IRQ_Line_Pin) == GPIO_PIN_SET) { return 0; } } HAL_GPIO_WritePin(InterSTM_SPI_CS_GPIO_Port, InterSTM_SPI_CS_Pin, GPIO_PIN_SET); HAL_Delay(1); HAL_GPIO_WritePin(InterSTM_SPI_CS_GPIO_Port, InterSTM_SPI_CS_Pin, GPIO_PIN_RESET); return 1; } void InterSTMFrame(uint8_t targettsstate) { spitxbuf[0] = (uint8_t)(shuntvoltage3 >> 24) & 0xFF; spitxbuf[1] = (uint8_t)(shuntvoltage3 >> 16) & 0xFF; spitxbuf[2] = (uint8_t)(shuntvoltage3 >> 8) & 0xFF; spitxbuf[3] = (uint8_t)(shuntvoltage3)&0xFF; spitxbuf[4] = (uint8_t)(shuntvoltage2 >> 24) & 0xFF; spitxbuf[5] = (uint8_t)(shuntvoltage2 >> 16) & 0xFF; spitxbuf[6] = (uint8_t)(shuntvoltage2 >> 8) & 0xFF; spitxbuf[7] = (uint8_t)(shuntvoltage2)&0xFF; spitxbuf[8] = (uint8_t)(shuntcurrent >> 24) & 0xFF; spitxbuf[9] = (uint8_t)(shuntcurrent >> 16) & 0xFF; spitxbuf[10] = (uint8_t)(shuntcurrent >> 8) & 0xFF; spitxbuf[11] = (uint8_t)(shuntcurrent)&0xFF; spitxbuf[12] = targettsstate; if (HAL_GPIO_ReadPin(InterSTM_IRQ_Line_GPIO_Port, InterSTM_IRQ_Line_Pin) == GPIO_PIN_SET) { return; } uint8_t dummiebuf[4] = {0xFF, 0xFF, 0xFF, 0xFF}; HAL_SPI_Transmit(stmspi, dummiebuf, 4, 10); // HAL_SPI_DeInit(stmspi); // HAL_SPI_Init(stmspi); HAL_SPIEx_FlushRxFifo(stmspi); HAL_GPIO_WritePin(InterSTM_SPI_CS_GPIO_Port, InterSTM_SPI_CS_Pin, GPIO_PIN_SET); if (waitforSlave() != 0) { return; } HAL_Delay(10); spi_transfer_state = 0; HAL_SPI_Transmit_IT(stmspi, spitxbuf, 13); uint32_t timeout = HAL_GetTick() + 100; while (spi_transfer_state == 0 && HAL_GetTick() < timeout) { } if (spi_transfer_state == 1) { HAL_Delay(10); HAL_SPI_Receive_IT(stmspi, spirxbuf, NUMBEROFSLAVES * 89 + 33); timeout = HAL_GetTick() + 200; while (spi_transfer_state == 1 && HAL_GetTick() < timeout) { } } HAL_GPIO_WritePin(InterSTM_SPI_CS_GPIO_Port, InterSTM_SPI_CS_Pin, GPIO_PIN_RESET); if (spi_transfer_state != 2) { return; } uint16_t min_v = 0xFFFF; uint16_t max_v = 0; uint16_t min_t = 0xFFFF; uint16_t max_t = 0; for (int n = 0; n < NUMBEROFSLAVES; n++) { slaves[n].slaveID = spirxbuf[n * 89]; slaves[n].timestamp = (spirxbuf[n * 89 + 1] << 24) | (spirxbuf[n * 89 + 2] << 16) | (spirxbuf[n * 89 + 3] << 8) | (spirxbuf[n * 89 + 4]); for (int i = 0; i < N_CELLS_SERIES; i++) { uint16_t v = ((uint16_t)spirxbuf[n * 89 + 5 + 2 * i] << 8) | spirxbuf[n * 89 + 6 + 2 * i]; slaves[n].cellVoltages[i] = v; if (v < min_v) { min_v = v; } if (v > max_v) { max_v = v; } } for (int i = 0; i < NUMBEROFTEMPS; i++) { uint16_t t = ((uint16_t)spirxbuf[n * 89 + 25 + 2 * i] << 8) | spirxbuf[n * 89 + 26 + 2 * i]; slaves[n].cellTemps[i] = t; if (t < min_t) { min_t = t; } if (t > max_t) { max_t = t; } } } min_voltage = min_v; max_voltage = max_v; min_temp = min_t; max_temp = max_t; uint16_t errorflagbaseaddress = NUMBEROFSLAVES * 89 + 1; spierrorflags.errorcode = spirxbuf[errorflagbaseaddress]; spierrorflags.errorargs[0] = spirxbuf[errorflagbaseaddress + 1]; spierrorflags.errorargs[1] = spirxbuf[errorflagbaseaddress + 2]; spierrorflags.errorargs[2] = spirxbuf[errorflagbaseaddress + 3]; spierrorflags.errorargs[3] = spirxbuf[errorflagbaseaddress + 4]; spierrorflags.errorargs[4] = spirxbuf[errorflagbaseaddress + 5]; spierrorflags.errorargs[5] = spirxbuf[errorflagbaseaddress + 6]; spierrorflags.errorargs[6] = spirxbuf[errorflagbaseaddress + 7]; // TODO: We can only transmit 7 error flags, we can remove the 8th // errorflags.errorargs[7] = spirxbuf[errorflagbaseaddress + 8]; spierrorflags.AMS_ERROR_LED = (spirxbuf[errorflagbaseaddress + 9] >> 7) & 0x01; spierrorflags.IMD_ERROR_LED = (spirxbuf[errorflagbaseaddress + 9] >> 6) & 0x01; spierrorflags.IMD_ERROR = (spirxbuf[errorflagbaseaddress + 9] >> 5) & 0x01; spierrorflags.HV_Inactive = (spirxbuf[errorflagbaseaddress + 9] >> 4) & 0x01; spierrorflags.TS_no_voltage_error = (spirxbuf[errorflagbaseaddress + 9] >> 3) & 0x01; spierrorflags.negative_AIR_error = (spirxbuf[errorflagbaseaddress + 9] >> 2) & 0x01; spierrorflags.positive_AIR_or_PC_error = (spirxbuf[errorflagbaseaddress + 9] >> 1) & 0x01; spierrorflags.positive_AIR_and_PC_open = spirxbuf[errorflagbaseaddress + 9] & 0x01; spierrorflags.negative_AIR_open = spirxbuf[errorflagbaseaddress + 10] & 0x01; uint16_t tsstatebaseaddress = errorflagbaseaddress + 12; ctrltsstate.currentTSState = spirxbuf[tsstatebaseaddress + 0]; ctrltsstate.targetTSState = spirxbuf[tsstatebaseaddress + 1]; ctrltsstate.relaisSupplyVoltage = spirxbuf[tsstatebaseaddress + 2] << 8 | spirxbuf[tsstatebaseaddress + 3]; ctrltsstate.shutdownCircuitVoltage = spirxbuf[tsstatebaseaddress + 4] << 8 | spirxbuf[tsstatebaseaddress + 5]; ctrltsstate.negativeAIRCurrent = spirxbuf[tsstatebaseaddress + 6] << 8 | spirxbuf[tsstatebaseaddress + 7]; ctrltsstate.positiveAIRCurrent = spirxbuf[tsstatebaseaddress + 8] << 8 | spirxbuf[tsstatebaseaddress + 9]; ctrltsstate.preChargeAIRCurrent = spirxbuf[tsstatebaseaddress + 10] << 8 | spirxbuf[tsstatebaseaddress + 11]; ctrltsstate.CtrlBatteryVoltageBatterySide = (spirxbuf[tsstatebaseaddress + 12] << 24) | (spirxbuf[tsstatebaseaddress + 13] << 16) | (spirxbuf[tsstatebaseaddress + 14] << 8) | (spirxbuf[tsstatebaseaddress + 15]); ctrltsstate.CtrlBatteryVoltageVehicleSide = (spirxbuf[tsstatebaseaddress + 16] << 24) | (spirxbuf[tsstatebaseaddress + 17] << 16) | (spirxbuf[tsstatebaseaddress + 18] << 8) | (spirxbuf[tsstatebaseaddress + 19]); } uint8_t calculatechecksum(uint8_t* data, uint8_t datalen) { uint8_t checksum = 0xFF; for (int i = 0; i < datalen; i++) { checksum ^= data[i]; } return checksum; } void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef* hspi) { spi_transfer_state = 1; } void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi) { spi_transfer_state = 2; }