概述

环境:vivado2018.3

FPGA:xilinx

实现方式:microblaze+xilinx can IP

MBS:(microblaze system的缩写)

IP配置

CAN的配置

注意can_clk需要连接24MHz的时钟,can_phy_rx和can_phy_tx分别连接外部的can芯片即可;

microblaze配置

microblaze的配置就不贴图了,正常能把can的ip挂到外设上面即可;

MBS代码

void main(){
    XIntc_Initialize(&Intc, INTC_DEVICE_ID);//该函数调用自xintc.c
    can_init_config_and_interrupt(&Can,XPAR_CAN_0_DEVICE_ID,XPAR_INTC_0_CAN_0_VEC_ID);//初始化
    InterruptEnable();
    while(1)
}
int can_init_config_and_interrupt(XCan* can_st, u8 can_id ,u8 can_intr_id)
//int can_init_config_and_interrupt(void)
{

	int Status;
	/*
	 * Initialize the XCan driver.
	 */
	Status = XCan_Initialize(can_st, can_id);
	if (Status != XST_SUCCESS) {
		return XST_FAILURE;
	}

	/*
	 * Configure the CAN device.
	 */
	Config(can_st);
    //下面3行注释掉的代码是用来设置ID过滤的,有兴趣的可以去自己研究一下;
//	XCan_AcceptFilterDisable(can_st,0x1);
//	XCan_AcceptFilterSet(can_st, 0x1,(0x7ff << XCAN_IDR_ID1_SHIFT), (YourId<< XCAN_IDR_ID1_SHIFT));
//	XCan_AcceptFilterEnable(can_st, 0x1);

	/*
	 * Set interrupt handlers.
	 */
	XCan_SetHandler(can_st, XCAN_HANDLER_SEND,(void *)SendHandler, can_st);
	XCan_SetHandler(can_st, XCAN_HANDLER_RECV,(void *)RecvHandler, can_st);
	XCan_SetHandler(can_st, XCAN_HANDLER_ERROR,(void *)ErrorHandler, can_st);
	XCan_SetHandler(can_st, XCAN_HANDLER_EVENT,(void *)EventHandler, can_st);

	Status = XIntc_Connect(&Intc, can_intr_id, (XInterruptHandler)XCan_IntrHandler, can_st);
	XIntc_Enable(&Intc, can_intr_id);
	/*
	 * Enable all interrupts in CAN device.
	 */
	XCan_InterruptEnable(can_st, XCAN_IXR_ALL);
	XIntc_Start(&Intc, XIN_REAL_MODE);

	/*
	 * Enter Normal Mode.
	 */
	XCan_EnterMode(can_st, XCAN_MODE_NORMAL);
	while(XCan_GetMode(can_st) != XCAN_MODE_NORMAL);

	return XST_SUCCESS;
}
void InterruptEnable(void) //使能MBS中断
{
	/* Enable interrupts from the hardware */
	Xil_ExceptionInit();
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT, (Xil_ExceptionHandler)INTC_HANDLER,(void *)&Intc);
	Xil_ExceptionEnable();
}
static void SendHandler(void *CallBackRef)
{
	/*
	 * The frame was sent successfully. Notify the task context.
	 */
}
static void ErrorHandler(void *CallBackRef, u32 ErrorMask)
{

	if(ErrorMask & XCAN_ESR_ACKER_MASK) {
		/*
		 * ACK Error handling code should be put here.
		 */
	}

	if(ErrorMask & XCAN_ESR_BERR_MASK) {
		/*
		 * Bit Error handling code should be put here.
		 */
	}

	if(ErrorMask & XCAN_ESR_STER_MASK) {
		/*
		 * Stuff Error handling code should be put here.
		 */
	}

	if(ErrorMask & XCAN_ESR_FMER_MASK) {
		/*
		 * Form Error handling code should be put here.
		 */
	}

	if(ErrorMask & XCAN_ESR_CRCER_MASK) {
		/*
		 * CRC Error handling code should be put here.
		 */
	}

	/*
	 * Set the shared variables.
	 */
}
static void EventHandler(void *CallBackRef, u32 IntrMask)
{
	XCan *CanPtr = (XCan *)CallBackRef;

	if (IntrMask & XCAN_IXR_BSOFF_MASK) { /* Enter Bus off status */
		/*
		 * Entering Bus off status interrupt requires
		 * the CAN device be reset and re-configurated.
		 */
		XCan_Reset(CanPtr);
		Config(CanPtr);
		return;
	}

	if(IntrMask & XCAN_IXR_RXOFLW_MASK) { /* RX FIFO Overflow Interrupt */
		/*
		 * Code to handle RX FIFO Overflow
		 * Interrupt should be put here.
		 */
	}

	if(IntrMask & XCAN_IXR_RXUFLW_MASK) { /* RX FIFO Underflow Interrupt */
		/*
		 * Code to handle RX FIFO Underflow
		 * Interrupt should be put here.
		 */
	}

	if(IntrMask & XCAN_IXR_TXBFLL_MASK) { /* TX High Priority Full Intr */
		/*
		 * Code to handle TX High Priority Buffer Full
		 * Interrupt should be put here.
		 */
	}

	if(IntrMask & XCAN_IXR_TXFLL_MASK) { /* TX FIFO Full Interrupt */
		/*
		 * Code to handle TX FIFO Full
		 * Interrupt should be put here.
		 */
	}

	if (IntrMask & XCAN_IXR_WKUP_MASK) { /* Wake up from sleep mode */
		/*
		 * Code to handle Wake up from sleep mode
		 * Interrupt should be put here.
		 */
	}

	if (IntrMask & XCAN_IXR_SLP_MASK) { /* Enter sleep mode */
		/*
		 * Code to handle Enter sleep mode
		 * Interrupt should be put here.
		 */
	}

	if (IntrMask & XCAN_IXR_ARBLST_MASK) { /* Lost bus arbitration */

		/*
		 * Code to handle Lost bus arbitration
		 * Interrupt should be put here.
		 */
	}
}
static void RecvHandler(void *CallBackRef)
{
	XCan *CanPtr = (XCan *)CallBackRef;
	int Status;
	Status = XCan_Recv(CanPtr, RxFrame);
	if (Status != XST_SUCCESS) {
		return;
	}
	u32 CanID = (RxFrame[0] >> 21) & 0x7FF;//查看接收到的CanID;
	SendFrame(CanPtr);
	return;
}
static void SendFrame(XCan *InstancePtr)
{
	u8 *FramePtr;
	int Status;
	/*
	 * Create correct values for Identifier and Data Length Code Register.
	 */
	TxFrame[0] = XCan_CreateIdValue(YourId, 0, 0, 0, 0);//创建CAN的ID,就是做了个移位;
	TxFrame[1] = XCan_CreateDlcValue(FRAME_DATA_LENGTH);//创建CAN的长度

	FramePtr = (u8 *)(&TxFrame[2]);//把接收到的CAN数据填到发送buffer;
	memcpy(FramePtr,&RxFrame[2],8));//
	/*
	 * Now wait until the TX FIFO is not full and send the frame.
	 */
	while (XCan_IsTxFifoFull(InstancePtr) == TRUE);
	Status = XCan_Send(InstancePtr, TxFrame);
	if (Status != XST_SUCCESS)
	{
		;
	}
}

代码有引用的,有自己写的,整体思路是:

        1、先配置Can,配置中断

        2、等待接收中断

        3、进入接收数据的中断后会调用发送数据的函数发送一包数据出去;

xilinx应该也是提供了can的例程的,小伙伴也可使用例程去修改;

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐