根据原理图,zynq IP配置CAN0 -- MIO10、11
使用USBCAN-E-U分析仪,配套的是ZCANPRO软件
https://blog.csdn.net/jpyjpy123/category_12463112.html
ZYNQ:PS-CAN总线功能应用_zynqcan驱动-CSDN博客
代码介绍
比较详细的介绍:(包括CAN相关概念&代码解析)
Xilinx-ZYNQ7000系列-学习笔记(26):CAN总线_zynq的can通信-CSDN博客
选择xcanps_intr_example模板,以下是CAN的配置:
#define CAN_DEVICE_ID XPAR_XCANPS_0_DEVICE_ID
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define CAN_INTR_VEC_ID XPAR_XCANPS_0_INTR
/* Maximum CAN frame length in word */
#define XCANPS_MAX_FRAME_SIZE_IN_WORDS (XCANPS_MAX_FRAME_SIZE / sizeof(u32))
#define FRAME_DATA_LENGTH 8 /* Frame Data field length */
/*
* Message Id Constant.
*/
#define TEST_MESSAGE_ID 2000
/*
* Timing parameters to be set in the Bit Timing Register (BTR).
* These values are for a 40 Kbps baudrate assuming the CAN input clock
* frequency is 24 MHz.
*/
#define TEST_BTR_SYNCJUMPWIDTH 3
#define TEST_BTR_SECOND_TIMESEGMENT 2
#define TEST_BTR_FIRST_TIMESEGMENT 15
/*
* The Baud rate Prescalar value in the Baud Rate Prescaler Register
* needs to be set based on the input clock frequency to the CAN core and
* the desired CAN baud rate.
* This value is for a 40 Kbps baudrate assuming the CAN input clock frequency
* is 24 MHz.
*/
#define TEST_BRPR_BAUD_PRESCALAR 29
/// Calculate baudrate = CAN_CLK / ((SYNCJUMPWIDTH + SECOND_TIMESEGMENT + FIRST_TIMESEGMENT ) * (PRESCALAR + 1))
/// 40K = 24M / (( 3 + 2 + 15 ) * ( 29 + 1))
波特率 baudrate = CAN_CLK / ((SYNCJUMPWIDTH + SECOND_TIMESEGMENT + FIRST_TIMESEGMENT ) * (PRESCALAR + 1))
CAN_CLK在zynq IP配置界面设置。
s32 XCanPs_SelfTest(XCanPs *InstancePtr)
{
u8 *FramePtr;
s32 Status;
u32 Index;
u8 GetModeResult;
u32 RxEmptyResult;
Xil_AssertNonvoid(InstancePtr != NULL);
Xil_AssertNonvoid(InstancePtr->IsReady == XIL_COMPONENT_IS_READY);
XCanPs_Reset(InstancePtr);
/*
* The device should enter Configuration Mode immediately after
* reset above is finished. Now check the mode and return error code if
* it is not Configuration Mode.
*/
if (XCanPs_GetMode(InstancePtr) != XCANPS_MODE_CONFIG) {
Status = XST_FAILURE;
return Status;
}
//波特率设置
(void)XCanPs_SetBaudRatePrescaler(InstancePtr, (u8)29U);
(void)XCanPs_SetBitTiming(InstancePtr, (u8)3U, (u8)2U, (u8)15U);
/*
* Enter the loop back mode.
*/
XCanPs_EnterMode(InstancePtr, XCANPS_MODE_LOOPBACK);
GetModeResult = XCanPs_GetMode(InstancePtr);
while (GetModeResult != ((u8)XCANPS_MODE_LOOPBACK)) {
GetModeResult = XCanPs_GetMode(InstancePtr);
}
// ID和端口 Length
TxFrame[0] = (u32)XCanPs_CreateIdValue((u32)2000U, (u32)0U, (u32)0U, (u32)0U, (u32)0U);
TxFrame[1] = (u32)XCanPs_CreateDlcValue((u32)8U);
FramePtr = (u8 *)((void *)(&TxFrame[2]));
for (Index = 0U; Index < 8U; Index++) {
if(*FramePtr != 0U) {
*FramePtr = (u8)Index;
*FramePtr++;
}
}
/*
* Send the frame.
*/
Status = XCanPs_Send(InstancePtr, TxFrame);
if (Status != (s32)XST_SUCCESS) {
Status = XST_FAILURE;
return Status;
}
/*
* Wait until the frame arrives RX FIFO via internal loop back.
*/
RxEmptyResult = XCanPs_ReadReg(((InstancePtr)->CanConfig.BaseAddr),
XCANPS_ISR_OFFSET) & XCANPS_IXR_RXNEMP_MASK;
while (RxEmptyResult == (u32)0U) {
RxEmptyResult = XCanPs_ReadReg(((InstancePtr)->CanConfig.BaseAddr),
XCANPS_ISR_OFFSET) & XCANPS_IXR_RXNEMP_MASK;
}
/*
* Receive the frame.
*/
Status = XCanPs_Recv(InstancePtr, RxFrame);
if (Status != (s32)XST_SUCCESS) {
Status = XST_FAILURE;
return Status;
}
/*
* Verify Identifier and Data Length Code.
*/
if (RxFrame[0] !=
(u32)XCanPs_CreateIdValue((u32)2000U, (u32)0U, (u32)0U, (u32)0U, (u32)0U)) {
Status = XST_FAILURE;
return Status;
}
if ((RxFrame[1] & ~XCANPS_DLCR_TIMESTAMP_MASK) != TxFrame[1]) {
Status = XST_FAILURE;
return Status;
}
for (Index = 2U; Index < (XCANPS_MAX_FRAME_SIZE_IN_WORDS); Index++) {
if (RxFrame[Index] != TxFrame[Index]) {
Status = XST_FAILURE;
return Status;
}
}
/*
* Reset device again before returning to the caller.
*/
XCanPs_Reset(InstancePtr);
Status = XST_SUCCESS;
return Status;
}
ID为2000
详细代码:
CAN总线介绍及在ZYNQ 7020中的应用_zynq can-CSDN博客
驱动下载
CAN设备打不开:
设备管理器中是未知设备
下载驱动试试看
更新驱动程序-->不选择搜索,选择从磁盘安装
可以识别到了:(用ECANTools的驱动就显示为ECANTOOLS_CAN(大概是这么个名字,反正就是从名字上可以看出它用的软件或者USBCAN硬件))
看USBCAN-E-U的手册:SYS亮绿灯(之前亮红灯说明驱动不对)
用ZCANPro软件(USBCAN-E-U配套的软件)
SDK操作
1. xilinx SDK如何退出Debug:
xilinx sdk退出Debug模式回到C开发布局_xilinx sdk step over 进入 .s-CSDN博客
2. 添加Linker script
右键工程,选择Properties
3. SDK打开界面:(vivado重新打开就好)
sdk debug 无法进入main,且无法单步调试
Xilinx SDK程序Debug无法在main函数入口处停住解决_sdk 调试不进main-CSDN博客
ZYNQ SDK DEBUG 无法进入main函数_zynq cpu0不进入main-CSDN博客
有时候debug还会出现如下界面:
Xilinx Toos --> Generate linker script:(下面三个改成ram) (后面又改回来了)
这里要选NO:(后面都选yes了,因为选no还会再出现)
然后就直接main跑完了。。。。
但是改了以下设置,加了断点(没用),程序就跑飞了:
(到了汇编的界面了)
Xilinx SDK程序Debug无法在main函数入口处停住解决_sdk 调试不进main-CSDN博客
关于zynq debug进入main函数或汇编函数的小技巧_使用 xilinx sdk 进行单步 debug 时,如何不让程序进入汇编代码?-CSDN博客
zynq IP很重要,但回去看了一下,配置也没有错误。
发现不是跑飞,因为Console可以看到printf的输出:
修改代码,while(1)让CAN一直发送数据
ZCANPRO能接收到。
那么现在看看接收数据的代码怎么写。
第一次接收,数据长度和ZCANPRO发送的不一致;强制修改data_length为8后
两次接收到的数据的顺序都乱了。
/* 接收后发送 */
canRevFrame.ID = ID_RECEIVED;
canRevFrame.remote = 0;
canRevFrame.len = 8;
/* TxFrame[1] = (u32)XCanPs_CreateDlcValue(frame.len); */
FramePtr = (u8 *)(&RxFrame[2]);
for (Index = 0; Index < 8; Index++) {
canRevFrame.data[Index] = *FramePtr++;
}
Status = CAN0_SendFrame(canRevFrame);
/* 发送 */
FramePtr = (u8 *)(&TxFrame[2]);
for (Index = 0; Index < 8; Index++) {
*FramePtr++ = data[Index];,
}
换成这样就可以了:
Status = XCanPs_Send(CanInstPtr, RxFrame);