我的思路是,用标准库的时候,定时器向上计数,串口接收到数据后,setcounter为0,定时器的计数器从头开始计数,这样当接收数据的时候,定时器不会中断。当接完一帧数据,不会给setcounter设置为0了,定时器一直计数,就会产生中断,此时处理数据,关闭定时器。
但是现在硬件定时器框架只有write control,没有控制定时器计数器的接口,想实现类似的功能应该怎么写呢?谢谢。
串口判断一帧结束应该是使用类似空闲中断的原理,比如说串口的通讯参数为 9600bps 8n1,那么一个字节的时间大约为 1ms,假设连续几个毫秒都没有收到新的数据,那么就认为这一帧数据结束了。
因此在使用定时器的时候可以每收到一个字节的数据将定时器清0,然后如果定时器的超时时间到了就认为该数据帧结束了。
怎么把定时器清零呢?rtt提供的只有write开始,control啥的。然后我不是一个字节一个字节算的,因为DMA接收会把数据断开,用定时器是为了把DMA接收断开的帧,再拼上。
我是在while里接收一部分数据,比如A0个字节,write定时器,这样有一个超时时间,设为100ms,如果超时了,说明100ms内,没有进while函数,说明一帧接收完成。
超时函数的回调函数给一个标志位,然后读取数据,stop定时器。
如果还没超时,又收到数据,那就再write,不知道可不可以在没stop的情况下write定时器,stop定时器,应该可以把定时器清空了吧。
现在单步调试的时候,每一帧都能分开,全速跑起来,就分不开了。
每两条数据的时间间隔好几s,绝对比100ms大。
代码如下:
07AA是结束符,没有区分开
@伊森亨特
直接使用 DMA + 空闲中断 也可以作为数据帧结束的判断,还能省去定时器
@伊森亨特
我还没用过硬件定时器,用的都是软件定时器,你看看 HWTIMER_CTRL_STOP 停止定时器会把定时器清 0 吗?
@伊森亨特
看了一下源码,下面这个函数可以清 0 定时器
@crystal266
没有,开启dma接收模式,就是dma半满 全满 ,串口空闲中断了,这时候接收的数据会混在一起,分不清帧。
@伊森亨特
你看看上面的 timer_stop() 函数,我看里面实现了定时器清 0 的功能。
@crystal266
这个调用control可能调用了。你看我的思路有问题吗?
@伊森亨特
调用下面这个代码
rt_device_control(hw_dev, HWTIMER_CTRL_STOP, RT_NULL);
应该是不能停止定时器的,我看这部分的源代码如下所示,这里面只实现了 HWTIMER_CTRL_FREQ_SET 这个指令。@伊森亨特
我认为
timer_ctrl
这个函数实现的不全,如果想通过timer_ctrl
实现停止的话还需要自己把停止的代码加到这个函数里面。@crystal266
我把定时器改成oneshot模式了,感觉可能是跟程序流程有关,假如数据被dma接收分成了两段,第一段接收到信号量,执行while循环,再执行下面的判断超时语句,然后接收第二段数据,同样可以接收到信号量。然后没有新的数据,定时器会超时,此时判断超时的函数在获取信号量的后面,而两段数据已经传完,不会再获得信号量了,这样后面的代码就因为县城被挂起执行不到了。直到下一针数据来到,获得信号量,才会执行到判断超时函数的语句,而此时,就会上一针数据的第二段,和这一帧数据的第一段连起来
你看我分析的有没有道理。
谢谢
@伊森亨特 不好意思啊,我没太看明白你上面那段话的逻辑,可以把你的代码传上来看一下。