You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AVR ATmega328P程序执行中断后频繁重启问题求助

ATmega328P程序在Proteus中频繁重启问题排查

问题描述

我为AVR ATmega328P编写了C程序,正在Proteus 8环境中调试。程序执行完中断后无法进入main函数的无限循环,反而从初始化段重启;该问题并非每次出现,但发生频率较高。希望程序完成初始化后能稳定进入main的无限循环,恳请指出可能的问题及排查方向。

程序代码

#include <avr/io.h>
#include <avr/interrupt.h>
#include <util/delay.h>
#include <stdbool.h>
#include <string.h>
#include "lic328p_gpio.h"
#include "lic_menuio.h"
#include "battery.h"
#include "lic_18650h.h"
#include "lic_uart.h"
#include "lic_adc.h"

static volatile tx_data tx_package;
static volatile adc_channel channel;
static volatile batlist batstat;

ISR(ADC_vect)
{
  uint16_t data = adc();
  batt_data_handling(data, &batstat);
  fill_tx_package(&batstat, &tx_package);
  UCSR0B |= (1 << UDRIE0);      
}

ISR(USART_RX_vect)
{
  // Selecting the Menu Mode
  setMode(&menu, UDR0);
}

ISR(USART_UDRE_vect)
{
    if(tx_package.index < tx_package.length) {
        UDR0 = tx_package.data[tx_package.index];
        tx_package.index++;
    } else {
        tx_package.inprocess = false;
        UCSR0B &= ~(1 << UDRIE0);
    };
}

ISR(USART_TX_vect) {

}

int main(void)
{
  port_init();
  uart_init(MYUBRR);
  timer_init();
  adc_init();

  init_adcChan(&channel);
  init_battData(&batstat);
  init_tx_data(&tx_package);

  sei();

  while(1) {
  };

  return 0;
}

仿真截图

Proteus仿真截图

可能的问题及排查方向

  • 栈溢出:中断服务函数(ISR)中调用了batt_data_handling、fill_tx_package这类复杂函数,或全局/静态变量占用过多栈空间,都可能导致栈溢出触发复位。

    • 检查tx_data、batlist等结构体的大小,避免过大的栈分配
    • 简化ISR内的操作,将复杂逻辑移至main循环处理
    • 通过编译器开启栈大小警告,或调试时观察栈指针(SP寄存器)的变化
  • 中断触发时机与非法操作:sei()开启中断后,可能在main进入循环前就触发ADC/UART中断,若中断内存在未初始化指针访问、数组越界等操作,会导致复位。

    • 调整初始化顺序:将sei()移至所有init函数之后,确保tx_package、batstat等变量完全初始化
    • 检查ISR内的数组访问:确认tx_package.length已正确初始化,避免tx_package.data[tx_package.index]越界
    • 逐一关闭中断(比如先禁用ADC中断),排查是哪个中断引发的重启
  • Proteus仿真环境异常:仿真模型bug、电源/时钟配置错误都可能导致异常复位。

    • 检查仿真电路的电源电压是否稳定(ATmega328P需5V或3.3V稳定供电)
    • 确认程序时钟设置与Proteus中单片机的时钟配置一致(如外部晶振频率、预分频器)
    • 尝试在真实硬件上测试,排除仿真环境问题
  • 看门狗误触发:若代码中意外开启看门狗,且main循环或中断处理耗时超过超时时间,会触发复位。

    • 检查初始化函数或头文件,确认未误开启看门狗
    • 若需使用看门狗,在main循环中添加喂狗操作
  • 复位原因排查:读取单片机的复位状态寄存器(MCUSR),可判断复位类型(上电复位、欠压复位、看门狗复位等),缩小排查范围。

内容的提问来源于stack exchange,提问作者vpos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:04:58