-1

在这段代码中,我没有使用 while(1),只有当它进入“if”条件时,它才会调用每 250 毫秒初始化一次的 TIMER_ISR 函数。但是当它进入 else 条件时,没有任何计时器功能或其他任何东西,但还有它为什么连续运行。

#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "mcc_generated_files/mcc.h"
#include "mcc_generated_files/eusart1.h"
void main(void)
{
    SYSTEM_Initialize();    
    INTERRUPT_GlobalInterruptEnable();
    INTERRUPT_PeripheralInterruptEnable();
    char temp1[] = "ok";
    char temp2[3] = { '\0', '\0', '\0' };
    char temp3[3], temp4[3];
    int i, j;
    for (i = 0; temp1[i] != '\0'; i++)
    {
        temp3[i] = temp1[i] - 32;
        EUSART1_Write(temp3[i]);
    }
    EUSART1_String("\r\n");
    for (i = 0; i < 2; i++)
    {
        temp2[i] = EUSART1_Read();
        EUSART1_Write(temp2[i]);
    }

    EUSART1_String("\r\n");
    if (strcmp(temp1, temp2) == 0)
    {
        for (i = 0; temp1[i] != '\0'; i++)
        {
            if (temp1[i] >= 'a' && temp1[i] <= 'z')
            {
                temp1[i] = temp1[i] - 32;
            }
        }

        for (j = 0; temp1[j]; j++)
            EUSART1_Write(temp1[j]);
        //Timer initialization (timer is initialized for every 250mS)
        TMR0_Initialize();
    }
    else
        EUSART1_String("\r\nERROR GIVE'ok'");
}
4

1 回答 1

1

如果问题是:在裸机 MCU 应用程序上从 main() 返回是否有意义,那么 TL;DR:不,这没有意义,因为没有人可以返回。没有操作系统可以牵你的手——你的应用程序就是一切。

详细解释:

所有现代 MCU 都有一个称为“复位中断”的入口点。当您通电时,或者可能在看门狗电路重置 MCU 之后,或者因为您在 MCU 复位引脚上有外部 /reset 信号时,您最终会到达哪里。

然后程序计数器通过进入上电复位(有时称为复位向量)的中断服务程序来启动程序。从这里开始,设置 MCU 上最基本的东西,然后通常它会调用“C 运行时”(CRT),这是编译器特定的启动代码,用于初始化所有内存区域以启用标准 C 环境,例如初始化变量等。当 CRT 完成所有这些后,它会调用main().

或者,如果您用汇编程序编写了所有内容,则不必为 CRT 操心,而是可以从复位 ISR 中调用您喜欢的任何函数。通常这是通过直接跳转而不是函数调用来完成的,无需堆叠任何参数,因为您不希望返回。你只会不必要地浪费堆栈空间。

这就是为什么嵌入式系统中最常见的 main() 形式是void main (void),而不是严格符合 Cint main (void)的 - 后者可能由于调用约定而不必要地浪费堆栈空间。(在 gcc 编译器上,始终选择嵌入式“独立”系统作为您的目标-ffreestanding。)

现在,如果您用 C 语言编写程序并从 中返回main(),您最多会崩溃回到 CRT 代码中,如果幸运的话,某个好心人在for(;;){}那里编写了一个循环来捕获程序计数器。这在新手友好的环境中很常见。或者,您可以一直崩溃到上电复位 ISR。

或者更有可能的是,如果main()被称为上述汇编程序方式(来自 CRT 或来自您的自定义代码),您会直接跳入未知,因为没有保存返回地址。

从那里,程序计数器将在随机内存位置用完,开始执行它最终在内存中遇到的任何内容,将这些单元格的内容解释为 OP 代码,无论它们是否是 - 你会“失控”代码”,这是一个严重且危险的错误情况。它将继续这样做,直到它偶然发现导致硬件异常的事情,例如访问受保护的内存,或者直到看门狗重置所有内容,以防看门狗启用。

于 2021-03-26T10:42:09.930 回答