Перейти к содержанию

Как програмно вызвать прерывание RESET?


Гость химик

Рекомендуемые сообщения

Нужен полный сброс.

 

А если так:


interrupt [TIM0_OVF] void timer0_ovf_isr(void){         

  бла, бла, бла;

 if (   ){      
   Функция А();                            
    }else{                                              
      TCCR0=0x00;                                       
      TCNT0=0x00; 
      };
}

void Функция А(void){
   
  SREG = SREG ^ 0b10000000;

  бла, бла, бла;
  
}

 

Мне нужно при переходе в функцию А, окончить прерывание чтобы запустилось другое в функции А. Либо заменить Функция А(); операцией reset.

 

А в каком окружении работает контроллер? Что у него на выходах? Чем он рулит?

Ссылка на комментарий
Поделиться на другие сайты

А в каком окружении работает контроллер? Что у него на выходах? Чем он рулит?

Контроллер управляет группой реле. Перезапуск мне нужен вот для чего:

нажимаем кнопку, таймер считает несколько секунд (если кнопку отпустили раньше, то условие не выполняется), после он должен выполнить подпрограмму, которая используется в main(), перед whail{}. Но пока не закончилось действующее прерывание, то функция подпрограммы виснет - в ней используется другое прерывание.

Понятно ли я объяснил? :smile:

Ссылка на комментарий
Поделиться на другие сайты

А если так:


interrupt [TIM0_OVF] void timer0_ovf_isr(void){         

  бла, бла, бла;

 if (   ){      
   Функция А();                            
    }else{                                              
      TCCR0=0x00;                                       
      TCNT0=0x00; 
      };
}

void Функция А(void){
   
  SREG = SREG ^ 0b10000000;

  бла, бла, бла;
  
}

 

Ну так в этом случае ведь после того, как выполнится функция А опять произойдет возврат в обработчик TIM0_OVF, затем выход из него и возврат неизвестно куда.

Поясните этот момент:

Но пока не закончилось действующее прерывание, то функция подпрограммы виснет - в ней используется другое прерывание.

И вообще, Вы бы лучше написали что нужно в итоге получить, как-нибудь в более широком смысле, что ли, без привязки к конкретным функциям/прерываниям/циклам. Вероятно, можно все это сделать как-нибудь попроще.

 

Если все же делать псевдо-reset, то очистку регистров и sram можно сделать так, к примеру:

uint8_t *ptr = (uint8_t*)0x0000;
while (ptr <= 0x045F) { // 0x045F - the end of internal sram 
*ptr = 0x00;
ptr++;
};

Не уверен, что есть необходимость обнулять РОН, если не надо, то начинать следует с адреса 0x0020.

Изменено пользователем alexakaohm
Ссылка на комментарий
Поделиться на другие сайты

Если все же делать псевдо-reset, то очистку регистров и sram можно сделать так, к примеру:

uint8_t *ptr = (uint8_t*)0x0000;
while (ptr <= 0x045F) { // 0x045F - the end of internal sram 
*ptr = 0x00;
ptr++;
};

Не уверен, что есть необходимость обнулять РОН, если не надо, то начинать следует с адреса 0x0020.

Если я вставлю этот код в обработчик прерываний, то после условия while () я уже не вернусь обратно в обработчик?

Я же писал выше, что мне нужно при определенном условии в обработчике прерываний окончить это самое прерывание посередине , пока оно не завершилось, и перейти в main().

Ссылка на комментарий
Поделиться на другие сайты

Компилятор ругается на необозначенные символы uint8_t и ptr. Обозначил их как int, теперь ругается так:

the expression must be a modifiable lvalue;

operand of '*' must be a pointer

 

Может надо какую библиотеку подключить?

Изменено пользователем химик
Ссылка на комментарий
Поделиться на другие сайты

Если я вставлю этот код в обработчик прерываний, то после условия while () я уже не вернусь обратно в обработчик?

Вернетесь. Этот кусок надо вставлять в самое начало функции main. А переход в неё делать(из обработчика прерывания), например, используя ассемблерную вставку. Хотя, наверное, лучше переходить по адресу вектора сброса

Кроме того, надо учитывать, что глобальные переменные инициализируются до функции main, поэтому, если произойдет переход из обработчика прерывания в начало main(а не на 0x0000), то инициализация этих переменных(если таковые имеются) не будет выполнена. Решить эту проблему можно, если производить инициализацию(т.е. определение, а не объявление; к примеру "var = 0xFA;") глобальных переменных "вручную", как раз в начале main.

Компилятор ругается на необозначенные символы uint8_t и ptr.

Напишите unsigned char вместо uint8_t. "uint8_t" этот тот же тип данных, определен в stdint.h

А "ptr" ведь объявлен, все должно быть нормально.

Я же писал выше, что мне нужно при определенном условии в обработчике прерываний окончить это самое прерывание посередине , пока оно не завершилось, и перейти в main().

Нужно еще не забыть переинициализировать указатель стека, если переход осуществляется в main.

 

В общем, на мой взгляд, самое лучшее решение - тупо переход на вектор сброса используя команду jmp, с применением inline-ассемблера.

Тогда, по идее, будет корректно выполнена инициализация глобальных переменных и указателя стека. Очистку же SRAM и РОН выполнить, используя написанный выше пример.

Изменено пользователем alexakaohm
Ссылка на комментарий
Поделиться на другие сайты

Теперь понял.

Вобщем получилось освободить одну лапу, сделал как писал сергей, подал с этой лапки единицу на reset и в нужный момент подаю ноль. Всем спасибо за помощь. :smile:

Ссылка на комментарий
Поделиться на другие сайты

Гость
Эта тема закрыта для публикации ответов.
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...