Проблема AVR застряла и программный счетчик потерян - PullRequest
0 голосов
/ 05 сентября 2018

Я столкнулся со странным поведением, я работаю над проектом с использованием MCEL ATMEL (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);

} 

Но через некоторое время вся программа зависла, и даже после полного сброса, чтобы снова работать, я должен отключить и снова включить питание.

Примечания: - - Я уверен, что hard reset работает - Я использую таймеры в фоновом режиме как системный тик.

Ответы [ 2 ]

0 голосов
/ 07 сентября 2018

Спасибо за поддержку Я обнаружил проблемы, потому что таймер сторожевого таймера удерживает MCU в режиме перезапуска, даже когда я нажимаю на аппаратный перерыв. это потому, что я рассматривал все регистры, возвращаясь к его значению по умолчанию после отдыха. Блок-схема WDT

я делал это в коде, когда 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 произошел и остановил программу, процессор обнаружил, что установлен флаг 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
........
}

это то, что написано в листе данных

Примечание: если сторожевой таймер случайно включен, например, с помощью указателя убегания или Выключение, устройство будет сброшено, а сторожевой таймер останется включенным. Если код не настроен для обработки Watchdog, это может привести к вечному циклу сброса тайм-аута. Чтобы избежать этой ситуации, прикладное программное обеспечение должно всегда очищать Флаг сброса сторожевой системы (WDRF) и управляющий бит WDE при инициализации рутина, даже если сторожевой таймер не используется.

0 голосов
/ 05 сентября 2018

код небезопасен; вы ничего не делаете для предотвращения переполнения буфера.

Считай, что безопаснее и проще:

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 обнуляется.

...