完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
转
前段时间学习了CanOpen协议,到网上下载的CanFestival3-10源码,移植到VC、QT、STM32等平台,由于网上的资源较少,走了不少弯路,移植好使用过程中才逐渐暴露出各种问题,比如OD字符串传输、心跳时间不准确等等,现在已经解决了遇到的所有问题,移植出来的工程能够完好支持CanOpen协议,花了点时间,整理出一个简单易用的移植方法说明,也写了一些比较实用的调试工具,本来还想整理SDO、PDO、EDS文件装载等相关知识的,可惜比较忙,等什么时候有空了再整理其他的吧!先把移植的贴上来,希望能帮到大家。 如果是第一次,整个移植过程还比较麻烦,需要有耐心,按照下面说的一步步来肯定可以的,移植成功一次后,再移植到其他平台就非常轻松了。 到网上下载CanFestival源码CanFestival-3-1041153c5fd2,解压出来,并将文件夹名字改为CanFestival-3-10,我们移植需要用到的源文件在CanFestival-3-10src目录下,头文件在CanFestival-3-10include目录下。 CanFestival-3-10src下的文件如下图所示: CanFestival-3-10include下的文件如下图所示: 接下来开始移植: 步骤一:在新建好的工程目录下新建文件夹CanFestival,再在CanFestival下新建文件夹driver、inc和src,再在inc文件夹下面新建stm32文件夹(我这里主要以移植到stm32为例说明,如果是移植到VC或其他平台下,这里也可以命名为其他名字,如vc)。 步骤二:将CanFestival-3-10src目录下的dcf.c、emcy.c、lifegrd.c、lss.c、nmtMaster.c、nmtSlave.c、objacces.c、pdo.c、sdo.c、states.c、sync.c、timer.c共12个文件拷贝到CanFestivalsrc目录下;将CanFestival-3-10include目录下的所有.h文件共19个文件全部拷贝到CanFestivalinc目录下,再把CanFestival-3-10examplesAVRSlave目录下的ObjDict.h文件拷贝过来,一共20个;将CanFestival-3-10includeAVR目录下的applicfg.h、canfestival.h、config.h、timerscfg.h共4个头文件拷贝到canfestivalincstm32目录下;将CanFestival-3-10examplesTestMasterSlave目录下的TestSlave.c、TestSlave.h、TestMaster.h、TestMaster.c拷贝到canfestivaldriver目录下,并在该目录下新建stm32_canfestival.c文件。 步骤三:将CanFestivalsrc目录下的所有.c文件添加到工程;将canfestivaldriver目录下的stm32_canfestival.c文件添加到工程;如果实现的是从设备,再将canfestivaldriver目录下的TestSlave.c文件添加到工程,如果实现的是主设备,则将TestMaster.c文件添加到工程; 步骤四:将文件目录canfestivalinc、canfestivalincstm32、canfestivaldriver等路径添加到工程包含路径。 步骤五:在stm32_canfestival.c中包含头文件#include "canfestival.h",并定义如下函数: void setTimer(TIMEVAL value) { } TIMEVAL getElapsedTime(void) { return 1; } unsigned char canSend(CAN_PORT notused, Message *m) { return 1; } 可以先定义一个空函数,等到编译都通过了之后,再往里面添加内容,这几个函数都是定义来供canfestival源码调用的,如果找不到这几个函数编译就会报错。 步骤六:通过以上几步,所有的文件都弄齐了,但是编译一定会出现报错,注释或删除掉config.h文件中的如下几行就能编译通过: #include #include #include #include #include #include 如果还有其他报错,那有可能是因为不同源码版本、不同平台、不同人遇到的错误也会不相同,这里的过程只能做一定的参考,不一定完全相同,解决这些错误需要有一定的调试功底,需要根据编译出错提示来进行修改对应地方,一般都是有些函数没声明或者某个头文件没有包含或者包含了一些不必要的头文件而该文件不存在或者是一些变量类型不符合需定义之类的,如果能够摆平所有的编译出错,那么移植就算成功了,如果你被编译出错摆平了,那么游戏就结束,没得玩了。 步骤七:解决了所有的编译错误后,接下来实现刚才定义的3个空函数,函数void setTimer(TIMEVAL value)主要被源码用来定时的,时间到了就需要调用一下函数TimeDispatch(),函数TIMEVAL getElapsedTime(void)主要被源码用来查询距离下一个定时触发还有多少时间,unsigned char canSend(CAN_PORT notused, Message *m)函数主要被源码用来发一个CAN包的,需要调用驱动来将一个CAN包发出去。 我们在stm32_canfestival.c文件里定义几个变量如下: unsigned int TimeCNT=0;//时间计数 unsigned int NextTime=0;//下一次触发时间计数 unsigned int TIMER_MAX_COUNT=70000;//最大时间计数 static TIMEVAL last_time_set = TIMEVAL_MAX;//上一次的时间计数 setTimer和getElapsedTime函数实现如下: //Set the next alarm // void setTimer(TIMEVAL value) { NextTime=(TimeCNT+value)%TIMER_MAX_COUNT; } // Get the elapsed time since the last occured alarm // TIMEVAL getElapsedTime(void) { int ret=0; ret = TimeCNT> last_time_set ? TimeCNT - last_time_set : TimeCNT + TIMER_MAX_COUNT - last_time_set; last_time_set = TimeCNT; return ret; } 另外还要开一个1毫秒的定时器,每1毫秒调用一下下面这个函数。 void timerForCan(void) { TimeCNT++; if (TimeCNT>=TIMER_MAX_COUNT) { TimeCNT=0; } if (TimeCNT==NextTime) { TimeDispatch(); } } can发包函数canSend跟CAN驱动有关,CAN通道可以使用真实的CAN总线,也可以使用虚拟的CAN通道(如文件接口、网络通道等等)。 启动时初始化: 在初始化的文件里(比如main.c)添加以下几行代码 #include "TestSlave.h" unsigned char nodeID=0x21; extern CO_Data TestSlave_Data; 在调用函数(比如main函数)里调用以下代码初始化 setNodeId(&TestSlave_Data, nodeID); setState(&TestSlave_Data, Initialisation); // Init the state 其中T estSlave_Data在TestSlave.c中定义 然后开启调用TimerForCan()的1毫秒定时器,在接收CAN数据那里调用一下源码函数canDispatch(&TestSlave_Data, &m); canfestival源码就可以跑了,如果需要跟主设备联调,还要实现canSend函数,这个与平台的Can驱动相关。 Stm32平台下的驱动实现: 开启一个1毫秒定时器,可参考如下代码,调用一下函数TIM4_start();即可: /* TIM4 configure */ static void TIM4_Configuration(void) { /* 时钟及分频设置 */ TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; /* Time Base configuration */ /* 72M / 72 = 1us */ // 这个就是预分频系数,当由于为0时表示不分频所以要减1 TIM_TimeBaseStructure.TIM_Prescaler =72-1; //72000 - 1; //计数模式:向上计数 TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; //这个就是自动装载的计数值,由于计数是从0开始的 //TIM_TimeBaseStructure.TIM_Period =0xffff;// TIM_TimeBaseStructure.TIM_Period =0x03e8;//1ms TIM_TimeBaseStructure.TIM_ClockDivision = TIM_CKD_DIV1; //重新计数的起始值 TIM_TimeBaseStructure.TIM_RepetitionCounter = 0; TIM_TimeBaseInit(TIM4, &TIM_TimeBaseStructure); // TIM IT enable TIM_ITConfig(TIM4, TIM_IT_CC1, ENABLE); //打开溢出中断 // TIM enable counter TIM_Cmd(TIM4, ENABLE);//计数器使能,开始工作 } static void NVIC_Configuration(void) { NVIC_InitTypeDef NVIC_InitStructure; NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3); /* Enable the TIM4 global Interrupt */ NVIC_InitStructure.NVIC_IRQChannel = TIM4_IRQn; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC_InitStructure); } static void RCC_Configuration(void) { RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO,ENABLE); /* TIM4 clock enable */ RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM4, ENABLE); /* clock enable */ RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOA ,ENABLE); } void TIM4_start(void) { RCC_Configuration(); /* configure TIM4 for remote and encoder */ NVIC_Configuration(); TIM4_Configuration(); } |
|
相关推荐
|
|
嵌入式学习-飞凌嵌入式ElfBoard ELF 1板卡-spi编程示例之spi编写程序
421 浏览 0 评论
《DNK210使用指南 -CanMV版 V1.0》第三十七章 image图像对比实验
406 浏览 0 评论
398 浏览 1 评论
465 浏览 0 评论
关于RT-Thread studio添加freemodbus控件失败的问题
739 浏览 1 评论
【youyeetoo X1 windows 开发板体验】少儿AI智能STEAM积木平台
11636 浏览 31 评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-11-8 04:37 , Processed in 0.719342 second(s), Total 69, Slave 51 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191 工商网监 湘ICP备2023018690号