Atilla
@Atilla

Как реализоать экономный delay на микроконтроллере?

Микроконтроллер stm32f4.

Допустим в ходе работы программы нужно прервать работу данного участка программы на некоторое время (допустим, пока другой микроконтроллер, с которым ты обмениваешься данными, перезапускается или обрабатывает данные). Можно конечно крутиться в цикле:
for ( ; i<time; i++ );
Но это значит что процессор кучу времени работает в холостую, а мог бы в это время что-нибудь считать. Если надо подождать немного, то не страшно. А если надо пару миллисекунд подождать? Как можно сделать так, чтобы ты вызывал некую функцию:
delay ( 100 );
Которая бы остановила работу функции в этой точке на 100 миллисекунд, во время которых процессор мог бы работать над другими рассчётами?
  • Вопрос задан
  • 4854 просмотра
Пригласить эксперта
Ответы на вопрос 3
Gereykhanov
@Gereykhanov
Инженер-разработчик
Только с помощью таймеров и системы прерываний, другого способа не вижу
Ответ написан
@Catethysis
Полностью согласен с @Gereykhanov, только на таймерах.
Берём таймер TIM6 (самый простой таймер с базовыми функциями - чтобы более крутые таймеры оставить свободными), настраиваем его:

// Включаем тактирование таймера
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM6, ENABLE); 

// Настраиваем прескалер. При тактовой частоте 24МГц частота
// таймера будет равна 24МГц/24000 = 1кГц
TIM6->PSC = 24000;

// Настраиваем период таймера = 1000 циклов - полный цикл таймера
// будет равен 1/1кГц*1000 = 1 секунда.
TIM6->ARR = 1000;

// Разрешаем прерывание по окончанию счёта
TIM6->DIER |= TIM_DIER_UIE;  

// Включаем обработку всех прерываний от таймера TIM6
NVIC_EnableIRQ(TIM6_DAC_IRQn);

// Включаем таймер
TIM6->CR1 |= TIM_CR1_CEN;

после срабатывания таймера будет вызван обработчик прерывания
void TIM6_DAC_IRQHandler(void)
{
  if (TIM6->SR & TIM_SR_UIF) {
    // Сбрасываем флаг прерывания
    TIM6->SR &= ~TIM_SR_UIF;

    /* ваш код после задержки*/
  }
}


Это не функция delay(100), это скорее демонстрация асинхронного алгоритма - но нужно понимать, что в сложных программах, особенно связанных с передачей и приёмом данных снаружи, практически всё нужно делать на прерываниях.
Во время работы таймера процессор полностью свободен, и может рассчитывать какую-то математику или обслуживать другие прерывания.
Довольно часто в моих программах для STM32 void main выглядит просто как while(1) {}, а вся логика работы находится именно в прерываниях. Кстати, здесь уже рукой подать до конечных автоматов.
Ответ написан
Комментировать
@komjaga
Программист встроенного ПО
Самое простое организовать свой диспетчер, типа такого

while(1)
{
Task1();
Task2();
Task3():
};

где Taks твои процессы, каждый процесс быстро выполняет и ничего не ждет

Taks1()
{
static step=0;

switch(step)
{
case 0: SendCommand(); step=1; break; //отсылаем команду
case 1: if(port) { Led=1; step=0; break; //ждем ответа
};

};

};
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы