B1a*_*ge1 2 c embedded microcontroller stm32
main在C语言中,像stm32这样的嵌入式系统最基本的函数是:
int main(void) {
int i = 0;
while(1) {
i++;
}
}
Run Code Online (Sandbox Code Playgroud)
但是,由于i是一个整数,它不会溢出并因此在某些时候产生问题吗?
while(1) i++另外,在等待特定中断时使用相同的策略(使用 )循环是否安全?
编辑:感谢您的所有回答。我很遗憾不知道溢出处理程序与 C 和 C++ 有很大不同。现在我明白了 !
以下内容适用于 C 和 C++。以下所有代码均可编译为 C 和 C++。
\n\n\n为什么这个
\nmain带有递增整数的函数永远不会溢出?
它确实溢出了。然而,由于整数是有符号的,因此它是未定义的行为并且是一个错误。根据正在编译代码的编译器和硬件体系结构,编译器可能会以预期的方式处理有符号整数溢出和下溢,例如:在溢出时回绕到最小值,但这不是保证,每个都不允许语言标准,这不是一个好主意。
\n请参阅此问题中的引号:为什么无符号整数溢出定义了行为,但有符号整数溢出却没有?(强调):
\n\n\nC 和 C++ 标准都明确定义了无符号整数溢出。例如,[C99 标准][http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf] (
\n\xc2\xa76.2.5/9) 规定\n\n涉及无符号操作数的计算永远不会超过\xef\xac\x82ow, \n因为无法由结果无符号整数类型表示的结果\n会以比可表示的最大值大 1 的数字进行归约。结果类型。
\n然而,这两个标准都规定有符号整数溢出是未定义的行为。再次,来自 C99 标准 (
\n\xc2\xa73.4.3/1)\n\nunde\xef\xac\x81ned 行为的一个示例是整数 over\xef\xac\x82ow的行为
\n
下一个问题:
\n\n\n\n
while(1) i++另外,在等待特定中断时使用相同的策略(使用 )循环是否安全?
在微控制器中使用以下内容就可以了,是的:
\nint main(void) \n{\n while (1) \n {\n // loop continually as fast as the processor can, while waiting for \n // interrupts; ISR (interrupt service routine) function definitions not\n // shown \n }\n\n // On a microcontroller, this code must never be reached!\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n然而,在任何具有操作系统的系统上,您应该在 while 循环中休眠,即使只是一毫秒,以便让调度程序有机会运行其他进程。然而,在裸机(意思是:没有操作系统)微控制器上,无限 while 循环尽可能快地运行是正常的。
\n您不得依赖未定义的行为有符号整数上溢和下溢。相反,依赖于明确定义的无符号整数上溢和下溢行为。
\n这完全没问题:
\n#include <stdint.h> // for uint16_t, etc.\n\nint main(void) \n{\n uint16_t counter = 0;\n while (1) \n {\n counter++; // increment unsigned counter; overflow is fine\n\n // use the `counter` variable somewhere or else it may be optimized out\n // completely by the compiler\n\n // loop continually as fast as the processor can, while waiting for \n // interrupts; ISR (interrupt service routine) function definitions not\n // shown \n }\n\n // On a microcontroller, this code must never be reached!\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n对于无符号整数,这样的事情也完全没问题。请注意,这uint8_t是一个无符号 8 位整数,值范围为 0 到 255:
uint8_t u1 = 0 - 1; // underflows to 255 at compile-time\n\nuint8_t u2 = 0; \nu2 - 1; // underflows to 255; can be at run-time\n\nuint8_t u2 = 255;\nu2 + 1; // overflows to 0; can be at run-time\n\nuint8_t u3 = 255;\nu3 + 2; // overflows to 1; can be at run-time\n\nuint8_t timestamp_end = 128;\nuint8_t timestamp_beginning = 129;\n// The result is 255\nuint8_t time_difference = timestamp_end - timestamp_beginning; \n\ntimestamp_end = 100;\ntimestamp_beginning = 200;\n// The result is 156\ntime_difference = timestamp_end - timestamp_beginning;\nRun Code Online (Sandbox Code Playgroud)\nwhile有关微控制器中无限循环的更多信息作为示例,下面是main()Arduino 中 AVR 微控制器内核的 C++ 函数(例如:ATmega328:Arduino Uno、Nano 等)。
注意无限for (;;)循环。使用与使用orfor (;;)完全相同。在里面,它调用用户定义的函数,只要定义了该函数就调用(请参见下面的注释 1),然后重复,与处理器运行的速度一样快!您编写的其他所有内容都必须通过主循环外部的 ISR 中处理的中断来处理,或者通过主循环内部的协作多任务处理(请参阅我在此处的答案中执行此操作的一些示例代码),这确实非常有效。while (1)while (true)loop()serialEventRun()
注1:在gcc编译器中,__attribute__((weak))从未定义的函数等于0,这将导致if (serialEventRun)错误。请参阅我的eRCaGuy_hello_world存储库中的测试代码:cpp/check_addr_of_weak_undefined_funcs.cpp。示例输出位于该文件的最底部。
该serialEventRun()函数调用可选的、自定义的、用户定义的serialEvent()函数(如果已定义)。如果用户没有定义它,它就是一个声明为 的弱空函数void serialEvent() __attribute__((weak));。请参阅我对此的回答:Arduino“SerialEvent”示例代码不适用于我的 Arduino Nano。我无法接收串行数据。为什么?。
还要注意USBDevice.attach();来电。我还没有研究过它,但我怀疑将回调附加到 ISR(中断服务例程函数),以便每当(显然)发生 USB 相关中断时都会调用回调函数。
另请注意,在进入无限循环之前,用户的setup()函数仅被调用一次,for (;;)而用户的loop()函数在无限for (;;)循环内被重复调用:
https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/main.cpp:
\n#include <Arduino.h>\n\n// Declared weak in Arduino.h to allow user redefinitions.\nint atexit(void (* /*func*/ )()) { return 0; }\n\n// Weak empty variant initialization function.\n// May be redefined by variant files.\nvoid initVariant() __attribute__((weak));\nvoid initVariant() { }\n\nvoid setupUSB() __attribute__((weak));\nvoid setupUSB() { }\n\nint main(void)\n{\n init();\n\n initVariant();\n\n#if defined(USBCON)\n USBDevice.attach();\n#endif\n \n setup();\n \n for (;;) {\n loop();\n if (serialEventRun) serialEventRun();\n }\n \n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n\n\nC++ 2020 草案 n4849 6.8.1 在注释中说,
\n\n\n无符号算术不会溢出。有符号算术的溢出会产生未定义的行为 (7.1)。
\n按照标准的规定,有符号整数算术会溢出,因为指定的结果(例如加法的总和)无法用结果类型表示,而无符号算术永远不会溢出,因为操作被指定为换行,因此指定的结果是总是有代表性的。
\n
换句话说,从技术上讲,“溢出”一词意味着“无法保存指定的结果”,因此只有有符号整数才能执行此操作,但无符号整数不会执行此操作,因为它们被指定为环绕,因此它们的结果始终是可表示的。
\n这与我们(几乎所有人)使用这些词的方式相反。我们使用“溢出”来表示“环绕”,因此无符号整数可以正确溢出,但有符号整数则不会。再说一遍,从技术上讲,我们用我们的常用白话(包括我自己)来看待这些定义,甚至在我上面的回答中也是如此。
\n但是,我们不是这里的语言律师,所以我将继续说无符号整数具有“明确定义”的下溢和上溢,而有符号整数具有“未定义的行为”下溢和上溢。
\n| 归档时间: |
|
| 查看次数: |
370 次 |
| 最近记录: |