CANOpen移植(CanFestival移植)
wwwblogs/tdyizhen1314/p/4348666.html
wwwblogs/ChYQ/p/5719469.html
settimer头文件在⽹上下载CanFestival源码最新版本CanFestival-3-884a60cbb83e
建⽴以下⽂件夹:
inc⽂件夹:放LM3S8962硬件相关以及驱动部分的头⽂件,adc.h、hw_adc.h等等;
Lib⽂件夹:放集成库⽂件driverlib.lib,这个需要⽐较新的,因为遇到⽼的库⽂件缺少CANbitset()函数;
Startup⽂件夹:放启动代码,Keil软件⾃⾝提供的,只需要加⼊定时器中断(CANopen需要⼀个16位定时器)和CAN接收中断处理函数;
Target⽂件夹:⽬标板初始化代码,其实就是设置系统时钟吧!其实设置的50M;
CANopen_source⽂件夹:包括CANopen源⽂件,下载的源码中有13个,不过本次移植dcf.c、lss.c、symbols.c⽂件没有⽤到,其中不包含对象字典⽂件ObjDict.c,该⽂件我们选取的是examples\AVR\Slave
中的ObjDict.c,是从节点的对象字典;
CANopen_include⽂件夹:包括CANopen头⽂件,即下载的⽂件夹的\include⽬录下的公共⽂件19个,然后我们把ObjDict.h加进来了,那⼀共20个,但是有2个应该不会⽤到(lss.h、dcf.h),因为未⽤对应的C⽂件;
user⽂件夹:存放main.c、includes.h(包括inc中的头⽂件以及其他⽂件如CANopen相关的)、以及\include\AT91⽬录下的4个头⽂件,分别为applicfg.h、canfestival、config.h、timerscfg.h
需要注意的地⽅:
CANopen中的timer.h和can.h与库头⽂件中的⽂件重名了,需要修改CANopen中的⽂件名,⽽且CANopen源⽂件中引⽤该头⽂件的地⽅也需要修改过来,我们将其改名为
CANopen_timer.h、CANopen_can.h。Keil软件提供了全局查的功能,可以⽅便查。
Keil⾥全局查Message时,在.h⽂件中没有到,其实在CANopen_can.h中有Message的定义,估计是h⽂件没有包含进⼊⼯程吧!我们只是option for target中的C/C++的包含⽬录中添加了头⽂件所在的路径,以后可以将h⽂件加⼊⼯程
建⽴新的⼯程,将上述⽂件加⼊⼯程,然后编写简单的main.c函数,开始编译改错
编译错误:
1)SDO中发现SDO_BLOCK_SIZE常量未定义,在SDO.c中增加定义#defineSDO_BLOCK_SIZE 10
2)CO_Data结构体中⽤到了未定义的ObjDict_obj100C,故在对象字典中增加定义
3)Link错误:⽐如未实现voidsetTimer(TIMEVALvalue)、TIMEVALgetElapsedTime(void)等等。实现上述函数是移植的关键
......
修改直⾄编译通过,然后写简单的测试代码,测试⼼跳报⽂、TPDO、RPDO、SDO功能,当然是从最简单的⼼跳报⽂开始,测试时发现了犯了⼀个错误,搞错
UNS8canSend(CAN_PORT notused, Message *m)函数类型,之前采⽤的UNS8canSend(Message *m) ,解决这个问题后所有的功能就正常了。这个是通过跟踪调试发现的,具体跟踪如下:
setState(&ObjDict_Data, Initialisation); 之后会⾃动跳到Pre_operational状态,该状态⽀持{0, 1, 1, 1, 1, 0, 1};分别对应csLSS、csSDO、csSYNC、csLifeGuard、csEmergency、csPDO、csBoot_Up,由此可知仅不⽀持csLSS和csPDO功能。
switchCommunicationState()中会执⾏StartOrStop(csLifeGuard,lifeGuardInit(d),lifeGuardStop(d))
这就会执⾏lifeGuardInit(d),就会执⾏heartbeatInit(d);定时时间到就会执⾏ProducerHeartbeatAlarm(),该函数就会调⽤底层CAN发送函数canSend(d->canHandle,&msg );发送⼼跳报⽂,帧ID为0x701
SDO测试结果截图,读取对象字典对象索引0x1017的第0个数据(标号是从0开始的)
USB-CAN卡发送帧ID 0x601  数据40 17 10 00 00 00 00 00//
从节点返回:帧ID 0x581  数据4b 17 10 00 10 27 00 00
USB-CAN卡发送帧ID 0x601  数据23 00 18 01 01 02 00 00//改写索引0x1800⼦索引0x01即TPDO1对应的帧ID为0x00000201从节点返回:帧ID 0x581  数据40 00 18 01 00 00 00 00//读取索引0x1800⼦索引0x01即TPDO1对应的帧ID
USB-CAN卡发送SYNC,从节点收到之后C触发发送TPDO,我们设置的TPDO是同步⽅式,⽽且受到⼀个SYNC就发送TPDO
从以上结果可以知道移植的CANopen从节点功能正常。
调试时还发现⼀个问题:
TIMER_HANDLE SetAlarm()函数中有⼀条语句有问题,需要加上强制类型转换:
if (row_number == (TIMER_HANDLE)last_timer_raw + 1) last_timer_raw++;
也即下⾯的问题:
U16 i = 0;
U16 j = -1;
i != (j + 1),其实j + 1为65536
故需要加强制类型转换
i == (U16)(j + 1) 成⽴
⼀个硬件⼯程师的故事