arduino 中断 串口_经过很长时间后,Arduino会停止向串口发送数据

本文探讨了Arduino在长时间运行后停止向串口发送数据的问题,可能原因是时钟折叠导致的中断失效。通过分析和示例代码展示了如何检查和处理时钟折叠,确保在中断和串口通信中维持正确的时间戳管理。同时,提出了比较和设置函数的改进方法,以避免类似问题,并建议优化全局变量初始化和字符串处理方式。
摘要由CSDN通过智能技术生成

时钟可能会折叠。

previousclock = millis()可能会在折叠前陷入高值。您可以扩展测试以包括(currentmilis< previousmillis)加/减一些软糖因子的情况。

BTW它使用了ignas的源代码(OP源代码在没有注册的情况下无法读取,我不想注册)

编辑:我从wakkerbot复制下面的片段,并编辑了一下。它只是为了

演示如何将wrap_action时间戳停留在int间隔的顶部(如果bump值不是int_max的除数)

你可以稍微简化上面/下面的逻辑,因为你只对内部/外部间隔测试感兴趣。 Stamp的typedef当然应该适应millis()的类型(unsigned long?)和fakemillis()删除,并用millis()替换它的引用。

#include

#define STAMP_INSIDE 0

#define STAMP_BELOW -1

#define STAMP_ABOVE 1

#define STAMP_BEYONDO -1

/* Intentionally very small, for fast wraparound

** Intentionally signed to stress test the logig.

*/

typedef signed char Stamp;

/* fake clock, returns incrementing value, but folds around

*/

Stamp fakemillis(void)

{

static Stamp ticker =0;

return ticker++;

}

/* Check if "test" is inside or above/below the interval {low,high}

** low and high may have been wrapped around zero (--> low > high)

** return

** 0 := "test" inside interval

** 1 := "test" below interval

** -1 := "test" above interval (but wrapped)

** The two impossible cases return -2.

*/

static int check_interval(Stamp low, Stamp high, Stamp test)

{

switch (4 *(high >= low)

+2 *(test >= low)

+1 *(test > high)

) {

case 0: return STAMP_INSIDE; /* inside (wrapped) */

case 1: /* outside (wrapped) */

return ((Stamp)(low - test) < (Stamp)(test - high)) ? STAMP_BELOW : STAMP_ABOVE;

case 2: break; /* impossible */

case 3: return STAMP_INSIDE; /* inside (wrapped) */

case 4: /* all below */

return ((Stamp)(low - test) < (Stamp)(test - high)) ? STAMP_BELOW : STAMP_ABOVE;

case 5: break; /* impossible */

case 6: return STAMP_INSIDE; /* inside normal case */

case 7: /* all above) */

return ((Stamp)(low - test) < (Stamp)(test - high)) ? STAMP_BELOW : STAMP_ABOVE;

}

return STAMP_BEYONDO;

}

/* Get new clock value, test if it is inside interval {*old, *old+width)

** iff inside: return STAMP_INSIDE;

** iff above (or below) return STAMP_ABOVE or STAMP_BELOW

** and UPDATE *old

*/

static int test_or_set(Stamp *old, Stamp width)

{

Stamp tick;

int diff;

tick = fakemillis();

diff = check_interval( *old, *old+width, tick);

if (!diff) return 0;

*old = tick;

return diff;

}

int main(void) {

Stamp goodlast=0;

Stamp tick=0;

Stamp badlast=0;

int goodtest;

int badtest;

unsigned uu;

for (uu = 0; uu < 260; uu++) {

tick= fakemillis();

if (tick > badlast+10) { badlast=tick; badtest=1; } else {badtest =0;}

goodtest = test_or_set ( &goodlast, 10);

printf("%x:Tick=%x bad=%x, badtest=%d good=%x goodtest=%d\n"

, uu, (unsigned) tick

, (unsigned) badlast, badtest

, (unsigned) goodlast, goodtest

);

}

return 0;

}如果您在“普通”计算机上编译并运行上述程序,您可以看到badlast和badtest卡住了。这就是你的arduino上发生的事情,恕我直言。

更新:绝对溢出/翻转。 (GIYF)

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1200662708

Update2:不相关但编码不好的做法:

#define CMD_SET_SPEED "S"

...

/* Internal configuration */

if(buffer.substring(0,1)==CMD_SET_SPEED) {

updateSpeed(buffer.substring(1));

}你在这里比较两个字符串。 (这可能是按照c ++的意图处理的,但是在C中它只是完全错误。我还建议用一个巨大的switch语句替换重复的if(...){...},这至少会避免调用substr()函数重复。(或内联?)

UPDATE 20111211:这是一个包装不经意的比较和设置函数,它需要一个指向要比较和设置的值的指针,以及预期间隔的宽度:

int test_and_set_if_beyond( unsigned long *pprev, unsigned long width )

{

unsigned long tick, low,high;

low = *pprev;

high = low+width;

tick = millis();

if (low < high) {

if (tick >= low && tick < high ) return 0; /* normal case */

}

else { /* interval is wrapped , clock could have wrapped */

if (tick >= low || tick < high) return 0;

}

*pprev = tick;

return 1;

}此函数在loop()部分中使用如下:

if (test_and_set_if_beyond ( &lightTimer, lightnessCheckPeriod)) {

int newLightness = analogRead(brightnessPin);

if(newLightness-lightness > LIGHT_TRESHOLD) {

say(RESPONSE_FLASH);

}

lightness = newLightness;

}

if (test_and_set_if_beyond ( &pingTimer, pingTimerPeriod)) {

say(RESPONSE_PING);

}

if (test_and_set_if_beyond ( &pingLEDTimer, pingTimerPeriod*2)) {

digitalWrite(failPin, HIGH);

}

feed();最后:恕我直言,RESET不起作用的原因是,并非所有全局变量都在setup()函数中初始化。另外:我认为你应该摆脱String thingies(运行时是否有GC?)并使用普通的字符缓冲区。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值