CANopen开启PDO定时发送后心跳帧时间错误,PDO迟迟不发送,CANopen时间轴错乱

本文探讨了在CANopen应用中使用1ms定时器中断时,如何修正计时问题,避免因PDO定时发送导致的心跳帧紊乱。关键在于调整`getElapsedTime`函数中last_time_set的更新位置,确保正确计时。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

CANopen的例子中,一种使用很多也很简单的方式是用一个1ms定时器中断,然后用全局变量重写sertimer和getElapsedTime函数,然后中断服务函数中加入timerForCan

//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;
}

但是这种方式存在一个致命问题,这种方式计算的时间,在只有心跳帧的时候是没问题的,加入PDO定时发送,就会混乱,例如1s心跳帧300msPDO定时,出现的现象是1s心跳帧保留,在1s心跳帧之后300ms会多出一个心跳帧,而PDO定时发送迟迟不出现!!!!!!,这种情况下应改为last_time_set = TimeCNT;放在timerForCan之前!!!!


```c
//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();
        }
}
//1ms中断服务函数
void TIM7_IRQHandler(void)
{
	if(TIM7->SR&0X0001)//中断
	{
		
	}
	TIM7->SR&=~(1<<0);//清除中断标志位	
	last_time_set = TimeCNT;
	timerForCan();
}

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值