Zynq移植canopen协议站canfestival+控制电机运动



一、 内容介绍

从零开始,在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 协议栈,专为嵌入式系统设计。以下是其核心特点的简要总结:

  1. 功能

    • 支持 CANopen 核心协议(NMT、PDO、SDO、对象字典等)。
    • 适用于工业自动化、机器人、汽车电子等领域。
  2. 优势

    • 开源免费(LGPL 许可证)。
    • 跨平台,支持多种操作系统和微控制器。
    • 提供代码生成工具(如 objdictgen),简化开发。
  3. 应用

    • 适合资源有限的嵌入式系统。
    • 广泛应用于需要 CANopen 通信的场景。
  4. 官网下载源码


五 、移植

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、完整视频教程 及 全部资料 获取

相关推荐
LabVIEW开发12 天前
LabVIEW利用CANopen的Batch SDO写入
labview·canopen
萨文 摩尔杰1 个月前
ZYNQ-IP-AXI-GPIO
fpga开发·zynq
如何学会学习?1 个月前
4 AXI USER IP
zynq·axi·mpsoc·zcu106
如何学会学习?1 个月前
5-1 创建和打包AXI Interface IP
ip·zynq·axi·mpsoc·zcu106
如何学会学习?1 个月前
1 使用EMIO
fpga开发·zynq·emio·zcu106·ug1244
一叶知秋h2 个月前
ZYNQ初识10(zynq_7010)UART通信实验
笔记·学习·zynq
一叶知秋h2 个月前
ZYNQ初识7(zynq_7010)RAM_IP核
笔记·学习·zynq
如何学会学习?2 个月前
10. zynq应用开发--camke编译
cmake·zynq·petalinux·mpsoc·acu106·zcu106
不想写代码的我3 个月前
基于ZYNQ-7000系列的FPGA学习笔记11——IP核之单端RAM读写
笔记·学习·fpga开发·嵌入式·zynq