FPGA实现CAN总线
环境:vivado2018.3实现方式:microblaze+xilinx can IPMBS:(microblaze system的缩写)
·
概述
环境: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的例程的,小伙伴也可使用例程去修改;
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)