Перейти к содержанию
    

Ультразвуковой датчик и STM32f4-Discovery

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

 

Пытаюсь прикрутить к STM32f4-Discovery ультразвуковой дальномер US-015.

Как я понял, нужно подать на ножку датчика импульс длиной 10 микросекунд, а потом посчитать ширину эха.

Думаю, что решение через задержку в главном цикле не совсем правильно, поэтому пытаюсь прикрутить все это аппаратно.

Как вариант решения, решил использовать режим одновибратора ТIM_SelectOnePulseMode(TIM9, TIM_OPMode_Single), но не могу понять как перезапустить импульс заново.

Перезапускать его хочу его из TIM1_BRK_TIM9_IRQHandler, после того, как произойдет считывание ширины эха.

 

Помогите пожалуйста подкостылить код, дабы запускать импульс по мере необходимости :smile3046:

P.S. Длительность импульса задаю из главного цикла командой TIM_SetCompare1(TIM9, length);

 

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

 

#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);
 }
}

 

Спасибо.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Режим one pulse mode просто сбрасывает битик TIM_CR1_CEN в момент, TIM_CNT станет равным TIM_ARR.

Чтобы снова запустить таймер, надо установить этот бит обратно.

 

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Игрался с HC-SR04 - та же штука - вид сбоку.

Опрос в майне конечно не кошерно.

Делал опрос эхо-пина в прерывании таймера, настроенный на 58мкс или его множителях. 58мкс==1см до объекта, точности хватает, получается обычный счетчик в сантиметрах.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Делал опрос эхо-пина в прерывании таймера...

 

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


// Настроил Пин 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 милисекунд
//     Мне все время кажется, что где то тут у меня ошибка :)

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:

 


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 наконец:


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;
	}
}

 

Получилось .... какая то хрень получилась... Бытует мнение, что счетчик показывает часы до апокалипсиса, но вот только не эхо =(

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Игрался с HC-SR04 - та же штука - вид сбоку.

Опрос в майне конечно не кошерно.

Делал опрос эхо-пина в прерывании таймера, настроенный на 58мкс или его множителях. 58мкс==1см до объекта, точности хватает, получается обычный счетчик в сантиметрах.

 

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

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

 

Но неужели нельзя прикрутить сюда таймер? по-любому можно =)

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

 

Таймер 2 у меня занят, так что оба фронта не получится тут отслеживать.. только передний или задний.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

:08:

 

Добавьте конечный автомат: переход 0->1 - начало отсчета; удержание 1 - инкремент расстояния; переход 1->0 - конец счета.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...