CANFestival移植过程中1S心跳发两次的问题

时间:2024-03-16 12:38:54

CANFestival

CANFestival的移植

这个网上有很多,输入关键词就可以找到。这里仅指从站的移植
不过,我还是放一个原版链接(http://bbs.21ic.com/icview-878522-1-1.html)。

移植问题

按照以上方法,移植完成后,代码是可以正常运行的,不过在程序的运行中遇到了问题。
首先在字典中0x1017处设置producer心跳为1s。
1. 板子上电后,自动发送boot-up,然后1s发送一次心跳状态为7F;
2. 当对板子发送SDO或者NMT数据后,发送的心跳状态变为1S发送两次,两次时间之和为1S。

CANFestival移植过程中1S心跳发两次的问题
刚开始学习这个,碰到问题也摸不着头脑,只能去读关于时间处理这部分的代码

问题分析

//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();
}
}
首先getElapsedTime();这个函数被TimeDispatch();和SetAlarm();这两个函数调用
而SetAlarm();又在很多函数中调用。
所以就改变了getElapsedTime();的返回值ret≠1000us,以至于计算NextTime=1000-ret;
这也就形成了一个循环。

解决方法

将TIMEVAL getElapsedTime(void);函数中的last_time_set = TimeCNT;移到TimeDispatch();的前面
//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;

return ret;
}
另外还要开一个1毫秒的定时器,每1毫秒调用一下下面这个函数。
void timerForCan(void)
{
TimeCNT++;
if (TimeCNT>=TIMER_MAX_COUNT)
{
TimeCNT=0;
}
if (TimeCNT==NextTime)
{
last_time_set = TimeCNT;
TimeDispatch();
}
}
然后再去测试一下
CANFestival移植过程中1S心跳发两次的问题
解决问题
参考:
可以看一下这个https://www.amobbs.com/thread-5688488-1-1.html?_dsign=e79ff9a5下的回复链接的代码