问题AVR卡住了,程序计数器丢失了...?

时间:2018-09-05 06:19:48

标签: rest stack embedded avr pc

我正面临一个奇怪的行为,我正在使用带有大量字符串的ATMEL MCU(ATMEGA328p)进行项目开发,因此我将其存储在闪存中,并且在运行时我从闪存中读取并通过UART发送。 我不知道这是否是问题,因为我之前在其他项目中使用的是相同的技术,但是这里的字符串数量比以前大了。

void PLL_void_UART_SendSrting_F(U8_t* RXBuffer,const char * str , U8_t UART_No)
{
    unsigned int _indx=0;
    memset(RXBuffer,'\0', A9G_RX_Index);    // Initialize the string
    RXBuffer[A9G_RX_Index-1]='\0';

    //  cli();
    while((RXBuffer[_indx]=pgm_read_byte(&(*str))))
    {
        str++;
        _indx++;
        _delay_ms(5);
    }
    //  sei();
    PLL_void_UART_SendSrting(RXBuffer,0);

} 

但是过了一会儿,整个程序陷于瘫痪,甚至在进行了硬重置之后,要再次工作,我也应拔出电源并重新插入电源。

注意:- -我确信硬重置工作正常 -我在后台使用计时器作为系统时钟。

2 个答案:

答案 0 :(得分:0)

感谢您的支持 我发现了问题,这是因为看门狗定时器即使按了硬件支架也使MCU处于重启模式。这是因为,我正在考虑所有寄存器,休息后标志恢复为默认值。WDT Block Digram

当MCU开始执行这样的代码时,我正在用代码进行操作:

U8_t PLL_U8_System_Init()
{
static U8_t SetFalg=0;

PLL_void_TimerInit();                               // General Timer Initialize                         
PLL_WDT_Init();                                     // Initialize WDT and clear  WDRF 
wdt_enable(WDTO_8S);                                // Enable WDT Each 2 S
........
}

但是一旦发生WDT并停止程序,CPU就会发现WDRF标志已设置,因此自从我进行了电源休息后,它将一直保持静止状态。

解决方案 我必须在程序首次启动后清除WDT计时器,然后再执行任何代码及其工作

U8_t PLL_U8_System_Init()
{
static U8_t SetFalg=0;

PLL_void_TimerInit();                               // General Timer Initialize                         
PLL_WDT_Init();                                     // Initialize WDT and clear WDRF   
wdt_enable(WDTO_8S);                                // Enable WDT Each 2 S
........
}

这就是数据表中所写的内容

注意:如果看门狗被意外启用,例如通过失控指针或 掉电情况下,器件将被复位并且看门狗定时器将保持使能状态​​。如果 代码未设置为处理看门狗,这可能会导致超时重置的永恒循环。为避免这种情况,应用程序软件应始终清除 看门狗系统复位标志(WDRF)和初始化中的WDE控制位 即使不使用看门狗也是如此。

答案 1 :(得分:-1)

代码不安全;您什么也不做,以防止缓冲区溢出。

考虑更安全,更简单:

void PLL_void_UART_SendString_F( U8_t* RXBuffer, const char* str, U8_t UART_No )
{
    unsigned index = 0 ;
    RXBuffer[A9G_RX_Index - 1] = '\0' ;

    while( index < A9G_RX_Index - 1 && 
           0 != (RXBuffer[index] = pgm_read_byte( &str[index] )) )
    {
        index++ ;
    }

    PLL_void_UART_SendSrting( RXBuffer, 0 ) ;
} 

即使那样,您也必须确保RXBuffer的大小合适并且str被终止。

相关问题