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 秒的延迟。它工作正常,但在此之前我使用的其他设置不起作用。变化是:
- 将计数声明为无符号长整数 => 这导致延迟函数正常工作,但只是第一次。
- 在 for 循环的初始化步骤中将 count 声明并初始化为 int => 延迟函数根本没有按预期工作。
根据 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 < sec
到 always 为真并给你一个无限循环。
当然,解决方案是使用可以毫无问题地处理像您这样大的数字的类型。像例如unsigned long
.
哦,停止使用全局变量。 count
和 sec
都应该在延迟函数中是局部的。 和停止制作您自己的延迟函数,据我所知,Arduino 框架应该具有您可以使用的延迟函数。最后,Arduino 是用 C++ 而不是 C 编程的,尽管没有完整和适当的标准库(它使用自己的框架代替)。
我正在为要在项目中使用的 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 秒的延迟。它工作正常,但在此之前我使用的其他设置不起作用。变化是:
- 将计数声明为无符号长整数 => 这导致延迟函数正常工作,但只是第一次。
- 在 for 循环的初始化步骤中将 count 声明并初始化为 int => 延迟函数根本没有按预期工作。
根据 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 < sec
到 always 为真并给你一个无限循环。
当然,解决方案是使用可以毫无问题地处理像您这样大的数字的类型。像例如unsigned long
.
哦,停止使用全局变量。 count
和 sec
都应该在延迟函数中是局部的。 和停止制作您自己的延迟函数,据我所知,Arduino 框架应该具有您可以使用的延迟函数。最后,Arduino 是用 C++ 而不是 C 编程的,尽管没有完整和适当的标准库(它使用自己的框架代替)。