Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: STM32f4 discovery прерывания
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > ARM, 32bit
Silber
в STM32CubeMX сгенерировал себе вот такой проект:
USB OTG FS(для передачи данных на пк через виртуальный ком-порт), TIM6, Синяя кнопка, +2 gpio пина для работы с ультразвуковым датчиком расстояния.
Цель программы - научиться считывать показания датчика. Как с ним работать: подать на пин Trig единицу длиной 10микроСек, засечь, сколько жду ответ от датчика по пину Echo. Преобразовать временной промежуток и получить расстояние до объекта. Все просто!
Как я хочу, чтобы работала программа: при нажатии на кнопку контроллер отправляет по usb мне расстояние до объекта. Алгоритм:
1)прерывание по нажатию на кнопку
2)запускается таймер, его источник - 48МГц, делитель 0, период 47. (чтобы каждую микросекунду он генерировал прерывание)
3)работа с сенсором //этот пункт сейчас не вызывает вопросов
4)отправка данных по usb
Данные по usb передаются нормально, но, если я включаю таймер, то USB виснет. Догадываюсь, что дело в прерываниях и их приоритетах. Приоритеты прерываний см на изображении. Что такое под-приоритет?
adnega
Цитата(Silber @ Apr 23 2015, 17:49) *
2)запускается таймер, его источник - 48МГц, делитель 0, период 47. (чтобы каждую микросекунду он генерировал прерывание)

Тут вам следует пересмотреть архитектуру.
Что полезного вы успеете сделать за 48 тактов, причем 12 израсходуется только для вхождения в прерывание?
Для формирования импульса и измерения отклика можно и нужно использовать аппаратные возможности таймера (при этом точность можно значительно повысить).
Silber
Цитата(adnega @ Apr 23 2015, 19:10) *
Тут вам следует пересмотреть архитектуру.
Что полезного вы успеете сделать за 48 тактов, причем 12 израсходуется только для вхождения в прерывание?
Для формирования импульса и измерения отклика можно и нужно использовать аппаратные возможности таймера (при этом точность можно значительно повысить).

А почему за 48 тактов? Проц работает на частоте 168Мгц (или нет?). А как называется режим, в котором стоит использовать таймер для такой моей цели? One Pulse Mode?
Спасибо за ответ, но насчет прерываний-то что?
adnega
Цитата(Silber @ Apr 23 2015, 19:56) *
А почему за 48 тактов? Проц работает на частоте 168Мгц (или нет?). А как называется режим, в котором стоит использовать таймер для такой моей цели? One Pulse Mode?
Спасибо за ответ, но насчет прерываний-то что?

Частота 168МГц это максимум для данного МК. В данном случае это ситуацию не меняет, т.к. вместо 48 тактов будет 168 и это все равно очень мало.

Я бы сделал так:
1. Настроил таймер (лучше TIM2 - он 32-битный) с нужным PSC (т.е. временнЫм разрешением).
2. В ARR записал значение в зависимости от требуемой частоты опроса.
3. CH1 настроил на вывод PWM сигнала на ногу Trig с длительностью 10 мкс.
4. CH2 настроил на захват переднего фронта с ноги Echo и генерацией прерывания.

В итоге имеем требуемую частоту опроса датчика с генерацией прерывания по приходу эха.
Таймер работает с максимальным разрешением, cpu отвлекается только в моменты прихода эха.
При этом в регистре лежит результат, который нужно лишь домножить на константу, чтоб получить расстояние.
Если данные нужны не в реальном времени, а можно сложить в буфер, например, для отправки по USB, то, натравив на таймер DMA,
можно еще больше разгрузить cpu. Задачка явно не для 168МГц))
Silber
Цитата(adnega @ Apr 23 2015, 20:44) *
Частота 168МГц это максимум для данного МК. В данном случае это ситуацию не меняет, т.к. вместо 48 тактов будет 168 и это все равно очень мало.

Я бы сделал так:
1. Настроил таймер (лучше TIM2 - он 32-битный) с нужным PSC (т.е. временнЫм разрешением).
2. В ARR записал значение в зависимости от требуемой частоты опроса.
3. CH1 настроил на вывод PWM сигнала на ногу Trig с длительностью 10 мкс.
4. CH2 настроил на захват переднего фронта с ноги Echo и генерацией прерывания.

В итоге имеем требуемую частоту опроса датчика с генерацией прерывания по приходу эха.
Таймер работает с максимальным разрешением, cpu отвлекается только в моменты прихода эха.
При этом в регистре лежит результат, который нужно лишь домножить на константу, чтоб получить расстояние.
Если данные нужны не в реальном времени, а можно сложить в буфер, например, для отправки по USB, то, натравив на таймер DMA,
можно еще больше разгрузить cpu. Задачка явно не для 168МГц))

Большое спасибо, очень круто (даже не подозревал, что можно так)! Так и сделаю. А насчет моего изначального вопроса (ну не оставлять же пробелы в голове)

У датчика есть еще один способ снятия показаний: умножить на коэф длину эха. Получается, еще лучше использовать этот способ, поставив СН2 в input capture?
Silber
Ошибся в последнем предложении. Режим называется PWM Input mode:
This mode is a particular case of input capture mode. The procedure is the same except:
• Two ICx signals are mapped on the same TIx input.
• These 2 ICx signals are active on edges with opposite polarity.
• One of the two TIxFP signals is selected as trigger input and the slave mode controller
is configured in reset mode.
For example, you can measure the period (in TIMx_CCR1 register) and the duty cycle
adnega
Цитата(Silber @ Apr 23 2015, 22:40) *
Режим называется PWM Input mode:

Вам достаточно простого захвата переднего фронта пина Echo.

Цитата
Что такое под-приоритет?

Представьте: cpu находится в более приоритетном прерывании, за это время возникают два прерывания с одинаковым приоритетом пониже.
cpu заканчивает обработку приоритетного прерывания и что ему выполнять дальше? А дальше nvic смотрит есть два новых прерывания
с одинаковым приоритетом, из них он выбирает то, у которого под-приоритет выше. Если под-приоритеты равны, то nvic выбирает то, которое
стоит в таблице векторов прерываний раньше.

По сути под-приоритет в cortex это как приоритет в avr (если не заморачиваться с вложенными прерываниями) - сказать контроллеру прерываний
кого вызывать вперед при прочих равных.
Silber
Цитата(adnega @ Apr 24 2015, 08:36) *
Вам достаточно простого захвата переднего фронта пина Echo.


Представьте: cpu находится в более приоритетном прерывании, за это время возникают два прерывания с одинаковым приоритетом пониже.
cpu заканчивает обработку приоритетного прерывания и что ему выполнять дальше? А дальше nvic смотрит есть два новых прерывания
с одинаковым приоритетом, из них он выбирает то, у которого под-приоритет выше. Если под-приоритеты равны, то nvic выбирает то, которое
стоит в таблице векторов прерываний раньше.

По сути под-приоритет в cortex это как приоритет в avr (если не заморачиваться с вложенными прерываниями) - сказать контроллеру прерываний
кого вызывать вперед при прочих равных.

Еще раз спасибо. С avr я не знаком, да и с электроникой в целом. Мой путь - от высокоуровнего программирования к низкоуровнему на МК. STM32f4 мой первый МК
adnega
Цитата(Silber @ Apr 24 2015, 09:09) *
Мой путь - от высокоуровнего программирования к низкоуровнему на МК. STM32f4 мой первый МК

Ааа. Понятно. Тогда предупреждаю, что тут подход отличается.
Основная цель разработчика - по максимуму нагрузить богатую периферию.
Решать железные вопросы софтово - дурной тон в МК)
Silber
Цитата(adnega @ Apr 24 2015, 09:32) *
Ааа. Понятно. Тогда предупреждаю, что тут подход отличается.
Основная цель разработчика - по максимуму нагрузить богатую периферию.
Решать железные вопросы софтово - дурной тон в МК)

Спасибо sm.gif
Еще и факультет не "электронный" - прикладная математика help.gif
Вообще цель - управление квадрокоптером, вот по части управления преподаватели хорошо помогают и учат, а с микроконтроллерами никто толком не знаком...

Почему-то значение захватывает ~468 (+-1)(это без преобразования), вне зависимости от расстояния до препятствия. Проверьте настройки, пожалуйста.
А код простой - как вы и написали: прерывание при захвате переднего фронта, сохранение значения в глобальную переменную. При нажати на голубую кнопку данные отправляются по юсб. По юсб данные идут исправно (совпадают со значениями в дебагере).



Может, дело в подтягиваниях? Я еще не до конца осознал, как они работают blush.gif
Сенсор рабочий, я его проверял: подавал короткие импульсы (по ноге, подключенной к диоду), и получал эхо (опять на ногу, подключенную к диоду) диод отвечающий за эхо моргал по-разному, в зависимости от расстояния до препятствия.
esaulenka
Осциллографа под рукой нету?

Моргания светодиода в 0.5 миллисекунды глазом увидеть никак не получится, значит, это явно не то значение.
Может быть, через 468 микросекунд этот сигнал echo переходит в единицу, а потом, собственно, по получению эха, обратно в ноль?..

Быстрый способ проверки - поменять полярность срабатывания capture.
Правильный способ - почитать документацию (и нам показать).
Silber
Показания сняты успешно!
Однако, не без загадок для меня: запомнил, что ответ с сенсора приходит приблизительно через 468мс, настроил Input capture канал таймера не на передний фронт, а на задний, вычел из захваченного значения 468 (получив таким образом длину эха) , преобразовал по формуле для длины ожидания ответа (поделил на 58). Получается, что производитель нагло врёт в мануале к датчику или я перевел не верно? (см. ниже)
The Timing diagram is shown below. You only need to supply a short 10uS
pulse to the trigger input to start the ranging, and then the module will send out
an 8 cycle burst of ultrasound at 40 kHz and raise its echo. The Echo is a
distance object that is pulse width and the range in proportion .You can
calculate the range through the time interval between sending trigger signal and
receiving echo signal. Formula: uS / 58 = centimeters or uS / 148 =inch; or: the
range = high level time * velocity (340M/S) / 2; we suggest to use over 60ms
measurement cycle, in order to prevent trigger signal to the echo signal.



Цитата(esaulenka @ Apr 24 2015, 15:24) *
Осциллографа под рукой нету?

Моргания светодиода в 0.5 миллисекунды глазом увидеть никак не получится, значит, это явно не то значение.
Может быть, через 468 микросекунд этот сигнал echo переходит в единицу, а потом, собственно, по получению эха, обратно в ноль?..

Быстрый способ проверки - поменять полярность срабатывания capture.
Правильный способ - почитать документацию (и нам показать).

Само собой получилось, пока ждал ответа тут. Осциллографа нет =/ (сколько стоит сие чудо техники?).

ПС помогите еще вот это перевести и осознать, а то я гироскоп уже спалил случайно =D
Attention:
The module is not suggested to connect directly to electric, if connected
electric, the GND terminal should be connected the module first, otherwise,
it will affect the normal work of the module.
esaulenka
Как нарисовано, так и работает.
По входу "триггер" датчик формирует пачку импульсов.
По окончанию отправки пачки датчик выставляет "эхо" в единичку (у него это занимает ПРИМЕРНО 468 мкс).
По окончанию приёма пачки датчик выставляет "эхо" в ноль (длительность импульса - именно то, что нам надо).

Слово "примерно" я подчеркнул не зря - скорее всего, за цифру 468 производитель не ручается.
Соответственно, ПРАВИЛЬНЫЙ алгоритм - померять время обоих фронтов (благо, Вы это делать умеете - нужно задействовать ещё один канал таймера) и вычитать одно из другого.
Silber
Цитата(esaulenka @ Apr 24 2015, 15:39) *
Как нарисовано, так и работает.
По входу "триггер" датчик формирует пачку импульсов.
По окончанию отправки пачки датчик выставляет "эхо" в единичку (у него это занимает ПРИМЕРНО 468 мкс).
По окончанию приёма пачки датчик выставляет "эхо" в ноль (длительность импульса - именно то, что нам надо).

Слово "примерно" я подчеркнул не зря - скорее всего, за цифру 468 производитель не ручается.
Соответственно, ПРАВИЛЬНЫЙ алгоритм - померять время обоих фронтов (благо, Вы это делать умеете - нужно задействовать ещё один канал таймера) и вычитать одно из другого.

Так, а что такое тогда high level time?
esaulenka
Цитата(Silber @ Apr 24 2015, 15:30) *
Осциллографа нет =/ (сколько стоит сие чудо техники?).

За неимением осциллографа можно пользоваться лог.анализатором. Самый дешёвый вариант - китайский. Тем не менее, работает хорошо, периодически заменяя осциллограф ценой в несколько тыс. $. Аналоговые подробности сигнала там не видно, конечно. Но просто посмотреть, как ножки контроллера дёргаются - очень полезно.
А собственно осциллограф... 200..300$ - это самое-самое начало...




Цитата(Silber @ Apr 24 2015, 15:30) *
Attention:
The module is not suggested to connect directly to electric, if connected
electric, the GND terminal should be connected the module first, otherwise,
it will affect the normal work of the module.

Не понял, что это. Полная документация есть?

Цитата(Silber @ Apr 24 2015, 15:50) *
Так, а что такое тогда high level time?

Могу предположить, что "длительность высокого уровня на выходе echo".
Почему в описании предлагают измерять длительность от входного сигнала... Видимо, ошибка.
Silber
Цитата
Не понял, что это. Полная документация есть?

Да, извиняюсь, что сразу не скинул.
esaulenka
Ну... Надо учитывать, что Шенжень находится достаточно далеко от Оксфорда :-) Соответственно, язык там знают неидеально...
Правильное описание алгоритма этого датчика, кстати, есть в разделе product features.

А как трактовать "not suggested to connect directly to electric"... Видимо, "не втыкать при наличии питания" (и это правильно!)
Silber
Цитата(esaulenka @ Apr 24 2015, 16:25) *
А как трактовать "not suggested to connect directly to electric"... Видимо, "не втыкать при наличии питания" (и это правильно!)

А я в основном так и поступал rolleyes.gif
Спасибо за помощь всем!

А в чем разница между установкой одного IC-канала на срабатывании на обоих фронатах (и передний и задний) и установкой двух каналов на одну ногу, каждый канал за свой фронт отвечает? Я сейчас реализовал первый вариант, всё нормально работает...

Реализовал второй вариант (два канала на одну ногу). Логика программы чуть чуть изменилась: прерывание теперь обрабатывается при сбрасывании таймера (в первом варианте прерывание создавалось при захвате фронтов). Какой вариант использовать предпочтительнее?
esaulenka
Цитата(Silber @ Apr 24 2015, 17:39) *
А в чем разница между установкой одного IC-канала на срабатывании на обоих фронатах (и передний и задний) и установкой двух каналов на одну ногу, каждый канал за свой фронт отвечает? Я сейчас реализовал первый вариант, всё нормально работает...

Реализовал второй вариант (два канала на одну ногу). Логика программы чуть чуть изменилась: прерывание теперь обрабатывается при сбрасывании таймера (в первом варианте прерывание создавалось при захвате фронтов). Какой вариант использовать предпочтительнее?


Какой вариант лучше - вопрос предпочтений.

В первом случае процессор чуть меньше загружен. К тому же, если почему-то заблокируется прерывание от таймера в момент прихода ответного импульса, значение переднего фронта потеряется (можно проанализировать флаг переполнения и что-то сделать).
Во втором случае экономится один канал таймера (актуально, если датчиков много).
Во втором случае, кстати, не обязательно ждать переполнения таймера - можно использовать прерывание по заднему фронту импульса.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.