news 2026/7/13 15:52:29

CANopen学习记录(三)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CANopen学习记录(三)

现在开始学习使用如何使用canfestival去移植CANopen。直接去CANopen的官网去下载https://canfestival.org/code.html.en或者GitHub - ljessendk/CanFestival · GitHub。有时候官方下载不了,挂梯子也没有用!真的是恶心!

(一)开始移植Canfestival源码

下面我使用了STM32CubeMX创建了一个新的工程,将从github上面下载的canfestival源码下的所有被圈到的源文件和头文件全部放到新建的工程里面。

最终大概是这个样子:

至此和CANopen所有相关的代码都添加进工程里面了,接下来我们需要开始修改源码去适配CANopen。

(1)报错"..\Canfestival\Inc\config.h(34): error: #5: cannot open source input file "avr/io.h": No such file or directory"

在config.h文件中把下面图片我28~47行全屏蔽掉!

(2)报错"..\Canfestival\Inc\applicfg.h(29): error: #5: cannot open source input file "avr/interrupt.h": No such file or directory"

把所有涉及到avr/interrupt.h文件全部屏蔽掉

(3)报错"..\Canfestival\Inc\objdictdef.h(99): error: #3092: anonymous unions are only supported in --gnu mode, or when enabled with #pragma anon_unions"

是因为编码器版本太旧导致的,在魔术棒->Target下替换更新版本的编译器即可。

(4)报错"CANopen\CANopen.axf: Error: L6218E: Undefined symbol start_and_seek_node (referred from dcf.o)."和"CANopen\CANopen.axf: Error: L6218E: Undefined symbol start_node (referred from dcf.o)."

是因为编译器不支持inline,在其前面添加static即可决绝

(5)报错"CANopen\CANopen.axf: Error: L6218E: Undefined symbol canSend (referred from emcy.o)."

是因为你没有支持CAN控制器,需要在STM32CubeMx中添加CAN控制器:

有可能会出现STM32CubeMX生成代码后编译发现canfestival里面自带的CAN.h文件与STM32CubeMx生成的冲突了。修改修改一下文件名。

有些工程生成的配置全部集成到main.c文件里面了,这种情况没有出现冲突就不需要改了。目前我的工程是没有出现冲突的!

然后在工程里面添加canfestival.c文件,在文件中添加如下内容:

#include "stm32f1xx_hal.h" #include "canfestival.h" #include "testslave.h" #include "can.h" #include "timerscfg.h" extern CAN_HandleTypeDef hcan; CAN_TxHeaderTypeDef TxHeader; CAN_RxHeaderTypeDef RxHeader; uint8_t CanFestival_Can_Init(void) { CAN_FilterTypeDef sFilterConfig; /* Configure the CAN Filter */ sFilterConfig.FilterBank = 0; sFilterConfig.FilterMode = CAN_FILTERMODE_IDMASK; sFilterConfig.FilterScale = CAN_FILTERSCALE_32BIT; sFilterConfig.FilterIdHigh = 0x0000; sFilterConfig.FilterIdLow = 0x0000; sFilterConfig.FilterMaskIdHigh = 0x0000; sFilterConfig.FilterMaskIdLow = 0x0000; sFilterConfig.FilterFIFOAssignment = CAN_RX_FIFO0; sFilterConfig.FilterActivation = ENABLE; sFilterConfig.SlaveStartFilterBank = 14; if (HAL_CAN_ConfigFilter(&hcan, &sFilterConfig) != HAL_OK) { /* Filter configuration Error */ Error_Handler(); } /* Start the CAN peripheral */ if (HAL_CAN_Start(&hcan) != HAL_OK) { /* Start Error */ Error_Handler(); } /* Activate CAN RX notification */ if (HAL_CAN_ActivateNotification(&hcan, CAN_IT_RX_FIFO0_MSG_PENDING) != HAL_OK) { /* Notification Error */ Error_Handler(); } /* Configure Transmission process */ return 0; } /** * @brief Rx Fifo 0 message pending callback in non blocking mode * @param CanHandle: pointer to a CAN_HandleTypeDef structure that contains * the configuration information for the specified CAN. * @retval None */ void HAL_CAN_RxFifo0MsgPendingCallback(CAN_HandleTypeDef *CanHandle) { Message RxMSG ; HAL_CAN_GetRxMessage(&hcan, CAN_RX_FIFO0, &RxHeader, RxMSG.data); RxMSG.cob_id = (uint16_t)(RxHeader.StdId); if( RxHeader.RTR == CAN_RTR_REMOTE ) { RxMSG.rtr = 1; } else { RxMSG.rtr = 0; } RxMSG.len = RxHeader.DLC; canDispatch(&TestSlave_Data, &(RxMSG)); } uint8_t canSend(CAN_PORT notused, Message *message) { CanTxMsg TxMessage; uint32_t TxMailbox = 0; TxHeader.DLC = message->len; memcpy(TxMessage.Data, message->data, message->len); TxHeader.IDE = CAN_ID_STD; TxHeader.StdId = message->cob_id; TxHeader.RTR = (message->rtr == CAN_RTR_DATA) ? 0 : 2; while(( HAL_CAN_AddTxMessage(&hcan,&TxHeader,TxMessage.Data,&TxMailbox)!=HAL_OK)) { return 0; } return 1; } void setTimer(TIMEVAL value) { TIM2->ARR = TIM2->CNT + value; } TIMEVAL getElapsedTime(void) { return TIM2->CNT; }
#ifndef __CAN_CANFESTIVAL__ #define __CAN_CANFESTIVAL__ #include "applicfg.h" #include "stdint.h" typedef struct { uint32_t StdId; /*!< Specifies the standard identifier. This parameter can be a value between 0 to 0x7FF. */ uint32_t ExtId; /*!< Specifies the extended identifier. This parameter can be a value between 0 to 0x1FFFFFFF. */ uint8_t IDE; /*!< Specifies the type of identifier for the message that will be transmitted. This parameter can be a value of @ref CAN_identifier_type */ uint8_t RTR; /*!< Specifies the type of frame for the message that will be transmitted. This parameter can be a value of @ref CAN_remote_transmission_request */ uint8_t DLC; /*!< Specifies the length of the frame that will be transmitted. This parameter can be a value between 0 to 8 */ uint8_t Data[8]; /*!< Contains the data to be transmitted. It ranges from 0 to 0xFF. */ } CanTxMsg; // --------- to be called by user app --------- void initTimer(void); UNS8 canSend(CAN_PORT notused, Message *m); UNS8 canChangeBaudRate(CAN_PORT port, char* baud); uint8_t CanFestival_Can_Init(void); #endif

如果最后只剩下一个报错"../Canfestival/Src/canfestival.c(3): error: 'testslave.h' file not found"

说明移植成功了,这个testslave.h是在配置对象字典的时候生成的。

(二)生成对象字典:

前面编译只剩下一个报错了,这个报错可能是确实对象字典导致的!

https://www.python.org/ftp/python/2.7.15/python-2.7.15.amd64.msi

wxPython2.8-win64-unicode-2.8.12.1-py27.exe

Pythonwxpython(Python的图形界面)安装按照默认的方式安装即可。上面是这两个软件的下载链接。上面的两个软件都安装完成后,就到CanFestival-master->objdictgen目录下解压Gnosis_Utils-current.tar.gz这个压缩包。

Gnosis_Utils-current目录下有gnosis目录,将这个文件夹拷贝到CanFestival-master->objdictgen目录下。完成后双击objdictedit.py文件打开软件。

下面是安装过程踩到的坑:

(1)打开objdictedit.py 报错:n objdictedit.py install Traceback (most recent call last): File "objdictedit.py", line 24, in <module>import wx File "C:\Python27\lib\site-packages\wx-2.8-msw-unicode\wx\__init__.py", line 45, in <module>from wx._core import *File "C:\Python27\lib\site-packages\wx-2.8-msw-unicode\wx\_core.py", line 4, in <module>import _core_ImportError: DLL load failed: %1 不是有效的 Win32 应用程序。

这种情况是因为安装的Python版本和wxpython版本不匹配导致的,刚刚开始我安装的是Python2.7.10和wxPython2.8-win64-unicode-2.8.12.1-py27。打开软件会闪退,有的人的电脑安装这两个版本就可以。可能是不同的Window版本对于的Python版本也有差异导致的。遇到这种情况大概率是Python版本的问题,或者是Python版本是对于的,你的电脑的环境变量里面没有填Python的路径添加进去导致的。

(2)错误: <class wx. core PyAssertionError'>: Ct+ assertion "Assert failure" faled at. Mlsrcmswfontcpp (647) in waNativeFontinfo:Setfamiy0:invalid font family

遇到这种情况是因为wxpython版本导致的,可能是版本太新了,重新安装一下旧的版本尝试一下一般都可以解决。

上面的问题都解决之后,下面我们开始创建对象字典去简单测试:

把这里的变量名修改一下即可。目前已经编译通过了

目前我手上还没有测试条件,等待我的USB转CAN到了之后再补一篇文档吧

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/13 15:51:25

15_Python迭代器、生成器与推导式:写出更优雅的循环代码

Python迭代器、生成器与推导式&#xff1a;写出更优雅的循环代码 前面写循环时&#xff0c;你一直用 for i in range(100) 或 for item in my_list&#xff0c;没出过问题。但你有没想过——为什么 range(100) 和 my_list 都能放在 for 后面&#xff1f;range 不是列表&#xf…

作者头像 李华
网站建设 2026/7/13 15:47:47

Gammazero/Deque社区贡献指南:如何参与这个高性能队列项目的开发

Gammazero/Deque社区贡献指南&#xff1a;如何参与这个高性能队列项目的开发 【免费下载链接】deque Fast ring-buffer deque (double-ended queue) 项目地址: https://gitcode.com/gh_mirrors/deque3/deque Gammazero/Deque是一个高性能的环形缓冲区双端队列实现&#…

作者头像 李华
网站建设 2026/7/13 15:47:01

132、EDVR实战:基于可变形卷积的视频超分网络训练与优化

132、EDVR实战:基于可变形卷积的视频超分网络训练与优化 上个月调EDVR的时候,我差点把服务器搞崩了。原因是显存占用直接飙到了24G,而我的RTX 3090只有24G——你懂的,就差那么一丁点就OOM了。后来发现是DataLoader的batch size和帧数没算清楚,一个简单的配置失误让我浪费了…

作者头像 李华
网站建设 2026/7/13 15:42:36

Java笔记6-字符串

一、BigDecimal 精准浮点运算1. 问题double/float 二进制存储存在精度丢失double a1.06,b1.01; System.out.println(ab); //2.07000000000000032. 核心说明包&#xff1a;java.math.BigDecimal 推荐构造&#xff1a;new BigDecimal("数值")&#xff0c;避免 double 入…

作者头像 李华
网站建设 2026/7/13 15:41:30

如何快速集成GlassActionBar:3种主流ActionBar实现方案对比

如何快速集成GlassActionBar&#xff1a;3种主流ActionBar实现方案对比 【免费下载链接】GlassActionBar Android - a library that adds a glass-like effect to the action bar. 项目地址: https://gitcode.com/gh_mirrors/gl/GlassActionBar GlassActionBar是一款专为…

作者头像 李华