2022-07-03 17:33:09 +02:00
|
|
|
/*
|
|
|
|
* CAN_Communication.c
|
|
|
|
*
|
|
|
|
* Created on: Apr 26, 2022
|
|
|
|
* Author: max
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "CAN_Communication.h"
|
|
|
|
|
2022-07-03 23:47:14 +02:00
|
|
|
#include "SoC_Estimation.h"
|
2022-07-03 17:33:09 +02:00
|
|
|
|
2022-07-03 23:47:14 +02:00
|
|
|
#include "stm32g4xx_hal_fdcan.h"
|
2022-07-03 17:33:09 +02:00
|
|
|
|
|
|
|
canFrame framebuffer[CANFRAMEBUFFERSIZE] = {0};
|
|
|
|
uint8_t framebufferwritepointer;
|
|
|
|
uint8_t framebufferreadpointer;
|
|
|
|
|
|
|
|
int32_t shuntcurrent = 0;
|
|
|
|
int32_t shuntvoltage1 = 0;
|
|
|
|
int32_t shuntvoltage2 = 0;
|
|
|
|
int32_t shuntvoltage3 = 0;
|
|
|
|
int32_t shuntbusbartemp = 0;
|
|
|
|
int32_t shuntpower = 0;
|
|
|
|
int32_t shuntampereseconds = 0;
|
|
|
|
int32_t shuntenergy = 0;
|
|
|
|
|
|
|
|
uint32_t shuntlastmessage = 0;
|
|
|
|
|
|
|
|
uint8_t currentlap = 0;
|
|
|
|
uint8_t TSTargetState = 0;
|
|
|
|
|
|
|
|
void CAN_Init(FDCAN_HandleTypeDef* hcan) {
|
|
|
|
HAL_FDCAN_Stop(hcan);
|
|
|
|
|
|
|
|
framebufferreadpointer = 0;
|
|
|
|
framebufferwritepointer = 0;
|
|
|
|
|
|
|
|
FDCAN_FilterTypeDef fdfilter = {0};
|
|
|
|
|
|
|
|
fdfilter.FilterConfig = FDCAN_FILTER_TO_RXFIFO0;
|
|
|
|
fdfilter.FilterID1 = 0x000; // Range start
|
|
|
|
fdfilter.FilterID2 = 0x000; // Range stop
|
|
|
|
fdfilter.FilterIndex = 0;
|
|
|
|
|
|
|
|
fdfilter.FilterType = FDCAN_FILTER_MASK;
|
|
|
|
fdfilter.IdType = FDCAN_STANDARD_ID;
|
|
|
|
|
|
|
|
HAL_FDCAN_ConfigFilter(hcan, &fdfilter);
|
|
|
|
|
|
|
|
HAL_FDCAN_Start(hcan);
|
|
|
|
|
|
|
|
HAL_FDCAN_ActivateNotification(hcan, FDCAN_IT_RX_FIFO0_NEW_MESSAGE, 0);
|
|
|
|
// hcan->Instance->CCCR |= FDCAN_CCCR_ASM;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t CAN_Receive(FDCAN_HandleTypeDef* hcan) {
|
|
|
|
uint32_t ecount = hcan->Instance->ECR;
|
|
|
|
while (framebufferreadpointer != framebufferwritepointer) {
|
|
|
|
framebufferreadpointer++;
|
|
|
|
|
|
|
|
if (framebufferreadpointer >= CANFRAMEBUFFERSIZE) {
|
|
|
|
framebufferreadpointer = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
canFrame rxFrame = framebuffer[framebufferreadpointer];
|
|
|
|
|
|
|
|
switch (rxFrame.FrameID) {
|
|
|
|
case SHUNT_CURRENT:
|
|
|
|
shuntcurrent = (rxFrame.data[2] << 24) | (rxFrame.data[3] << 16) |
|
|
|
|
(rxFrame.data[4] << 8) | (rxFrame.data[5]);
|
|
|
|
shuntlastmessage = framebuffer[framebufferreadpointer].timestamp;
|
|
|
|
break;
|
|
|
|
case SHUNT_VOLTAGE_1:
|
|
|
|
shuntvoltage1 = (rxFrame.data[2] << 24) | (rxFrame.data[3] << 16) |
|
|
|
|
(rxFrame.data[4] << 8) | (rxFrame.data[5]);
|
|
|
|
shuntlastmessage = framebuffer[framebufferreadpointer].timestamp;
|
|
|
|
break;
|
|
|
|
case SHUNT_VOLTAGE_2:
|
|
|
|
shuntvoltage2 = (rxFrame.data[2] << 24) | (rxFrame.data[3] << 16) |
|
|
|
|
(rxFrame.data[4] << 8) | (rxFrame.data[5]);
|
|
|
|
shuntlastmessage = framebuffer[framebufferreadpointer].timestamp;
|
|
|
|
break;
|
|
|
|
case SHUNT_VOLTAGE_3:
|
|
|
|
shuntvoltage3 = (rxFrame.data[2] << 24) | (rxFrame.data[3] << 16) |
|
|
|
|
(rxFrame.data[4] << 8) | (rxFrame.data[5]);
|
|
|
|
shuntlastmessage = framebuffer[framebufferreadpointer].timestamp;
|
|
|
|
break;
|
|
|
|
case SHUNT_BUSBAR_TEMP:
|
|
|
|
shuntbusbartemp = (rxFrame.data[2] << 24) | (rxFrame.data[3] << 16) |
|
|
|
|
(rxFrame.data[4] << 8) | (rxFrame.data[5]);
|
|
|
|
shuntlastmessage = framebuffer[framebufferreadpointer].timestamp;
|
|
|
|
break;
|
|
|
|
case SHUNT_POWER:
|
|
|
|
shuntpower = (rxFrame.data[2] << 24) | (rxFrame.data[3] << 16) |
|
|
|
|
(rxFrame.data[4] << 8) | (rxFrame.data[5]);
|
|
|
|
shuntlastmessage = framebuffer[framebufferreadpointer].timestamp;
|
|
|
|
break;
|
|
|
|
case SHUNT_ENERGY:
|
|
|
|
shuntenergy = (rxFrame.data[2] << 24) | (rxFrame.data[3] << 16) |
|
|
|
|
(rxFrame.data[4] << 8) | (rxFrame.data[5]);
|
|
|
|
shuntlastmessage = framebuffer[framebufferreadpointer].timestamp;
|
|
|
|
break;
|
|
|
|
case SHUNT_AMPERE_SECONDS:
|
|
|
|
shuntampereseconds = (rxFrame.data[2] << 24) | (rxFrame.data[3] << 16) |
|
|
|
|
(rxFrame.data[4] << 8) | (rxFrame.data[5]);
|
|
|
|
shuntlastmessage = framebuffer[framebufferreadpointer].timestamp;
|
|
|
|
break;
|
|
|
|
|
|
|
|
case AUTOBOX_INFO:
|
|
|
|
currentlap = rxFrame.data[0] >> 2;
|
|
|
|
TSTargetState = rxFrame.data[0] & 0x01;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t CAN_Transmit(FDCAN_HandleTypeDef* hcan, uint16_t frameid,
|
|
|
|
uint8_t* buffer, uint8_t datalen) {
|
|
|
|
FDCAN_TxHeaderTypeDef txheader = {0};
|
|
|
|
|
|
|
|
txheader.Identifier = frameid;
|
|
|
|
txheader.IdType = FDCAN_STANDARD_ID;
|
|
|
|
txheader.TxFrameType = FDCAN_FRAME_CLASSIC;
|
|
|
|
txheader.DataLength = ((uint32_t)datalen) << 16;
|
|
|
|
txheader.ErrorStateIndicator = FDCAN_ESI_ACTIVE;
|
|
|
|
txheader.BitRateSwitch = FDCAN_BRS_OFF;
|
|
|
|
txheader.FDFormat = FDCAN_CLASSIC_CAN;
|
|
|
|
txheader.TxEventFifoControl = FDCAN_NO_TX_EVENTS;
|
|
|
|
txheader.MessageMarker = 0;
|
|
|
|
if (HAL_FDCAN_GetTxFifoFreeLevel(hcan) > 0) {
|
|
|
|
HAL_FDCAN_AddMessageToTxFifoQ(hcan, &txheader, buffer);
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void HAL_FDCAN_RxFifo0Callback(FDCAN_HandleTypeDef* handle,
|
|
|
|
uint32_t interrupt_flags) {
|
|
|
|
|
|
|
|
FDCAN_RxHeaderTypeDef rxFrameHeader;
|
|
|
|
uint8_t data[8];
|
|
|
|
framebufferwritepointer++;
|
|
|
|
|
|
|
|
if (framebufferwritepointer >= CANFRAMEBUFFERSIZE) {
|
|
|
|
framebufferwritepointer = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!(interrupt_flags & FDCAN_IT_RX_FIFO0_NEW_MESSAGE)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (HAL_FDCAN_GetRxMessage(handle, FDCAN_RX_FIFO0, &rxFrameHeader, data) !=
|
|
|
|
HAL_OK) {
|
|
|
|
framebuffer[framebufferwritepointer].error = 1;
|
|
|
|
} else {
|
|
|
|
framebuffer[framebufferwritepointer].error = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rxFrameHeader.IdType != FDCAN_STANDARD_ID) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
framebuffer[framebufferwritepointer].FrameID =
|
|
|
|
(int16_t)(rxFrameHeader.Identifier);
|
|
|
|
framebuffer[framebufferwritepointer].length =
|
|
|
|
(uint8_t)(rxFrameHeader.DataLength >> 16);
|
|
|
|
|
|
|
|
for (int i = 0; i < framebuffer[framebufferwritepointer].length; i++) {
|
|
|
|
framebuffer[framebufferwritepointer].data[i] = data[i];
|
|
|
|
}
|
|
|
|
|
|
|
|
framebuffer[framebufferwritepointer].timestamp = HAL_GetTick();
|
|
|
|
}
|
|
|
|
|
|
|
|
void HAL_FDCAN_ErrorCallback(FDCAN_HandleTypeDef* hcan) {}
|
|
|
|
|
|
|
|
void CAN_SendAbxStatus(FDCAN_HandleTypeDef* hcan) {
|
|
|
|
uint8_t buffer[4];
|
|
|
|
buffer[0] = ctrltsstate.currentTSState | (1 << 7);
|
|
|
|
buffer[1] = 160;
|
|
|
|
buffer[2] = (uint8_t)(shuntvoltage1 / 2000);
|
2022-07-03 23:47:14 +02:00
|
|
|
buffer[3] = current_soc;
|
2022-07-03 17:33:09 +02:00
|
|
|
CAN_Transmit(hcan, AMS_STATUS_ID, buffer, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
void CAN_SendAMSPanic(FDCAN_HandleTypeDef* hcan) {
|
|
|
|
uint8_t buffer[8];
|
|
|
|
buffer[0] = errorflags.errorcode;
|
|
|
|
buffer[1] = errorflags.errorargs[0];
|
|
|
|
buffer[2] = 0;
|
|
|
|
buffer[3] = 0;
|
|
|
|
buffer[4] = 0;
|
|
|
|
buffer[5] = 0;
|
|
|
|
buffer[6] = 0;
|
|
|
|
buffer[7] = 0;
|
|
|
|
CAN_Transmit(hcan, AMS_PANIC_ID, buffer, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t slavelognum = 0;
|
|
|
|
uint8_t framelognum = 0;
|
|
|
|
|
|
|
|
void CAN_SendLoggingFrame(FDCAN_HandleTypeDef* hcan) {
|
|
|
|
|
|
|
|
uint8_t buffer[8];
|
|
|
|
|
|
|
|
buffer[0] = ((slavelognum << 4) | framelognum);
|
|
|
|
|
|
|
|
framelognum++;
|
|
|
|
if ((framelognum > 6)) {
|
|
|
|
framelognum = 0;
|
|
|
|
slavelognum++;
|
|
|
|
}
|
|
|
|
if ((slavelognum > NUMBEROFSLAVES)) {
|
|
|
|
slavelognum = 0;
|
|
|
|
framelognum = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (framelognum) {
|
|
|
|
case 0:
|
|
|
|
buffer[1] = CAN_convert_logval(slaves[slavelognum].cellVoltages[0],
|
|
|
|
BATTERY_VOLTAGE_TYPE);
|
|
|
|
buffer[2] = CAN_convert_logval(slaves[slavelognum].cellVoltages[1],
|
|
|
|
BATTERY_VOLTAGE_TYPE);
|
|
|
|
buffer[3] = CAN_convert_logval(slaves[slavelognum].cellVoltages[2],
|
|
|
|
BATTERY_VOLTAGE_TYPE);
|
|
|
|
buffer[4] = CAN_convert_logval(slaves[slavelognum].cellVoltages[3],
|
|
|
|
BATTERY_VOLTAGE_TYPE);
|
|
|
|
buffer[5] = CAN_convert_logval(slaves[slavelognum].cellVoltages[4],
|
|
|
|
BATTERY_VOLTAGE_TYPE);
|
|
|
|
buffer[6] = CAN_convert_logval(slaves[slavelognum].cellVoltages[5],
|
|
|
|
BATTERY_VOLTAGE_TYPE);
|
|
|
|
buffer[7] = CAN_convert_logval(slaves[slavelognum].cellVoltages[6],
|
|
|
|
BATTERY_VOLTAGE_TYPE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 1:
|
|
|
|
buffer[1] = CAN_convert_logval(slaves[slavelognum].cellVoltages[7],
|
|
|
|
BATTERY_VOLTAGE_TYPE);
|
|
|
|
buffer[2] = CAN_convert_logval(slaves[slavelognum].cellVoltages[8],
|
|
|
|
BATTERY_VOLTAGE_TYPE);
|
|
|
|
buffer[3] = CAN_convert_logval(slaves[slavelognum].cellVoltages[9],
|
|
|
|
BATTERY_VOLTAGE_TYPE);
|
|
|
|
buffer[4] =
|
|
|
|
CAN_convert_logval(slaves[slavelognum].cellTemps[0], BATTERY_TEMP_TYPE);
|
|
|
|
buffer[5] =
|
|
|
|
CAN_convert_logval(slaves[slavelognum].cellTemps[1], BATTERY_TEMP_TYPE);
|
|
|
|
buffer[6] =
|
|
|
|
CAN_convert_logval(slaves[slavelognum].cellTemps[2], BATTERY_TEMP_TYPE);
|
|
|
|
buffer[7] =
|
|
|
|
CAN_convert_logval(slaves[slavelognum].cellTemps[3], BATTERY_TEMP_TYPE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 2:
|
|
|
|
buffer[1] =
|
|
|
|
CAN_convert_logval(slaves[slavelognum].cellTemps[4], BATTERY_TEMP_TYPE);
|
|
|
|
buffer[2] =
|
|
|
|
CAN_convert_logval(slaves[slavelognum].cellTemps[5], BATTERY_TEMP_TYPE);
|
|
|
|
buffer[3] =
|
|
|
|
CAN_convert_logval(slaves[slavelognum].cellTemps[6], BATTERY_TEMP_TYPE);
|
|
|
|
buffer[4] =
|
|
|
|
CAN_convert_logval(slaves[slavelognum].cellTemps[7], BATTERY_TEMP_TYPE);
|
|
|
|
buffer[5] =
|
|
|
|
CAN_convert_logval(slaves[slavelognum].cellTemps[8], BATTERY_TEMP_TYPE);
|
|
|
|
buffer[6] =
|
|
|
|
CAN_convert_logval(slaves[slavelognum].cellTemps[9], BATTERY_TEMP_TYPE);
|
|
|
|
buffer[7] = CAN_convert_logval(slaves[slavelognum].cellTemps[10],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 3:
|
|
|
|
buffer[1] = CAN_convert_logval(slaves[slavelognum].cellTemps[11],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[2] = CAN_convert_logval(slaves[slavelognum].cellTemps[12],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[3] = CAN_convert_logval(slaves[slavelognum].cellTemps[13],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[4] = CAN_convert_logval(slaves[slavelognum].cellTemps[14],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[5] = CAN_convert_logval(slaves[slavelognum].cellTemps[15],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[6] = CAN_convert_logval(slaves[slavelognum].cellTemps[16],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[7] = CAN_convert_logval(slaves[slavelognum].cellTemps[17],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 4:
|
|
|
|
buffer[1] = CAN_convert_logval(slaves[slavelognum].cellTemps[18],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[2] = CAN_convert_logval(slaves[slavelognum].cellTemps[19],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[3] = CAN_convert_logval(slaves[slavelognum].cellTemps[20],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[4] = CAN_convert_logval(slaves[slavelognum].cellTemps[21],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[5] = CAN_convert_logval(slaves[slavelognum].cellTemps[22],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[6] = CAN_convert_logval(slaves[slavelognum].cellTemps[23],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[7] = CAN_convert_logval(slaves[slavelognum].cellTemps[24],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case 5:
|
|
|
|
buffer[1] = CAN_convert_logval(slaves[slavelognum].cellTemps[25],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[2] = CAN_convert_logval(slaves[slavelognum].cellTemps[26],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[3] = CAN_convert_logval(slaves[slavelognum].cellTemps[27],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[4] = CAN_convert_logval(slaves[slavelognum].cellTemps[28],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[5] = CAN_convert_logval(slaves[slavelognum].cellTemps[29],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[6] = CAN_convert_logval(slaves[slavelognum].cellTemps[30],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
buffer[7] = CAN_convert_logval(slaves[slavelognum].cellTemps[31],
|
|
|
|
BATTERY_TEMP_TYPE);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
CAN_Transmit(hcan, AMS_LOGGING_ID, buffer, 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t CAN_convert_logval(uint16_t value, uint8_t type) {
|
|
|
|
if (type == BATTERY_VOLTAGE_TYPE) {
|
|
|
|
return (uint8_t)value >> 8;
|
|
|
|
} else if (type == BATTERY_TEMP_TYPE) {
|
|
|
|
return (uint8_t)value >> 4;
|
|
|
|
}
|
|
|
|
}
|