Arduino——关于数据类型

Arduino - About Data Types

我正在为要在项目中使用的 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 Reference 在 Unsigned Long and Int 上提供的知识,我认为在这种情况下它们本质上是相同的。因此,我想澄清一下循环以及延迟函数如何处理数据。

您用 arduino-uno 标记了问题,您为 int 提供的 link 明确表示 Uno 上的 int 是 16 位,范围为-32768 到 32767:

On the Arduino Uno (and other ATmega based boards) an int stores a 16-bit (2-byte) value. This yields a range of -32,768 to 32,767 (minimum value of -2^15 and a maximum value of (2^15) - 1).

现在 ((16000000/12)/1000)*1000(延迟 1000)是 1333333,这 way 超出了 [=11] 的限制=](甚至 unsigned int)。这意味着您的 int 变量 count 在循环中溢出 并且您将有 undefined behavior.

count 溢出时实际发生的是它变成 负数(因为 Uno 使用 two's complement 作为负数)。然后你数 up 到零,正数直到它再次溢出,导致 count < secalways 为真并给你一个无限循环。

当然,解决方案是使用可以毫无问题地处理像您这样大的数字的类型。像例如unsigned long.


哦,停止使用全局变量。 countsec 都应该在延迟函数中是局部的。 停止制作您自己的延迟函数,据我所知,Arduino 框架应该具有您可以使用的延迟函数。最后,Arduino 是用 C++ 而不是 C 编程的,尽管没有完整和适当的标准库(它使用自己的框架代替)。