реклама на сайте
подробности

 
 
3 страниц V  < 1 2 3  
Reply to this topicStart new topic
> STM32. Функция задержки, программные задержки на таймере
ViKo
сообщение Dec 28 2012, 06:26
Сообщение #31


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Хочу продолжить. Написать универсальную задержку, которая равна
DELAY = (PSC + 1) * (ARR + 1) / FCK_PSC
где
DELAY - задержка в секундах
PSC - значение прескалера, 0 - 65535
ARR - значение регистра автозагрузки, 0 - 65535
FCK_PSC - частота, поступающая на вход прескалера, в герцах
Как бы придумать с помощью #define разложить отношение DELAY * FCK_PSC на множители, чтобы получить точное значение?
Жаль, в препроцессоре невозможны циклы.
Go to the top of the page
 
+Quote Post
NaughtyFreak
сообщение Dec 28 2012, 08:17
Сообщение #32


Частый гость
**

Группа: Участник
Сообщений: 90
Регистрация: 7-10-11
Из: Москва
Пользователь №: 67 593



Очень наворочено blush.gif

Почему правда для задержки не использовать SysTick?
У меня есть вполне простенькая ф-ия для работы с задержками, там и миллисекунды и микросекунды получаюццо:

CODE
typedef unsigned long int DWORD; //max 4 294 967 295 delay units
#define mS_TICK 168000 // @ core FREQ = 168 MHz
#define uS_TICK 168 // @ core FREQ = 168 MHz

DWORD DelayTime; //global tick variable

void SysTick_Configure_ms (void)
{
SysTick_Config(mS_TICK); // interrupt 1 ms
}

void SysTick_Configure_us (void)
{
SysTick_Config(uS_TICK); // interrupt 1 us
}

void Delay_ms(DWORD time)
{
DelayTime=time;
while (DelayTime!=0){};
}

void Delay_us(DWORD time)
{
DelayTime=time;
while (DelayTime!=0){};
}

void DelayTime_Decrement (void)
{
if (DelayTime!=0)
{
DelayTime--;
}
}

void SysTick_Handler(void)
{
DelayTime_Decrement();
}


И усё. в зависимости от надобности кофигурируете в проге чтобы таймер тикал на мс или мкс пишете сколько отсчитывать. Работает 100%, проверено.

Сообщение отредактировал IgorKossak - Dec 28 2012, 08:18
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 28 2012, 09:10
Сообщение #33


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(NaughtyFreak @ Dec 28 2012, 11:17) *
Очень наворочено blush.gif
Почему правда для задержки не использовать SysTick?
И усё. в зависимости от надобности кофигурируете в проге чтобы таймер тикал на мс или мкс пишете сколько отсчитывать. Работает 100%, проверено.

На SysTick у меня тоже есть задержка. Но его лучше оставить для RTOS.
Вопрос скорее учебный, чем практический. Зарядка для ума.
Навороченного в задержке на таймере ничего нет.
Всплывает в сознании термин "рекурсия".
Go to the top of the page
 
+Quote Post
ViKo
сообщение Dec 28 2012, 14:07
Сообщение #34


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Типа такого, но на препроцессоре. rolleyes.gif
CODE
#define FT_MHZ 24
void delay_start(const uint32_t time) {
uint32_t psc, rst, arr;
for (psc = 1; psc < 0x10000; psc++) {
arr = time * FT_MHZ / psc;
rst = time * FT_MHZ % psc;
if ((arr < 0x10000) && (rst == 0)) {
TIM6->PSC = psc - 1;
TIM6->ARR = arr - 1;
TIM6->EGR = TIM_EGR_UG;
TIM6->SR = 0;
TIM6->CR1 |= TIM_CR1_CEN;
return;
}
}
for (psc = 1; psc < 0x10000; psc++) {
arr = (time * FT_MHZ + psc / 2) / psc;
if (arr < 0x10000) {
TIM6->PSC = psc - 1;
TIM6->ARR = arr - 1;
TIM6->EGR = TIM_EGR_UG;
TIM6->SR = 0;
TIM6->CR1 |= TIM_CR1_CEN;
return;
}
}
}

void delay_wait(void) {
while (!TIM6->SR);
}
Go to the top of the page
 
+Quote Post
polyname
сообщение Dec 28 2012, 17:44
Сообщение #35


Частый гость
**

Группа: Участник
Сообщений: 147
Регистрация: 18-05-12
Пользователь №: 71 915



Цитата
И усё. в зависимости от надобности кофигурируете в проге чтобы таймер тикал на мс или мкс
прерывание с частотой 1МГц и программный поллинг DelayTime ? Вы случайно не индус ?
И почему вы уверены что доступ к DelayTime атомарный ?

Сообщение отредактировал polyname - Dec 28 2012, 17:46
Go to the top of the page
 
+Quote Post
sidy
сообщение Mar 8 2013, 19:12
Сообщение #36


Местный
***

Группа: Участник
Сообщений: 280
Регистрация: 2-11-08
Пользователь №: 41 333



Поскольку в данной теме много разбирающихся в нюансах таймеров STM32, задам вопрос. Имеется MCU STM32F415. Если при достижении таймером TIM1 переполнения я хочу сбросить таймер TIM4 достаточно ли только записать TIM4->CNT=0? Или же если мне нужно не сбросить а продолжить счет TIM4 с определенного значения Х могу ли я записать TIM4->CNT=X?
Go to the top of the page
 
+Quote Post
Mimik
сообщение Jun 10 2014, 11:08
Сообщение #37





Группа: Новичок
Сообщений: 1
Регистрация: 10-06-14
Пользователь №: 81 922



Всем привет, прошу вашей помощи. Устроился на новую работу, и попался мне на переделку вот такой код :
CODE
class FreqIn
{
static std::vector<FreqIn*>tims;
static int timsNum;

public:
FreqIn(TIM_TypeDef *tim_, IRQn irqnUP_, IRQn irqnCC_, uint16_t chan_, uint32_t busDiv_)
: tim(tim_)
, irqnUP(irqnUP_)
, irqnCC(irqnCC_)
, chan(chan_)
, busDiv(busDiv_)
{
prescaler = 0;
tims.push_back(this);
timsNum ++;
reset();
}

void start()
{
stop();
enable = 1;
}
void stop()
{
enable = 0;
}
void reset()
{
timerInit();
stop();
}

inline float freq() {return freq_;}
inline uint16_t holdEdge() {return holdEdge_;}
inline void setEdge(uint16_t t)
{
timerInit();
holdEdge_ = t;
}
inline uint16_t holdPrescaler() {return prescaler;}
inline void setPrescaler(uint16_t t)
{
//timerInit();
prescaler = t;
}

private:
void timerInit()
{
NVIC_DisableIRQ(irqnUP);
NVIC_DisableIRQ(irqnCC);
TIM_Cmd(tim, DISABLE);

TIM_TimeBaseInitTypeDef timer_base;
TIM_TimeBaseStructInit(&timer_base);
timer_base.TIM_Prescaler = prescaler-1; //1,2,3
timer_base.TIM_Period = 0xFFFF;
TIM_TimeBaseInit(tim, &timer_base);

TIM_ICInitTypeDef TIM_ICStructure;
TIM_ICStructure.TIM_Channel = chan; // канал
if (holdEdge_)
{
TIM_ICStructure.TIM_ICPolarity = TIM_ICPolarity_Falling; // по заднему фронту
}
else
{
TIM_ICStructure.TIM_ICPolarity = TIM_ICPolarity_Rising;
}
TIM_ICStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; // прямо с ножки
TIM_ICStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; // без делителя
TIM_ICStructure.TIM_ICFilter = 0; // без фильтра

// эта функция и включает режим PWM input - автоматически настраивает комплементарный канал
// правда в стандартной библиотеке работает на 1 и 2 канале, на 3 и 4 - не умеет
//TIM_PWMIConfig(tim, &TIM_ICStructure);

TIM_ICInit(tim, &TIM_ICStructure);

// Выбираем источник для триггера: вход 1
TIM_SelectInputTrigger(tim, TIM_TS_TI1FP1);
// По событию от триггера счётчик будет сбрасываться.
TIM_SelectSlaveMode(tim, TIM_SlaveMode_Reset);
// Включаем события от триггера
TIM_SelectMasterSlaveMode(tim, TIM_MasterSlaveMode_Enable);

// Разрешаем таймеру генерировать прерывание по захвату
if (chan == TIM_Channel_1) TIM_ITConfig(tim, TIM_IT_CC1, ENABLE);
if (chan == TIM_Channel_2) TIM_ITConfig(tim, TIM_IT_CC2, ENABLE);
if (chan == TIM_Channel_3) TIM_ITConfig(tim, TIM_IT_CC3, ENABLE);
if (chan == TIM_Channel_4) TIM_ITConfig(tim, TIM_IT_CC4, ENABLE);

TIM_ITConfig(tim, TIM_IT_Update, ENABLE);

TIM_ClearFlag(tim, TIM_FLAG_CC1);
TIM_ClearFlag(tim, TIM_FLAG_CC2);
TIM_ClearFlag(tim, TIM_FLAG_CC3);
TIM_ClearFlag(tim, TIM_FLAG_CC4);
TIM_ClearFlag(tim, TIM_IT_Update);

// Включаем таймер
TIM_Cmd(tim, ENABLE);
// разрешаем прерывания
NVIC_SetVector(irqnUP, (uint32_t)irqHandler);
NVIC_SetVector(irqnCC, (uint32_t)irqHandler);
NVIC_EnableIRQ(irqnUP);
NVIC_EnableIRQ(irqnCC);
}

static void irqHandler()
{
for (register int i = 0; i != timsNum; ++i)
{
tims[i]->irq();
}
}

inline void captCh(int ch)
{
}

inline void irq()
{
if (TIM_GetITStatus(tim, TIM_IT_CC1) != RESET) {
TIM_ClearITPendingBit(tim, TIM_IT_CC1);
TIM_ClearITPendingBit(tim, TIM_IT_Update);

cnt = TIM_GetCapture1(tim);
freq_ = float(SystemCoreClock/busDiv)/(float(cnt) + (ovf << 16));
ovf = 0;
}
if (TIM_GetITStatus(tim, TIM_IT_CC2) != RESET) {
TIM_ClearITPendingBit(tim, TIM_IT_CC2);
TIM_ClearITPendingBit(tim, TIM_IT_Update);

cnt = TIM_GetCapture2(tim);
freq_ = float(SystemCoreClock/busDiv)/(float(cnt) + (ovf << 16));
ovf = 0;
}
if (TIM_GetITStatus(tim, TIM_IT_CC3) != RESET) {
TIM_ClearITPendingBit(tim, TIM_IT_CC3);
TIM_ClearITPendingBit(tim, TIM_IT_Update);

cnt = TIM_GetCapture3(tim);
freq_ = float(SystemCoreClock/busDiv)/(float(cnt) + (ovf << 16));
ovf = 0;
}
if (TIM_GetITStatus(tim, TIM_IT_CC4) != RESET) {
TIM_ClearITPendingBit(tim, TIM_IT_CC4);
TIM_ClearITPendingBit(tim, TIM_IT_Update);

cnt = TIM_GetCapture4(tim);
freq_ = float(SystemCoreClock/busDiv)/(float(cnt) + (ovf << 16));
ovf = 0;
}
if (TIM_GetITStatus(tim, TIM_IT_Update) != RESET) {
TIM_ClearITPendingBit(tim, TIM_IT_Update);
ovf++;
}
}

uint32_t ovf;
uint32_t cnt;
uint32_t prescaler;
float freq_;
uint16_t holdEdge_;
uint16_t chan;
uint32_t busDiv;

volatile int enable;
TIM_TypeDef *tim;
IRQn irqnUP;
IRQn irqnCC;
};


это 4 таймера для считывания частоты.
на частотах до 2-3 герц работает отлично, на 32 килогерца показывает точно 320000, но стоит выстваить к примеру 32.101 как частота съезжает и показывается как 32.104 ~ 32.117, на схеме стоит внешний предделитель.

Подскажите я уже все перекопал, ничего не помогает...

Сообщение отредактировал IgorKossak - Jun 10 2014, 13:09
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!
Go to the top of the page
 
+Quote Post

3 страниц V  < 1 2 3
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 26th July 2025 - 03:43
Рейтинг@Mail.ru


Страница сгенерированна за 0.01406 секунд с 7
ELECTRONIX ©2004-2016