我正在为项目使用的Arduino编写延迟功能。原因是TIMER0(用于Arduino延迟的默认计时器)被PWM控制占用。延迟功能的测试代码如下:
int count;
unsigned long int sec;
void delay_ms (uint16_t millisecond) {
sec = ((16000000/12)/1000)*millisecond;
for (count = 0; count < sec; count ++);
}
void setup (){
Serial.begin(9600);
}
void loop (){
Serial.println('a');
delay_ms(1000);
Serial.println('b');
delay_ms(1000);
}
此设置仅打印a和b之间的间隔为1秒。它工作正常,但是在此之前,我使用了其他设置,这些设置不起作用。更改为:
基于Arduino参考在Unsigned Long和Int上提供的知识,我认为在这种情况下它们本质上是相同的。因此,我想对循环如何处理数据以及延迟函数进行一些说明。
答案 0 :(得分:3)
您用arduino-uno
标记了问题,并且您为int
提供的链接明确表示Uno上的int
为16位,范围为-32768至32767:< / p>
在Arduino Uno(和其他基于ATmega的板)上,一个int存储一个16位(2字节)的值。这样产生的范围是-32,768到32,767(最小值为-2 ^ 15,最大值为(2 ^ 15)-1)。
现在((16000000/12)/1000)*1000
(延迟1000
)为1333333
,它超出了int
(甚至是unsigned int
)。这意味着您的int
变量count
将在循环中溢出,并且您将拥有undefined behavior。
count
溢出时实际上发生的是它变为负(因为Uno使用two's complement表示负数)。然后,您将 up 计数为零,然后将正数计数到再次溢出,导致count < sec
始终为 为真,并给您无限循环。
当然,解决方案是使用可以处理像您这样的大数目而没有问题的类型。像unsigned long
。
哦,停止使用全局变量。 count
和sec
都应位于延迟函数内部。 然后 停止制作自己的延迟功能,AFAIK Arduino框架应该具有可以使用的延迟功能。最后,尽管没有完整和适当的标准库(而是使用自己的框架),但Arduino是用C ++而不是C编程的。