Модераторы: PILOT, ManiaK, Mazzi
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> простая и надёжная организация временных задержек 
:(
    Опции темы
supercelt
Дата 23.6.2016, 17:58 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



Простите, если тема уже поднималась. Очень требуется решить вопрос.

Инициализирую LCD, в даташите оговорено, поставьте тут задержку 37 микросекунд, там 20 милисекунд и ещё вот тут 200 микросекунд. Реализацию задержки на милисекунды нашёл на систике. 

Код

static __IO uint32_t TimingDelay;


// Time dalay-----------------------------------------------------------------
void Delay_ms(__IO uint32_t nTime)

  TimingDelay = nTime;
  while(TimingDelay != 0);
}

void TimingDelay_Decrement(void)
{
  if (TimingDelay != 0x00)
  { 
    TimingDelay--;
  }
}

//Time delay handler interrupt systick
void SysTick_Handler(void)
{
  TimingDelay_Decrement();
}


Всё работает. Задерживает точно. А вот задержка на микросекунды - там мнения
расходятся. Кто-то говорит сделать на таймере, кто-то ещё на чём-то. Но неужели нет какого-нибудь очень простого и надёжного способа? Конечно если речь идёт о точности, то таймер скорее всего единственное решение. А если этот таймер, последний понадобится для другого? 
У меня мысль возникла, может сделать в цикле for, только вот как узнать сколько времени занимает 1 итерация цикла, что бы точно выставить число, до которого считать


PM   Вверх
Romikgy
Дата 23.6.2016, 19:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Любитель-программер
****


Профиль
Группа: Участник Клуба
Сообщений: 7326
Регистрация: 11.5.2005
Где: Porto Franco Odes sa

Репутация: 3
Всего: 146



все данные в даташите на проц.... а если время вывода не критично , все микросекунды замени задержкой в 1 мс


--------------------
Владение русской орфографией это как владение кунг-фу — истинные мастера не применяют его без надобности. 
smile

PM   Вверх
baldman88
Дата 24.6.2016, 08:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: 1
Всего: 7



Все зависит от используемого контроллера. Точнее от его частоты. Организация задержек с микросекундной длительностью с помощью SysTick возможна на контроллерах с частотой от 72 МГц. Все дело в том, что в таком случае используются прерывания. А на вход в прерывание нужно 14 тактов. Плюс декремент счетчика и выход из прерывания. В общем получаем около 20 тактов. Если контроллер работает на 24 МГц, то из 24 тактов в микросекунду, около 20 (возможно даже больше 24) будут уходить на обработку прерывания SysTick. А когда работать остальному коду? На 48 МГц на обработку прерывания будет уходить половина процессорного времени. А вот на 72 МГц уже можно себе это позволить.
Но перед тем, как делать микросекундные задержки нужно настроить SysTick. Я, обычно, делаю так:
Код
static __IO uint32_t TimingDelay;

void Delay_Init(void)
{
    SystemCoreClockUpdate();
    /* Set SysTick interrupts once in us */
    if (SysTick_Config(SystemCoreClock / 1000000))
    {
        while(1);
    }
    NVIC_SetPriority(SysTick_IRQn, 0x00);
}

void Delay_us(uint32_t delay)
{
    TimingDelay = delay;
    while (TimingDelay > 0);
}

void Delay_ms(uint32_t delay)
{
    TimingDelay = delay * 1000;
    while (TimingDelay > 0);
}

void SysTick_Handler(void)
{
    if (TimingDelay > 0)
    {
        TimingDelay--;
    }
}


Это сообщение отредактировал(а) baldman88 - 24.6.2016, 08:11
PM MAIL   Вверх
supercelt
Дата 24.6.2016, 20:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



У меня 24 мГц ((. Придётся делать 1 милисекундную задержку(
PM   Вверх
baldman88
Дата 24.6.2016, 22:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 210
Регистрация: 18.1.2009

Репутация: 1
Всего: 7



Если не нужна супер точность, то можно сделать проще. Каждая итерация (инкремент или декремент) цикла while занимает 4 такта. Поэтому можно сделать так (для 24 МГц -- 1 микросекунда = 24 такта, а так как итерация занимает 4 такта, то значение задержки нужно умножато на 6):
Код
void Delay_us(uint32_t delay)
{
    uint32_t counter = delay * 6;
    while (counter > 0)
    {
        counter--;
    }
}

Учитывая что еще будут затрачиваться такты на вход и выход из функции (около 10-ти тактов), а так же на расчет переменной counter, задержка будет, примерно, на пол микросекунды больше. Хотя можно это учесть отняв эти расходы от counter. Возьмем в сумме 12 тактов накладных расходов, тогда нужно будет отнять 3 (12 / 4 = 3). Получится как-то так:
Код
void Delay_us(uint32_t delay)
{
    uint32_t counter = delay * 6 - 3;
    while (counter > 0)
    {
        counter--;
    }
}

Сам не пробовал, но, по идее, должно получиться.

Это сообщение отредактировал(а) baldman88 - 24.6.2016, 22:11
PM MAIL   Вверх
Курсант
Дата 19.7.2016, 14:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 338
Регистрация: 21.2.2009
Где: Балашиха или Воро неж

Репутация: нет
Всего: 4



Здравствуйте!
Обычно я для таких целей использую метки времени и измерение временных интервалов между метками времени. Сейчас я использую 64-разрядные метки времени, которые не переполняются более 100 лет smile Если все временные интервалы будут небольшими, можно использовать и 32-разрядные метки времени. Нужно запустить таймер. Ещё нужна функция получения метки времени:
Код

uint32_t GetTimeStamp ( void ) {
return Timer1->Value;
}

После этого необходимы функции определения временных интервалов.
Код

uint32_t GetIntervalFrom ( uint32_t FromTimeStamp ) {
return ( GetTimeStamp () - FromTimeStamp );
}

uint32_t GetIntervalFromTo ( uint32_t FromTimeStamp, uint32_t ToTimeStamp ) {
return ( ToTimeStamp - FromTimeStamp );
}

uint32_t IsIntervalOverFrom ( uint32_t Interval, uint32_t FromTimeStamp ) {
return ( Interval < GetIntervalFrom ( FromTimeStamp ) );
}

uint32_t IsIntervalOverFromTo ( uint32_t Interval, uint32_t FromTimeStamp, uint32_t ToTimeStamp ) {
return ( Interval < GetIntervalFromTo ( FromTimeStamp, ToTimeStamp ) );
}


Теперь отсчёт требуемого интервала будет выглядеть так:
Код

void WaitForInterval ( uint32_t Interval ) {
uint32_t tmpTimeStamp = GetTimeStamp ();
while ( !IsIntervalOverFrom ( Interval, tmpTimeStamp ) );
}


Т.е. где-то у себя в коде можно записать так:
Код

int main ( void ) {
blah
blah
blah
WaitForInterval ( 1000 );   // Интервал в тиках таймера
blah
blah
blah
}


ИМХО. Пишу по памяти, без контрольной компиляции и на ходу улучшая когда-то работавший код. Ногами не пинайте если что.

Это сообщение отредактировал(а) Курсант - 19.7.2016, 14:17
PM ICQ Skype   Вверх
supercelt
Дата 19.7.2016, 15:20 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 658
Регистрация: 25.8.2005

Репутация: нет
Всего: 1



Спасибо! Это очень интересный вариант.
PM   Вверх
Crystaly
Дата 18.5.2018, 09:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 3
Регистрация: 2.12.2015

Репутация: нет
Всего: нет



Цитата(supercelt @ 23.6.2016,  17:58)
Простите, если тема уже поднималась. Очень требуется решить вопрос.

Инициализирую LCD, в даташите оговорено, поставьте тут задержку 37 микросекунд, там 20 милисекунд и ещё вот тут 200 микросекунд. Реализацию задержки на милисекунды нашёл на систике. 


Эти микросекунды, которые вы указываете, скорее всего МИНИМАЛЬНЫЕ значения задержек. Реально можно больше. Программно делать такие задержки (имхо) бред. (но не все делается программно, есть еще направление аппаратных разработок ПЛИС и т.п. вот там это важно соблюдать)


Это сообщение отредактировал(а) Crystaly - 18.5.2018, 09:57
PM MAIL   Вверх
Queenswu666
Дата 15.9.2020, 10:06 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 1
Регистрация: 15.9.2020

Репутация: нет
Всего: нет




Модератор: Сообщение скрыто.

PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Микроконтроллеры (MCU) и микропроцессоры (MPU)"
PILOT ManiaK
UniBomb Mazzi

На данный раздел помимо Правил форума распространяются текже следующие правила:


  • Прежде чем создать тему воспользуйтесь поиском или посмотрите в faq. Возможно на форуме уже есть ответ на ваш или близкий к вашему вопрос.
  • В заголовке темы в квадратных скобках обозначьте используемое семейство микроконтроллера: [avr],[pic],[arm].
  • При создании темы с вопросом указывайте участок кода с ошибкой, версию компилятора, схемы подключения, fuse биты и прочие данные, которые помогут найти правильный ответ. Для форматирования текста программ используйте кнопку код.
  • Новое сообщение должно иметь прямое отношение к тематике этого раздела. Для флуда, просьб выполнить задание, поиска партнёров или исполнителей существуют свои разделы.
  • Если вы заметили несовместимое с правилами сообщение, то можете уведомить об этом модератора раздела нажав кнопку Репорт у соответствующего сообщения.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, PILOT, ManiaK, UniBomb, Mazzi.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Микроконтроллеры (MCU) и микропроцессоры (MPU) | Следующая тема »


 




[ Время генерации скрипта: 0.1415 ]   [ Использовано запросов: 20 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.