一、 内容介绍
从零开始,在ZYNQ开发板上移植cnafestival,并最终控制电机运动。主要分别五部分
1. Vivado导出硬件XSA文件
2. 创建vitis工程,并移植Canfestival
3. 对象字典工具的安装及使用
4. 开发板通过SDO报文配置电机PDO参数
5. 开发板通过PDO报文控制电机运动
二 硬件介绍
1、支持Canopen协议的电机
2、zynq芯片的开发板
3、can分析仪,用来抓取监听Canopen报文
三、资料介绍
主要包括这些文件,里面包括了完整的Vitis工程代码,以及非常有用的Canopen相关的文档使用教程
四 、Canfestival介绍及下载
CanFestival 是一个开源的 CANopen 协议栈,专为嵌入式系统设计。以下是其核心特点的简要总结:
-
功能
- 支持 CANopen 核心协议(NMT、PDO、SDO、对象字典等)。
- 适用于工业自动化、机器人、汽车电子等领域。
-
优势
- 开源免费(LGPL 许可证)。
- 跨平台,支持多种操作系统和微控制器。
- 提供代码生成工具(如
objdictgen
),简化开发。
-
应用
- 适合资源有限的嵌入式系统。
- 广泛应用于需要 CANopen 通信的场景。
-
官网下载源码
五 、移植
1 、根据vivado导出的xsa文件,创建一个vitis工程

2 、Canfestival文件夹中复制源码库的src和include文件夹相关文件,到vitis工程中

移植c文件
移植H文件

此外还需要移植一个config.h文件
六 、修改vitis工程中的驱动代码
移植代码,我们编译后,会报错。要进行代码修改
1、start_and_seek_node() 和 start_node(),这两个函数把inline去掉
2、编写实现canSend() getElapsedTime() setTimer()这三个函数
- canSend() ,作用是发送can数据,最终canfestival库发送数据,都会调用canSend()函数.
- getElapsedTime(),作用是软件定时器的修正(通过一个硬件定时器,来模拟多个软件定时器).
- -setTimer(),作用是改变硬件定时器的溢出周期
3、编写代码,配置硬件can口和硬件定时器。注意can口波特率不要配置错误
4、导入对象字典文件Mater.h 和Master.c文件
5、修改static.c文件中_preOperational和_operational函数,切换状态时候,能发送NMT报文
6、根据硬件定时器周期,修改timerscfg.h中的TIMEVAL_MAX 、MS_TO_TIMEVAL、US_TO_TIMEVAL。
c
#define TIMEVAL_MAX 0X0FFFFFFF
#define MS_TO_TIMEVAL(ms) ms*1000L
#define US_TO_TIMEVAL(us) us*1L
7、修改timers.c中的TimeDispatch函数
8、修改applicfg.h文件中的MSG宏定义,可以输出调试信息
c
/* Definition of error and warning macros */
/* -------------------------------------- */
#define MSG(...) xil_printf(__VA_ARGS__)
/* Definition of MSG_ERR */
/* --------------------- */
#define MSG_ERR(num, str, val) \
//MSG("ERR:%s,%d : 0X%x, %s 0X%x \r\n",__FILE__,__LINE__,num,str,val);
/* Definition of MSG_WAR */
/* --------------------- */
#define MSG_WAR(num, str, val) \
//MSG("WAR:%s,%d : 0X%x, %s 0X%x \r\n",__FILE__,__LINE__,num,str,val)
9、修改完后,在main函数中添加代码如下,canfestival能会定时的发送同步报文
c
int main()
{
init_platform();
canfestival_port_Init();//can、硬件定时器,中断初始化
setState(&Master_Data,Initialisation);
while(1)
{
sleep(1);
}
print("Hello World\n\r");
print("Successfully ran Hello World application");
cleanup_platform();
return 0;
}
c
//master.c 同步报文参数的设置 100ms循环发送
/* index 0x1005 : SYNC COB ID. */
UNS32 Master_obj1005 = 0x40000080; /* 1073741952 */
ODCallback_t Master_Index1005_callbacks[] =
{
NULL,
};
subindex Master_Index1005[] =
{
{ RW, uint32, sizeof (UNS32), (void*)&Master_obj1005 }
};
/* index 0x1006 : Communication / Cycle Period. */
UNS32 Master_obj1006 = 0x186A0; /* 100000us */
ODCallback_t Master_Index1006_callbacks[] =
{
NULL,
};
subindex Master_Index1006[] =
{
{ RW, uint32, sizeof (UNS32), (void*)&Master_obj1006 }
};
七 、其他介绍
1、开发板发送SDO报文,主要是通过writeNetworkDict这个函数实现
c
UNS8 writeNetworkDict (CO_Data* d, UNS8 nodeId, UNS16 index,
UNS8 subIndex, UNS32 count, UNS8 dataType, void *data, UNS8 useBlockMode)
{
return _writeNetworkDict (d, nodeId, index, subIndex, count, dataType, data, NULL, 1, useBlockMode);
}
2、开发板作为主站,也就是客户端,注意TPDO和RPDO的ID 要设置正确。通过PDO绑定的变量控制电机运动
主要需要电机以下对象索引参数

最终把代码下载到开发板中,控制电机运动
8、完整视频教程 及 全部资料 获取
