stm32f4 cmsis delay как сделать задержку для lcd

Кто любит RISC в жизни, заходим, не стесняемся.
Ответить
Мучитель микросхем
Сообщения: 440
Зарегистрирован: Вс дек 29, 2019 08:05:21

Сообщение ivan dimir »

Кто подскажет как правильно написать задержку для LCD
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

На конечных автоматах, например.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Реклама
Мучитель микросхем
Сообщения: 440
Зарегистрирован: Вс дек 29, 2019 08:05:21

Сообщение ivan dimir »

а программно?
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

тупо - "пустым" циклом

Код: Выделить всё

volatile int delay = 123;
while(delay) delay--;
менее тупо - на основе аппаратного или программного счетчика "системных тиков".
а совсем правильно (имхо, не утверждаю, что для всех LCD приемлемо) - на основе считывания регистра состояния LCD, т.е. работа не по задержке, а по готовности дисплея.
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Реклама
Эиком - электронные компоненты и радиодетали
Мучитель микросхем
Сообщения: 440
Зарегистрирован: Вс дек 29, 2019 08:05:21

Сообщение ivan dimir »

Чтоб соотвецвовало мили миикросекундам?
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2516
Зарегистрирован: Пт июл 12, 2019 22:52:01

Сообщение Eddy_Em »

[uquote="ivan dimir",url="/forum/viewtopic.php?p=3871875#p3871875"]а программно?[/uquote]
А что КА — железо?
Миллисекундные задержки очень удобно делать на КА: заводим внутренний счетчик и сравниваем на каждом прогоне с SysTick, который системные миллисекунды считает. Вряд ли у вас один прогон "суперлупа" будет длиться больше 1мс, поэтому получаем точность не хуже 1мс.
А вот микросекунды зачастую прямо на месте и отсчитывают — при помощи вспомогательного таймера или тупыми nop'ами в цикле (правда, в этом случае точность будет паршивой). Обычно такие паузы нужны лишь на инициализации, которая все равно в начале проходит и можно считать, что пользователю пофиг, что в течение пяти секунд устройство вообще ни на что не реагирует..

Но, как уже написали, лучший вариант — читать регистры и принимать решение на основе этого.
Или вернуться к конечным автоматам: экранчикам не нужно точных пауз, достаточно (если нет регистра состояний) выдержать определенную. Вот и проходимся по массиву инициализации плавно: дошли до паузы, внутренний счетчик в нужное значение выставили, и ждем. Потом следующий кусок отправляем. И так далее. При этом нет блокирующих пауз, и железяка вовсю будет работать, пока инициализируется экран.
Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда.
Я на гитхабе, в ЖЖ
Контактная информация:
Реклама
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 35
Зарегистрирован: Чт май 14, 2015 16:58:00
Откуда: Kharkiv

Сообщение lizard66 »

Делаю через DWT

Код: Выделить всё

void DelayMs(uint32_t nTime)
{
	volatile uint32_t CounterTick = nTime * (SystemCoreClock / 1000);

	SCB_DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;		//разрешаем использовать счётчик
		DWT_CYCCNT  = 0;							//обнуляем значение счётного регистра
		DWT_CONTROL |= DWT_CTRL_CYCCNTENA_Msk;		//запускаем счётчик
		while(DWT_CYCCNT < CounterTick);
		DWT_CONTROL &= ~DWT_CTRL_CYCCNTENA_Msk;		//останавливаем счётчик
}
Мучитель микросхем
Сообщения: 440
Зарегистрирован: Вс дек 29, 2019 08:05:21

Сообщение ivan dimir »

В реферес мануал его нет где прочитать про него?DWT
Электрический кот
Аватара пользователя
Сообщения: 1029
Зарегистрирован: Сб мар 09, 2013 11:29:22
Откуда: 40RUS, Жуков

Сообщение 240265 »

IVL ex UA6PJ
Первый раз сказал Мяу!
Аватара пользователя
Сообщения: 35
Зарегистрирован: Чт май 14, 2015 16:58:00
Откуда: Kharkiv

Сообщение lizard66 »

сорри, забыл добавить дефайны:

Код: Выделить всё

#define    DWT_CYCCNT    *(volatile unsigned long *)0xE0001004
#define    DWT_CONTROL   *(volatile unsigned long *)0xE0001000
#define    SCB_DEMCR     *(volatile unsigned long *)0xE000EDFC
Мучитель микросхем
Сообщения: 440
Зарегистрирован: Вс дек 29, 2019 08:05:21

Сообщение ivan dimir »

а на базовом таймере как єто сделать?
Открыл глаза
Сообщения: 41
Зарегистрирован: Вс мар 21, 2021 11:06:04

Сообщение Professor Chaos »

[uquote="ivan dimir",url="/forum/viewtopic.php?p=4013156#p4013156"]а на базовом таймере как єто сделать?[/uquote]
Обычно это делается на любом свободном аппаратном таймере методом вычитывания и обработки значения его счетного регистра. Без использования прерываний. Подробнее про реализацию можно прочитать тут. Максимальный интервал времени для такого таймера определяется периодом перезагрузки его счетного регистра.
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18783
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

Professor Chaos писал(а):Подробнее про реализацию можно прочитать тут.
облагороженная версия ардуиновского millis() и ардуиновского же подхода...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

1 вариант:
Спойлер

Код: Выделить всё

void Delay(uint32_t ms)
{
        volatile uint32_t nCount;
        RCC_ClocksTypeDef RCC_Clocks;
        RCC_GetClocksFreq (&RCC_Clocks);
        nCount=(RCC_Clocks.HCLK_Frequency/10000)*ms;	
        for (; nCount!=0; nCount--);
}
2 вариант:
Спойлерверсия ардуиновского millis()

Код: Выделить всё

// Конфигурируем и запуск системного таймера
// для генерации каждую 1 мс.

SysTick->LOAD = 48000000UL/1000 - 1; // Загрузка значения в 1 ms
SysTick->VAL = 48000000UL/1000 - 1; // Устанавливаем текущее значение
SysTick->CTRL = SysTick_CTRL_CLKSOURCE_Msk | SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk;


volatile uint32_t currentMillis = 0;
//Обработчик прерывания системного таймера
void SysTick_Handler(void)
{
	currentMillis++;
}


uint32_t millis (void)
{
	return currentMillis;
}


uint32_t previousMillis = 0;
if((millis() - previousMillis) > 500){
	previousMillis = millis();
	//делаем что-то
}
Открыл глаза
Сообщения: 41
Зарегистрирован: Вс мар 21, 2021 11:06:04

Сообщение Professor Chaos »

Dimon456 писал(а):nCount=(RCC_Clocks.HCLK_Frequency/10000)*ms;   
        for (; nCount!=0; nCount--);
Вы строите этот код исходя из предположения, что одна итерация цикла for будет исполняться строго за 1 период тактовой частоты ядра? А если это не так? А это, в общем случае не так, и зависит от настроек оптимизации - тогда что?

Во втором варианте не учитывается событие переполнения счетчика: пусть последнее предыдущее значение 0хFFFFFFFF, текущее прочитанное 0. Сколько прошло времени? А что покажет условие?
Мудрый кот
Сообщения: 1849
Зарегистрирован: Вс дек 25, 2016 08:34:54

Сообщение Dimon456 »

Professor Chaos писал(а):Вы строите этот код исходя из предположения,
А вот мне "на.... с глубокой горки", главное работает и ладно, просто из вас ни кто ни чего не предложил, кроме слов конечно.

Делаю так:
Спойлер-Os

Код: Выделить всё

    while(1)
    {
		GPIOA->ODR |= GPIO_Pin_2;
		Delay(100); // Delay(1); Delay(10);
		GPIOA->ODR &= ~GPIO_Pin_2;	
	}
и вот это строчку

Код: Выделить всё

RCC_Clocks.HCLK_Frequency/10000
добиваю или убираю нулями.
А смотреть по осциллографу, или частотомеру
Professor Chaos писал(а):Во втором варианте не учитывается событие переполнения счетчика
Да плевать и на это
Спойлер

Код: Выделить всё

	if((millis() - previousMillis) > 500){
		previousMillis = millis();
		blink = !blink;
	}

	LCDI2C_setCursor (10,0);
	if (blink) LCDI2C_write(0x22); else LCDI2C_write(0x20);
А событие переполнения у вас произойдет где-то через 4294967295/1000/3600/24 = 49 дней.

Не нравится, делайте на конечных автоматах, там все учитывается, да же размер кода.
Мучитель микросхем
Сообщения: 440
Зарегистрирован: Вс дек 29, 2019 08:05:21

Сообщение ivan dimir »

а как сделать задержку таймером базовым?
Открыл глаза
Сообщения: 41
Зарегистрирован: Вс мар 21, 2021 11:06:04

Сообщение Professor Chaos »

[uquote="ivan dimir",url="/forum/viewtopic.php?p=4016305#p4016305"]а как сделать задержку таймером базовым?[/uquote]
Что такое базовый таймер? Вы, вообще, какой МК имеете ввиду? У ARM много разных ядер, и куча производителей используют их в своих контроллерах/процессорах. И понятие базового таймера везде разное. В ядре есть системный таймер. Другие таймеры каждый производитель реализует как хочет в качестве периферийных устройств.
Мучитель микросхем
Сообщения: 446
Зарегистрирован: Вс ноя 01, 2015 09:15:16
Откуда: 69.Ржев

Сообщение a797945 »

есть еще варианты как слова в вопросе переставить :)
или такой ответ сойдет:

Код: Выделить всё

TIM3->PSC = 56-1;		// предварительная
TIM3->ARR = 10-1;		// подготовка
TIM3->EGR = TIM_EGR_UG; // таймера
...
TIM3->CR1 = TIM_CR1_CEN|TIM_CR1_OPM;		// старт таймера
...
if (!(TIM3->CR1&TIM_CR1_CEN)) {...;}		// проверка с выполнением, если оттикал
или заLoopить на тупой опрос бита:
while(TIM3->CR1&TIM_CR1_CEN){};				// висеть если еще тикает
:write:
Мучитель микросхем
Сообщения: 440
Зарегистрирован: Вс дек 29, 2019 08:05:21

Сообщение ivan dimir »

TIM3->CR1 = TIM_CR1_CEN|TIM_CR1_OPM; и будет один импулс.Этот бит _OPM; один импулс
Ответить

Вернуться в «ARM»