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

 
 
 
Reply to this topicStart new topic
> Ультразвуковой датчик и STM32f4-Discovery, не получается настроить one pulse mode
peroid
сообщение Jun 14 2015, 20:04
Сообщение #1


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 6-05-15
Пользователь №: 86 555



Всем доброго времени суток.

Пытаюсь прикрутить к STM32f4-Discovery ультразвуковой дальномер US-015.
Как я понял, нужно подать на ножку датчика импульс длиной 10 микросекунд, а потом посчитать ширину эха.
Думаю, что решение через задержку в главном цикле не совсем правильно, поэтому пытаюсь прикрутить все это аппаратно.
Как вариант решения, решил использовать режим одновибратора ТIM_SelectOnePulseMode(TIM9, TIM_OPMode_Single), но не могу понять как перезапустить импульс заново.
Перезапускать его хочу его из TIM1_BRK_TIM9_IRQHandler, после того, как произойдет считывание ширины эха.

Помогите пожалуйста подкостылить код, дабы запускать импульс по мере необходимости smile3046.gif
P.S. Длительность импульса задаю из главного цикла командой TIM_SetCompare1(TIM9, length);

Вот настройки GPIO и TIM9:

CODE

#include "UltraSonic_timer_ini.h"

int capture=0;

void UltraSonic_init(void)
{
GPIO_InitTypeDef UltraSonic_GPIO_init;
TIM_TimeBaseInitTypeDef UltraSonic_TIM_BASE_Settings;
TIM_OCInitTypeDef UltraSonic_TIM_OC_Settings;
TIM_ICInitTypeDef UltraSonic_TIM_IC_Settings;

//TAKTIRUEM
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);


UltraSonic_GPIO_init.GPIO_Mode=GPIO_Mode_AF;
UltraSonic_GPIO_init.GPIO_OType=GPIO_OType_PP;
UltraSonic_GPIO_init.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_6;
UltraSonic_GPIO_init.GPIO_PuPd=GPIO_PuPd_DOWN;
UltraSonic_GPIO_init.GPIO_Speed=GPIO_Low_Speed;

GPIO_Init(GPIOE, &UltraSonic_GPIO_init);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource5, GPIO_AF_TIM9);
GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_TIM9);



UltraSonic_TIM_BASE_Settings.TIM_ClockDivision = TIM_CKD_DIV1;
UltraSonic_TIM_BASE_Settings.TIM_CounterMode = TIM_CounterMode_Up;
UltraSonic_TIM_BASE_Settings.TIM_Period = 1000;
UltraSonic_TIM_BASE_Settings.TIM_Prescaler = 167;
UltraSonic_TIM_BASE_Settings.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM9, &UltraSonic_TIM_BASE_Settings);

UltraSonic_TIM_OC_Settings.TIM_OCIdleState = TIM_OCIdleState_Reset;
UltraSonic_TIM_OC_Settings.TIM_OCMode = TIM_OCMode_PWM1;
UltraSonic_TIM_OC_Settings.TIM_OCPolarity = TIM_OCPolarity_High;
UltraSonic_TIM_OC_Settings.TIM_OutputState = TIM_OutputState_Enable;
UltraSonic_TIM_OC_Settings.TIM_Pulse = 10;

TIM_OC1Init(TIM9, &UltraSonic_TIM_OC_Settings);

UltraSonic_TIM_IC_Settings.TIM_Channel = TIM_Channel_2; //Ispolzuem 2y kanal TIMER 9
UltraSonic_TIM_IC_Settings.TIM_ICFilter = 2; //Ne filtruem nichego
UltraSonic_TIM_IC_Settings.TIM_ICPolarity = TIM_ICPolarity_Rising; //Schitaem po narastauschemu frontu
UltraSonic_TIM_IC_Settings.TIM_ICPrescaler = TIM_ICPSC_DIV1; //Schitaem kajdiy impuls
UltraSonic_TIM_IC_Settings.TIM_ICSelection = TIM_ICSelection_DirectTI; //Napryamuiu so vhoda!!!

TIM_ICInit(TIM9, &UltraSonic_TIM_IC_Settings);


TIM_ITConfig(TIM9, TIM_IT_CC2, ENABLE);

TIM_Cmd(TIM9, ENABLE);

TIM_SelectOnePulseMode(TIM9, TIM_OPMode_Single);


NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);
}

void TIM1_BRK_TIM9_IRQHandler(void)
{
if (TIM_GetITStatus(TIM9, TIM_IT_CC2) != RESET)
{
TIM_ClearITPendingBit(TIM9, TIM_IT_CC2);

capture = TIM_GetCapture2(TIM9);

TIM_ClearFlag(TIM9,TIM_FLAG_Update);
}
}


Спасибо.
Go to the top of the page
 
+Quote Post
esaulenka
сообщение Jun 15 2015, 05:38
Сообщение #2


Профессионал
*****

Группа: Свой
Сообщений: 1 032
Регистрация: 13-03-08
Из: Маськва
Пользователь №: 35 877



Режим one pulse mode просто сбрасывает битик TIM_CR1_CEN в момент, TIM_CNT станет равным TIM_ARR.
Чтобы снова запустить таймер, надо установить этот бит обратно.

Однако в момент прерывания он явно ещё тикает, и эта идея не работает, нужна какая-то другая :-)


--------------------
Тут обсуждается творческий порыв, а не соответствие каким-либо стандартам ©
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Jun 16 2015, 07:19
Сообщение #3


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



Игрался с HC-SR04 - та же штука - вид сбоку.
Опрос в майне конечно не кошерно.
Делал опрос эхо-пина в прерывании таймера, настроенный на 58мкс или его множителях. 58мкс==1см до объекта, точности хватает, получается обычный счетчик в сантиметрах.
Go to the top of the page
 
+Quote Post
peroid
сообщение Jun 16 2015, 13:11
Сообщение #4


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 6-05-15
Пользователь №: 86 555



Цитата(alexeyv @ Jun 16 2015, 07:19) *
Делал опрос эхо-пина в прерывании таймера...


Сделал следующим образом - у таймера 9 настроил канал на сравнение:
CODE


// Настроил Пин 6 как альтернативную функцию таймера 9.
GPIO_InitTypeDef USonic_GPIOE_init;
TIM_TimeBaseInitTypeDef USonic__TIMER_9_init;
TIM_ICInitTypeDef USonic__IC_TIMER_9_def;


RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_TIM9, ENABLE);

USonic_GPIOE_init.GPIO_Mode = GPIO_Mode_AF;
USonic_GPIOE_init.GPIO_OType = GPIO_OType_PP;
USonic_GPIOE_init.GPIO_Pin = GPIO_Pin_6;
USonic_GPIOE_init.GPIO_PuPd = GPIO_PuPd_DOWN;
USonic_GPIOE_init.GPIO_Speed = GPIO_High_Speed;

GPIO_PinAFConfig(GPIOE, GPIO_PinSource6, GPIO_AF_TIM9);

GPIO_Init(GPIOE, &USonic_GPIOE_init);

// Думается, что при частоте 168 МГц и предделителе 16800, частота таймера будет 10'000 тиков в секунду
// Устанавливаю период, равный 10'000, чтобы таймер обнулялся каждые 10 милисекунд
// Мне все время кажется, что где то тут у меня ошибка sm.gif

USonic__TIMER_9_init.TIM_ClockDivision = TIM_CKD_DIV1;
USonic__TIMER_9_init.TIM_CounterMode = TIM_CounterMode_Up;
USonic__TIMER_9_init.TIM_Period = 10000;
USonic__TIMER_9_init.TIM_Prescaler = 16799;

TIM_TimeBaseInit(TIM9, &USonic__TIMER_9_init);

// Говорю таймеру считать по нарастающему фронту.

USonic__IC_TIMER_9_def.TIM_Channel = TIM_Channel_2;
USonic__IC_TIMER_9_def.TIM_ICFilter = 0;
USonic__IC_TIMER_9_def.TIM_ICPrescaler = TIM_ICPSC_DIV1;
USonic__IC_TIMER_9_def.TIM_ICSelection = TIM_ICSelection_DirectTI;
USonic__IC_TIMER_9_def.TIM_ICPolarity = TIM_ICPolarity_Rising;

TIM_ICInit(TIM9, &USonic__IC_TIMER_9_def);

// Включаю прерывания
NVIC_EnableIRQ(TIM1_BRK_TIM9_IRQn);
TIM_ITConfig(TIM9, T// Vkluchaem TIMER

// И сам таймер
TIM_Cmd(TIM9, ENABLE);

}



void TIM1_BRK_TIM9_IRQHandler(void)
{

if (TIM_GetITStatus(TIM9,TIM_IT_CC2)!=RESET)
{
TIM_ClearITPendingBit(TIM9, TIM_IT_CC2);

// Пишу значение, что насчитал таймер, в память.
delay_us = TIM_GetCapture2(TIM9);

}
}


Теперь беру таймер 7 и прикручиваю к нему ногу Е5:

CODE


GPIO_InitTypeDef USonic_GPIOEout_init;

RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOE, ENABLE);

USonic_GPIOEout_init.GPIO_Mode = GPIO_Mode_OUT;
USonic_GPIOEout_init.GPIO_OType = GPIO_OType_PP;
USonic_GPIOEout_init.GPIO_Pin = GPIO_Pin_5;
USonic_GPIOEout_init.GPIO_PuPd = GPIO_PuPd_DOWN;
USonic_GPIOEout_init.GPIO_Speed = GPIO_High_Speed;

GPIO_Init(GPIOE, &USonic_GPIOEout_init);



И таймер 7 наконец:
CODE


TIM_TimeBaseInitTypeDef Delay_TIM_BASE_Settings;

RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM7, ENABLE);

//Планируется, что таймер обнуляется каждую микросекунду
Delay_TIM_BASE_Settings.TIM_ClockDivision = TIM_CKD_DIV1;
Delay_TIM_BASE_Settings.TIM_CounterMode = TIM_CounterMode_Up;
Delay_TIM_BASE_Settings.TIM_Period = 1;
Delay_TIM_BASE_Settings.TIM_Prescaler = 83;
Delay_TIM_BASE_Settings.TIM_RepetitionCounter = 0;
TIM_TimeBaseInit(TIM7, &Delay_TIM_BASE_Settings);

// Включаю прерывание
NVIC_EnableIRQ(TIM7_IRQn);
TIM_ITConfig(TIM7, TIM_IT_Update, ENABLE);
// Запускаю таймер
TIM_Cmd(TIM7, ENABLE);



// Вот тут планируется, что пока счетчик меньше 10 мкС, идет импульс. В противном случае - выход подтянут к земле.
void TIM7_IRQHandler(void)
{

if (TIM_GetITStatus(TIM7,TIM_IT_Update)!=RESET)
{
if (us_delay < 10)
{
GPIO_SetBits(GPIOE, GPIO_Pin_5);
}else {
GPIO_ResetBits(GPIOE, GPIO_Pin_5);
}
us_delay++;
if (us_delay >= 10000)
{
us_delay=0;
}
}


Получилось .... какая то хрень получилась... Бытует мнение, что счетчик показывает часы до апокалипсиса, но вот только не эхо =(
Go to the top of the page
 
+Quote Post
peroid
сообщение Jun 18 2015, 13:45
Сообщение #5


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 6-05-15
Пользователь №: 86 555



Цитата(alexeyv @ Jun 16 2015, 07:19) *
Игрался с HC-SR04 - та же штука - вид сбоку.
Опрос в майне конечно не кошерно.
Делал опрос эхо-пина в прерывании таймера, настроенный на 58мкс или его множителях. 58мкс==1см до объекта, точности хватает, получается обычный счетчик в сантиметрах.


Блин! Вот я Алень wacko.gif =) Сейчас перечитал пост тов. alexeyv и на меня снизошла благодать и полная алилуя! Можно ж не только формировать импульс, но и посчитать его тупо по прерываниям maniac.gif
Пока вход == 1 инкрементировать значение счетчика таймера каждый раз в прерывании по переполнению, а как только он упадет (сигнал) в ноль, то передать это значение в обработку!!!

Но неужели нельзя прикрутить сюда таймер? по-любому можно =)
Думал по переднему фронту принудительно обнулять таймер и начинать захват, но не могу понять как отловить задний фронт... подумывал уже запаралелить ногу на другой вход, по заднему фронту генерить прерывание и тянуть значение таймера в обработку, но жаба душит безумно! Отдать ногу на такую хрень - это очень плохо.

Таймер 2 у меня занят, так что оба фронта не получится тут отслеживать.. только передний или задний.
Go to the top of the page
 
+Quote Post
alexeyv
сообщение Jun 19 2015, 02:47
Сообщение #6


Местный
***

Группа: Участник
Сообщений: 298
Регистрация: 26-01-09
Из: Пермь
Пользователь №: 43 940



Цитата
Пока вход == 1 инкрементировать значение счетчика таймера каждый раз в прерывании по переполнению, а как только он упадет (сигнал) в ноль, то передать это значение в обработку!!!

08.gif

Добавьте конечный автомат: переход 0->1 - начало отсчета; удержание 1 - инкремент расстояния; переход 1->0 - конец счета.
Go to the top of the page
 
+Quote Post
ArtDenis
сообщение Jun 19 2015, 03:07
Сообщение #7


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

Группа: Участник
Сообщений: 142
Регистрация: 10-11-12
Пользователь №: 74 318



Цитата(peroid @ Jun 18 2015, 18:45) *
Думал по переднему фронту принудительно обнулять таймер и начинать захват, но не могу понять как отловить задний фронт... подумывал уже запаралелить ногу на другой вход, по заднему фронту генерить прерывание и тянуть значение таймера в обработку, но жаба душит безумно! Отдать ногу на такую хрень - это очень плохо

Ничего надо параллелить. Всё предусмотрено внутри таймера. Смотри в даташите главу "PWM input mode". Там прямо по шагам расписано как сделать, чтобы таймер автоматом обнулялся на фронте и автоматом считывал длительность на спаде импульса. Что-то мне подсказывает, что на эту тему есть и примеры HAL или STL


--------------------
http://ufa-darts.ru/ - собираем дартс-лигу в Уфе
Go to the top of the page
 
+Quote Post

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

 


RSS Текстовая версия Сейчас: 21st July 2025 - 13:44
Рейтинг@Mail.ru


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