2501_94708778 2026-02-02 21:43 采纳率: 0%
浏览 12

stm32单片机运行跑飞

img

img


给stm32f103zet6单片机烧录程序成功 ,但运行程序时总是跑飞(标准库、HAL库、寄存器都一样),如图,pc寄存器跑飞的地址都一样。stlink烧录时boot0和boot1都设置的0。把boot0设置成1,用串口烧录且选中其带的“编译后执行功能”,可正常运行,但是复位或者重新上电后又是跑飞不能执行,这是什么问题呀。

  • 写回答

4条回答 默认 最新

  • 檀越@新空间 2026-02-02 21:44
    关注

    晚上好🌙🌙🌙
    本答案参考通义千问

    你提到的问题是 STM32F103ZET6 单片机在烧录程序后运行时“跑飞”,并且无论使用标准库、HAL库还是寄存器方式都一样。这种问题通常与 程序启动机制、Flash配置、系统时钟、堆栈指针(SP)设置或硬件连接 有关。


    ✅ 一、问题分析

    根据你的描述:

    • 程序烧录成功;
    • 运行时 PC寄存器跑飞到固定地址(如0x00000000 或 0x00000004)
    • 使用 ST-Link烧录时Boot0=0,Boot1=0(即从Flash启动);
    • 设置 Boot0=1(从系统存储器启动),通过串口烧录并选择“编译后执行”,可以正常运行;
    • 复位或上电后又会跑飞

    这说明:

    • 程序没有正确写入Flash
    • 或者 Flash被擦除/覆盖
    • 或者 系统时钟未正确初始化
    • 或者 堆栈指针(SP)未正确设置
    • 或者 芯片存在硬件问题(如Flash损坏、电源不稳定等)。

    ✅ 二、可能原因及解决方案

    1. Flash 写入失败或未正确烧录

    • 原因:虽然看起来烧录成功,但实际 Flash 中的代码未被正确写入。
    • 解决方法
      • 检查烧录工具(如 ST-Link Utility、Keil、IAR)是否配置为 正确的芯片型号和Flash大小
      • 使用 ST-Link Utility 的 "Read Memory" 功能 验证 Flash 内容是否与你烧录的文件一致。
      • 如果发现内容不一致,尝试重新烧录。

    加粗重点:确保烧录工具与芯片匹配,并且 Flash 写入操作完成无误


    2. 系统时钟初始化错误

    • 原因:如果系统时钟未正确配置,可能导致程序运行异常。
    • 解决方法
      • main() 开始处添加调试打印(如使用 USART)确认是否进入 main()
      • 如果无法进入 main(),说明 程序入口点错误
      • 检查 SystemInit() 是否被调用,尤其是对于 STM32F1 系列,SystemInit() 是必须的。
    // 示例:在 main 函数开始处添加调试输出
    #include "stm32f103x6.h"
    #include "stdio.h"
    
    void SystemClock_Config(void);
    void Error_Handler(void);
    
    int main(void) {
        HAL_Init();
        SystemClock_Config();
        MX_GPIO_Init();
        MX_USART2_UART_Init();
    
        printf("Program started...\n"); // 假设已实现printf
    
        while (1) {
            // 主循环
        }
    }
    

    加粗重点:确保 SystemClock_Config() 被调用,否则可能导致时钟异常导致程序跑飞。


    3. 堆栈指针(SP)未正确设置

    • 原因:如果 SP 指向了无效地址,程序将无法正常执行。
    • 解决方法
      • 检查 .s 文件中是否有如下代码(默认应为 0x20008000):
        .section .isr_vector
        .align 4
        .globl _estack
        .extern __main
        .type _estack, %object
    _estack:
        .word 0x20008000  @ Stack top
        .word Reset_Handler
        .word NMI_Handler
        ...
    
    • 如果你手动修改了堆栈地址,请确保其指向有效的内存区域。

    加粗重点:确保堆栈指针(SP)指向有效内存区域,否则程序无法正常启动。


    4. Flash 地址冲突或未正确映射

    • 原因:如果你的程序地址与 Bootloader 或其他固件冲突,可能导致程序无法运行。
    • 解决方法
      • 在 Keil 或 IAR 中检查 Memory Map,确认程序起始地址是否与 Flash 区域匹配。
      • 如果你使用的是 STM32F103ZET6,它的 Flash 容量为 512 KB,确保程序大小不超过该容量。

    加粗重点:确保程序大小不超过芯片 Flash 容量,并且起始地址正确。


    5. Boot0 和 Boot1 配置问题

    • 原因:虽然你设置 Boot0=0,Boot1=0,但某些情况下可能仍会进入系统存储器(System Memory)。
    • 解决方法
      • 尝试将 Boot0 设置为 1,Boot1 设置为 0,然后使用 System Memory Bootloader 通过串口烧录。
      • 确保在烧录完成后,将 Boot0 改回 0,以便从 Flash 启动。

    加粗重点:确保 Boot0 和 Boot1 的配置与你期望的启动方式一致。


    6. 电源或复位电路不稳定

    • 原因:电源波动或复位信号不稳定,可能导致程序在启动时跑飞。
    • 解决方法
      • 检查 VDD、VSS 是否稳定;
      • 检查 复位引脚(NRST)是否接有 10kΩ 上拉电阻
      • 确保 外部晶振(如 HSE)稳定工作

    加粗重点:确保电源和复位电路稳定,避免因硬件问题导致程序异常。


    ✅ 三、建议的调试步骤

    1. 使用 ST-Link Utility 读取 Flash 内容,验证是否与程序文件一致;
    2. 添加调试输出(如 USART)查看程序是否进入 main()
    3. 检查 SystemClock_Config() 是否被调用;
    4. 检查堆栈指针(SP)是否指向有效地址;
    5. 检查 Boot0 和 Boot1 配置是否正确;
    6. 检查电源和复位电路是否稳定;
    7. 尝试使用 STM32CubeIDESTM32CubeMX 生成工程,确保配置正确。

    ✅ 四、示例代码(SystemClock_Config)

    void SystemClock_Config(void) {
        RCC_DeInit();
        RCC_HSEConfig(RCC_HSE_ON);
        while (RCC_GetFlagStatus(RCC_FLAG_HSERDY) == RESET);
    
        RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_9); // 8MHz * 9 = 72MHz
        RCC_PLLCmd(ENABLE);
        while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET);
    
        RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
        while (RCC_GetSYSCLKSource() != 0x08);
    }
    

    加粗重点:确保 SystemClock_Config() 正确配置系统时钟。


    ✅ 五、总结

    | 问题类型 | 解决方案 | |----------|----------| | Flash 写入失败 | 检查烧录工具配置,验证 Flash 内容 | | 系统时钟未初始化 | 确保 SystemClock_Config() 被调用 | | 堆栈指针错误 | 检查 .s 文件中的 SP 地址 | | Boot0/Boot1 配置错误 | 确认启动方式与 Boot 引脚配置一致 | | 电源或复位不稳定 | 检查电源和复位电路 |


    如有更多具体错误信息(如报错、跑飞地址、代码片段等),欢迎继续提问,我可以进一步帮助你定位问题!

    评论

报告相同问题?

问题事件

  • 创建了问题 2月2日