240 lines
7.8 KiB
C
240 lines
7.8 KiB
C
/**
|
|
******************************************************************************
|
|
* @file can.c
|
|
* @author AMG Energy Solution Team
|
|
* @version V1.0.0
|
|
* @date 07-Feb-2022
|
|
* @brief This file provides all the codes of CAN communication functions.
|
|
******************************************************************************
|
|
* @attention
|
|
*
|
|
* THE PRESENT FIRMWARE WHICH IS FOR GUIDANCE ONLY AIMS AT PROVIDING CUSTOMERS
|
|
* WITH CODING INFORMATION REGARDING THEIR PRODUCTS IN ORDER FOR THEM TO SAVE
|
|
* TIME. AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY
|
|
* DIRECT, INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING
|
|
* FROM THE CONTENT OF SUCH FIRMWARE AND/OR THE USE MADE BY CUSTOMERS OF THE
|
|
* CODING INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
|
|
*
|
|
* <h2><center>© COPYRIGHT 2022 AMG</center></h2>
|
|
******************************************************************************
|
|
*/
|
|
|
|
/** @addtogroup mBMS2
|
|
* @{
|
|
*/
|
|
|
|
/* Includes ------------------------------------------------------------------*/
|
|
#include "can.h"
|
|
#include "string.h"
|
|
|
|
/* Private typedef -----------------------------------------------------------*/
|
|
/* Private define ------------------------------------------------------------*/
|
|
/* CAN channel definition */
|
|
/* CAN baudrate definition */
|
|
#define CAN_BAUDRATE (250000ul)
|
|
|
|
/* CAN RX Port/Pin definition */
|
|
#define CAN_RX_PORT (PortE)
|
|
#define CAN_RX_PIN (Pin01)
|
|
#define CAN_RX_FUNC (Func_Can1_Rx)
|
|
|
|
/* CAN TX Port/Pin definition */
|
|
#define CAN_TX_PORT (PortE)
|
|
#define CAN_TX_PIN (Pin00)
|
|
#define CAN_TX_FUNC (Func_Can1_Tx)
|
|
|
|
#define TX_BUFFER_SIZE 10
|
|
#define RX_BUFFER_SIZE 320
|
|
|
|
/* Private macro -------------------------------------------------------------*/
|
|
typedef struct {
|
|
volatile uint16_t RxInPos, RxOutPos;
|
|
volatile uint32_t RxOverflowCount;
|
|
uint16_t TxInPos, TxOutPos;
|
|
stc_can_rxframe_t RxBuf[RX_BUFFER_SIZE];
|
|
stc_can_txframe_t TxBuf[TX_BUFFER_SIZE];
|
|
} CAN_Info;
|
|
|
|
/* Private variables ---------------------------------------------------------*/
|
|
CAN_Info Can;
|
|
|
|
/* Private function prototypes -----------------------------------------------*/
|
|
void CAN_RxIrqCallBack(void);
|
|
|
|
/* Private functions ---------------------------------------------------------*/
|
|
|
|
// Initializes CAN Port
|
|
void can_init(uint32_t CAN_Baud_Rate)
|
|
{
|
|
stc_can_init_config_t stcCanInitCfg;
|
|
stc_can_filter_t stcFilter;
|
|
stc_irq_regi_conf_t stcIrqRegiConf;
|
|
stc_port_init_t stcPortInit;
|
|
|
|
MEM_ZERO_STRUCT(stcCanInitCfg);
|
|
MEM_ZERO_STRUCT(stcFilter);
|
|
MEM_ZERO_STRUCT(stcIrqRegiConf);
|
|
MEM_ZERO_STRUCT(stcPortInit);
|
|
MEM_ZERO_STRUCT(Can);
|
|
|
|
stcPortInit.enPinMode = Pin_Mode_Out;
|
|
stcPortInit.enExInt = Disable;
|
|
stcPortInit.enPullUp = Enable;
|
|
|
|
/* SPI Port/Pin initialization */
|
|
PORT_Init(CAN_TX_PORT, CAN_TX_PIN, &stcPortInit);
|
|
|
|
stcPortInit.enPinMode = Pin_Mode_In;
|
|
|
|
PORT_Init(CAN_RX_PORT, CAN_RX_PIN, &stcPortInit);
|
|
|
|
// PORT_Init(PortB, Pin03, &stcPortInit);
|
|
PORT_Init(PortB, Pin04, &stcPortInit);
|
|
|
|
//<<Enable can peripheral clock and buffer(ram)
|
|
PWC_RamOpMdConfig(HighSpeedMd);
|
|
PWC_RamPwrdownCmd(PWC_RAMPWRDOWN_CAN, Enable);
|
|
PWC_Fcg1PeriphClockCmd(PWC_FCG1_PERIPH_CAN, Enable);
|
|
|
|
//<<CAN GPIO config
|
|
PORT_SetFunc(CAN_RX_PORT, CAN_RX_PIN, CAN_RX_FUNC, Disable);
|
|
PORT_SetFunc(CAN_TX_PORT, CAN_TX_PIN, CAN_TX_FUNC, Disable);
|
|
|
|
//<<Can bit time config
|
|
// stcCanInitCfg.stcCanBt.PRESC = 4u-1u;//???,??????????
|
|
switch(CAN_Baud_Rate) {
|
|
case 1000: // 1000K
|
|
stcCanInitCfg.stcCanBt.PRESC = 2u-1u;
|
|
break;
|
|
case 500: // 500K
|
|
stcCanInitCfg.stcCanBt.PRESC = 4u-1u;
|
|
break;
|
|
case 250: // 125K
|
|
stcCanInitCfg.stcCanBt.PRESC = 8u-1u;
|
|
break;
|
|
case 125: // 100K
|
|
stcCanInitCfg.stcCanBt.PRESC = 16u-1u;
|
|
break;
|
|
default:
|
|
stcCanInitCfg.stcCanBt.PRESC = 2u-1u;
|
|
break;
|
|
}
|
|
|
|
// stcCanInitCfg.stcCanBt.PRESC = 1u-1u;
|
|
stcCanInitCfg.stcCanBt.SEG_1 = 5u-2u;
|
|
stcCanInitCfg.stcCanBt.SEG_2 = 3u-1u;
|
|
stcCanInitCfg.stcCanBt.SJW = 3u-1u;
|
|
|
|
stcCanInitCfg.stcWarningLimit.CanErrorWarningLimitVal = 10u;
|
|
stcCanInitCfg.stcWarningLimit.CanWarningLimitVal = 16u-1u;
|
|
|
|
stcCanInitCfg.enCanRxBufAll = CanRxNormal;
|
|
stcCanInitCfg.enCanRxBufMode = CanRxBufNotStored;
|
|
stcCanInitCfg.enCanSAck = CanSelfAckDisable; //CanSelfAckEnable;
|
|
stcCanInitCfg.enCanSTBMode = CanSTBFifoMode;
|
|
|
|
CAN_Init(&stcCanInitCfg);
|
|
|
|
//<<Can filter config
|
|
stcFilter.enAcfFormat = CanAllFrames;
|
|
stcFilter.enFilterSel = CanFilterSel1;
|
|
stcFilter.u32CODE = 0x00000000u;
|
|
stcFilter.u32MASK = 0x1FFFFFFFu;
|
|
CAN_FilterConfig(&stcFilter, Enable);
|
|
|
|
//<<Can Irq Enable
|
|
CAN_IrqCmd(CanRxIrqEn, Enable);
|
|
CAN_IrqCmd(CanTxPrimaryIrqEn, Enable);
|
|
|
|
stcIrqRegiConf.enIRQn = Int005_IRQn;
|
|
stcIrqRegiConf.enIntSrc = INT_CAN_INT;
|
|
stcIrqRegiConf.pfnCallback = &CAN_RxIrqCallBack;
|
|
enIrqRegistration(&stcIrqRegiConf);
|
|
NVIC_SetPriority(stcIrqRegiConf.enIRQn, DDL_IRQ_PRIORITY_DEFAULT);
|
|
NVIC_ClearPendingIRQ(stcIrqRegiConf.enIRQn);
|
|
NVIC_EnableIRQ(stcIrqRegiConf.enIRQn);
|
|
}
|
|
|
|
void CAN_RxIrqCallBack(void)
|
|
{
|
|
if (true == CAN_IrqFlgGet(CanRxIrqFlg)) {
|
|
CAN_IrqFlgClr(CanRxIrqFlg);
|
|
|
|
stc_can_rxframe_t received;
|
|
uint16_t next = (uint16_t)((Can.RxInPos + 1U) % RX_BUFFER_SIZE);
|
|
/* Always drain the hardware receive slot, even when the software queue is full. */
|
|
CAN_Receive(&received);
|
|
if (next == Can.RxOutPos) {
|
|
Can.RxOverflowCount++;
|
|
} else {
|
|
memcpy(&Can.RxBuf[Can.RxInPos], &received, sizeof(received));
|
|
__DMB();
|
|
Can.RxInPos = next;
|
|
}
|
|
|
|
// CAN_IrqCmd(CanRxIrqEn, Disable);
|
|
}
|
|
if (true == CAN_IrqFlgGet(CanTxPrimaryIrqFlg)) {
|
|
CAN_IrqFlgClr(CanTxPrimaryIrqFlg);
|
|
// CAN_IrqCmd(CanRxIrqEn, Enable);
|
|
}
|
|
if (true == CAN_IrqFlgGet(CanBusErrorIrqFlg)) {
|
|
CAN_IrqFlgClr(CanBusErrorIrqFlg);
|
|
}
|
|
if (true == CAN_IrqFlgGet(CanArbiLostIrqFlg)) {
|
|
CAN_IrqFlgClr(CanArbiLostIrqFlg);
|
|
}
|
|
NVIC_ClearPendingIRQ(Int005_IRQn);
|
|
}
|
|
|
|
/*******************************************************************************
|
|
* Function Name : uint8_t CAN_GetPacket(CanRxMsg *packet)
|
|
* Description : Send 1 packet data to CAN Port transmit buffer
|
|
* Parameters : none
|
|
* Return : Transmission result (0: buffer empty, 1: buffer has data)
|
|
*******************************************************************************/
|
|
uint8_t CAN_GetPacket(stc_can_rxframe_t *packet)
|
|
{
|
|
if (Can.RxInPos != Can.RxOutPos) {
|
|
memcpy(packet, &Can.RxBuf[Can.RxOutPos], sizeof(stc_can_rxframe_t));
|
|
__DMB();
|
|
Can.RxOutPos = (uint16_t)((Can.RxOutPos + 1U) % RX_BUFFER_SIZE);
|
|
|
|
return 1;
|
|
}
|
|
else
|
|
return 0;
|
|
}
|
|
|
|
void CAN_SendPacket(stc_can_txframe_t *packet)
|
|
{
|
|
uint32_t timeout = 50000;
|
|
while ((M4_CAN->TCMD_f.TPE != 0) && (--timeout > 0)) {
|
|
__NOP();
|
|
}
|
|
if (timeout == 0) {
|
|
M4_CAN->TCMD |= CanPTBTxAbortCmd;
|
|
}
|
|
|
|
CAN_SetFrame(packet);
|
|
en_can_tx_buf_status_t txSts = CAN_TransmitCmd(CanPTBTxCmd);
|
|
switch (txSts) {
|
|
case CanTxBufEmpty: // = 0, ///< TTEN=0 or TTTBM=0: STB is empty
|
|
// printf("CanTxBufEmpty \r\n");
|
|
break; ///< TTEN=1 and TTTBM=1: PTB and STB are empty
|
|
case CanTxBufnotHalfFull: // = 1, ///< TTEN=0 or TTTBM=0: STB is less than or equal to half full
|
|
// printf("CanTxBufnotHalfFull \r\n");
|
|
break; ///< TTEN=1 and TTTBM=1: PTB and STB are not empty and not full
|
|
case CanTxBufHalfFull: // = 2, ///< TTEN=0 or TTTBM=0: STB is more than half full
|
|
// printf("CanTxBufHalfFull \r\n");
|
|
break; ///< TTEN=1 and TTTBM=1: None
|
|
case CanTxBufFull: // = 3, ///< TTEN=0 or TTTBM=0: STB is full
|
|
// printf("CanTxBufFull \r\n");
|
|
break;
|
|
}
|
|
|
|
// CAN_IrqCmd(CanRxIrqEn, Enable);
|
|
}
|
|
|
|
/*******************(C)COPYRIGHT 2022 AMG ********************END OF FILE******/
|