S32K144-EVB开发板CAN实例代码
时间: 2023-10-01 22:06:50 浏览: 152
S32K144的boot,可修改普通CAN
5星 · 资源好评率100%
以下是S32K144-EVB开发板CAN实例代码:
```c
#include "S32K144.h"
#include "can.h"
#include "clocks_and_modes.h"
#include "gpio.h"
#include "interrupt_manager.h"
#define CAN0_TX_PIN 27U
#define CAN0_RX_PIN 26U
#define CAN0_TX_MUX 2U
#define CAN0_RX_MUX 2U
#define CAN0_RX_MSG_BUF_NUM (4U)
#define CAN0_BASE_ADDR (0x40024000U)
#define CAN0_RX_FIFO_ID (0x100U)
#define CAN0_RX_FIFO_NUM (8U)
static uint8_t can0RxMsgBuf[CAN0_RX_MSG_BUF_NUM][CAN_MESSAGE_BUFFER_MAX_PAYLOAD_SIZE];
void Can0_RxIsr(void);
void InitCan0(void)
{
/* Enable clock for PORTA */
PCC->PCCn[PCC_PORTA_INDEX] |= PCC_PCCn_CGC_MASK;
/* Configure CAN0_TX_PIN and CAN0_RX_PIN as alternative function (Alt2) */
PORTA->PCR[CAN0_TX_PIN] = PORT_PCR_MUX(CAN0_TX_MUX);
PORTA->PCR[CAN0_RX_PIN] = PORT_PCR_MUX(CAN0_RX_MUX);
/* Set the bit rate to 500 kbps with a 8 MHz clock */
const uint32_t can0ClkFreq = 8000000U;
const uint32_t baudRate = 500000U;
const uint32_t prescaler = (can0ClkFreq / (baudRate * 20U)) - 1U;
CAN0->CTRL1 &= ~CAN_CTRL1_CLKSRC_MASK;
CAN0->CTRL1 |= CAN_CTRL1_CLKSRC(1U);
CAN0->CTRL1 |= CAN_CTRL1_PRESDIV(prescaler);
/* Enable CAN0 */
PCC->PCCn[PCC_FlexCAN0_INDEX] |= PCC_PCCn_CGC_MASK;
/* Enable individual RX FIFO filters */
CAN0->MCR |= CAN_MCR_IRMQ_MASK;
/* Enable RX FIFO */
CAN0->MCR |= CAN_MCR_RFEN_MASK;
/* Configure RX FIFO ID filter */
CAN0->RXFIFO.IDTABLE[0] = 0x80000000U;
CAN0->RXFIFO.IDTABLE[1] = 0x80000000U;
/* Configure RX FIFO filter element */
CAN0->RXIMR[CAN0_RX_FIFO_NUM] = 0xFFFFFFFFU;
CAN0->RXMGMASK = 0x80000000U;
CAN0->RXFGMASK = 0x80000000U;
/* Enable RX FIFO interrupt */
CAN0->IMASK1 |= CAN_IMASK1_BUF5M_MASK;
/* Configure RX message buffers */
for (uint32_t msgBufIdx = 0U; msgBufIdx < CAN0_RX_MSG_BUF_NUM; msgBufIdx++)
{
/* Configure RX message buffer filter */
CAN0->RAMn[msgBufIdx].ID = (CAN_RAMn_ID_STD(0x7FFU) | CAN_RAMn_IDE_MASK);
/* Configure RX message buffer payload size */
CAN0->RAMn[msgBufIdx].CS = CAN_CS_DLC(CAN_MESSAGE_BUFFER_MAX_PAYLOAD_SIZE);
/* Configure RX message buffer for reception */
CAN0->RAMn[msgBufIdx].CS |= CAN_CS_CODE(CAN_CS_CODE_RX_INACTIVE);
}
/* Configure NVIC for RX FIFO interrupt */
const IRQn_Type can0RxIrqId = IRQ_CAN0_ORed_Message_buffer;
INT_SYS_EnableIRQ(can0RxIrqId);
INT_SYS_SetPriority(can0RxIrqId, 3U);
}
void Can0_RxIsr(void)
{
uint32_t msgBufIdx = 0U;
/* Read RX FIFO and dispatch messages */
while (CAN0->IFLAG1 & CAN_IFLAG1_BUF5I_MASK)
{
/* Clear RX FIFO interrupt flag */
CAN0->IFLAG1 |= CAN_IFLAG1_BUF5I_MASK;
/* Read RX FIFO element */
const uint32_t fifoElemIdx = 0U;
const uint32_t fifoElemAddr = (CAN0_BASE_ADDR + 0x00000C00U + (fifoElemIdx * 0x10U));
uint32_t fifoElemData[4] = {0U};
for (uint32_t i = 0U; i < 4U; i++)
{
fifoElemData[i] = (*(volatile uint32_t *)(fifoElemAddr + (i * 4U)));
}
/* Process RX FIFO element */
if ((fifoElemData[0] & CAN_RAMn_IDE_MASK) == CAN_RAMn_IDE_MASK)
{
/* Extended ID */
const uint32_t rxMsgId = (fifoElemData[0] & CAN_RAMn_ID_MASK_EXT);
const uint8_t rxMsgDlc = (fifoElemData[1] & CAN_RAMn_CS_DLC_MASK);
uint8_t rxMsgPayload[CAN_MESSAGE_BUFFER_MAX_PAYLOAD_SIZE] = {0U};
for (uint32_t i = 0U; i < (rxMsgDlc >> 2U); i++)
{
((uint32_t *)rxMsgPayload)[i] = fifoElemData[i + 2U];
}
/* Find free RX message buffer and configure it for reception */
for (msgBufIdx = 0U; msgBufIdx < CAN0_RX_MSG_BUF_NUM; msgBufIdx++)
{
if ((CAN0->RAMn[msgBufIdx].CS & CAN_CS_CODE_MASK) == CAN_CS_CODE_RX_INACTIVE)
{
break;
}
}
if (msgBufIdx < CAN0_RX_MSG_BUF_NUM)
{
/* Configure RX message buffer filter */
CAN0->RAMn[msgBufIdx].ID = (CAN_RAMn_ID_EXT(rxMsgId) | CAN_RAMn_IDE_MASK);
/* Configure RX message buffer payload size */
CAN0->RAMn[msgBufIdx].CS = CAN_CS_DLC(rxMsgDlc);
/* Configure RX message buffer for reception */
CAN0->RAMn[msgBufIdx].CS |= CAN_CS_CODE(CAN_CS_CODE_RX_FULL);
/* Copy RX message payload */
for (uint32_t i = 0U; i < CAN_MESSAGE_BUFFER_MAX_PAYLOAD_SIZE; i++)
{
can0RxMsgBuf[msgBufIdx][i] = rxMsgPayload[i];
}
}
else
{
/* RX message buffer not available */
}
}
else
{
/* Standard ID */
}
}
}
void SendCan0Msg(const uint32_t msgId, const uint8_t * const msgPayload, const uint32_t msgPayloadSize)
{
/* Find free TX message buffer and configure it for transmission */
uint32_t txMsgBufIdx = 0U;
for (txMsgBufIdx = 0U; txMsgBufIdx < CAN0_TX_MSG_BUF_NUM; txMsgBufIdx++)
{
if ((CAN0->RAMn[txMsgBufIdx].CS & CAN_CS_CODE_MASK) == CAN_CS_CODE_TX_INACTIVE)
{
break;
}
}
if (txMsgBufIdx < CAN0_TX_MSG_BUF_NUM)
{
/* Configure TX message buffer ID */
CAN0->RAMn[txMsgBufIdx].ID = (CAN_RAMn_ID_STD(msgId) | CAN_RAMn_IDE_MASK);
/* Configure TX message buffer payload size */
CAN0->RAMn[txMsgBufIdx].CS = CAN_CS_DLC(msgPayloadSize);
/* Copy TX message payload */
for (uint32_t i = 0U; i < msgPayloadSize; i++)
{
can0TxMsgBuf[txMsgBufIdx][i] = msgPayload[i];
}
/* Configure TX message buffer for transmission */
CAN0->RAMn[txMsgBufIdx].CS |= CAN_CS_CODE(CAN_CS_CODE_TX_INACTIVE);
}
else
{
/* TX message buffer not available */
}
}
int main(void)
{
/* Init board hardware */
InitClocksAndModes();
InitGpio();
InitCan0();
/* Send CAN message */
const uint32_t msgId = 0x123U;
const uint8_t msgPayload[] = {0x11U, 0x22U, 0x33U};
const uint32_t msgPayloadSize = sizeof(msgPayload);
SendCan0Msg(msgId, msgPayload, msgPayloadSize);
/* Main loop */
while (1U)
{
/* Do nothing */
}
}
```
这个例程中,我们使用了S32K144-EVB开发板上的CAN0模块,并且配置了一个接收FIFO和四个接收消息缓冲区。在初始化过程中,我们设置了CAN0的波特率为500 kbps,并且启用了CAN0模块和RX FIFO中断。在主函数中,我们发送了一个CAN消息,并且在接收中断处理函数Can0_RxIsr中读取并处理了接收到的CAN消息。
阅读全文