понеділок, 28 листопада 2016 р.

Далекомір HC-SR04 -- зовнішні переривання EXTI/HAL

Подивимося, що в порівнянні із використанням CMSIS, надає нам STM32CubeMX разом із HAL для організації обробки переривань від зовнішніх джерел, традиційно -- реалізувавши приклад із попереднього CMSIS-поста.

Периферія сконфігурована як і раніше:
  • Trig -- пін PA10,  вивід. Ми керуватимемо ним третім каналом таймера TIM1.
  • Echo -- PA6, генеруємо переривання.
"Малюємо" відповідну конфігурацію:

неділю, 27 листопада 2016 р.

Далекомір HC-SR04 -- зовнішні переривання EXTI/CMSIS

Взято тут: "STM32 External Interrupt"
Перекласти всю роботу із далекоміром на таймери (чи таймер) -- зручно, але, іноді, надміру складно -- якісь Capture-compare, захоплення ШІМ, інший "страх и ужас". Мікроконтролери мають ще один, простіший спосіб фіксувати тривалість імпульсу -- за допомогою "банального" зовнішнього переривання -- EXTI: фіксується момент зміни стану лінії ECHO з 0 в 1, потім -- назад, тривалість -- різниця часу між ними. Таймер, звичайно, використовується -- для вимірювання часу, але лише як лічильник. 

Спрощений варіант роботи за допомогою переривань було розглянуто в "методичному" пості: "Зовсім просто про далекомір HC-SR04 із GPIO/HAL", тут дотримуватимуся більш систематичного, але дещо заскладного для конкретної простої задачі підходу. 

понеділок, 21 листопада 2016 р.

Далекомір HC-SR04 -- один таймер/HAL

Повторимо зроблене в попередньому пості, із використанням HAL/SMT32CubeMX. Такі, трішки нестандартні, режими роботи, HAL безпосередньо не підтримує, але і не заважає сильно -- все ж, абстракція, надана цією бібліотекою, зовсім тоненька.

Нагадаємо апаратну конфігурацію:
  • TRIG -- PA6 (TIM3_CH1)
  • ECHO -- PB0 (TIM3_CH3)
  • PC8 -- синій світлодіод
  • PC9 -- зелений світлодіод 
За потреби, Cube вміє автоматично робити ремапінг. Тут в ньому потреби немає:

пʼятницю, 18 листопада 2016 р.

Далекомір HC-SR04 -- трасування, додаток

Взято тут.
Як вже згадувалося, використання дебагера для пошуку помилок можливе не завжди. Причин дві -- таймери, які не обов'язково зупиняються при зупинці головної програми та периферія, яка має свої часові характеристики, і часто не може вийти за їх межі. Якщо для таймерів мікроконтролер підтримує режим зневадження із їх зупинкою (при тому, не всі середовища розробки надають доступ до нього), то з периферією складніше. Наприклад, якщо шина I2C цілком терпима до доступних людині затримок, то  HC-SR04 не чекатиме -- через мілісекунди після запуску, видає результат, тривалістю до десятків мілісекунд і на тому завершує.

Один із способів пошуку помилок у таких програмах -- зберегти послідовність виконання програми в самому мікроконтролері, а потім передати її на комп'ютер -- так зване трасування. Воно використовувалося для створення програм, які працюють із далекоміром з використанням таймерів (чесно кажучи, однотаймерний варіант я б без трасування не зміг би до ладу довести, принаймні, це забрало б на порядок більше часу). Розглянемо використаний там підхід.
Увага: дана реалізація дуже примітивна і має багато недоліків! Створювалася нашвидкоруч і без якихось подальших перспектив. На С++ можна зробити багато краще та надійніше. Та й на чистому С є простір для покращення.
Крім того, навіть ідеально реалізований, цей метод придатний не всюди -- він не підійде, наприклад, для дуже чутливої до часів реакції апаратури, або коли пам'яті не вистачає. Однак, на загал, інструмент зручний.
Отож, поїхали.

середу, 16 листопада 2016 р.

Далекомір HC-SR04 -- один таймер/CMSIS

Приклад скінченного автомата,
який визначає чи двійкове число
має непарну кількість 0.
(c) Wiki
Чим простіший код, тим краще. Код, де пінами ECHO та TRIG керують окремі таймери відносно простий. Однак, з одного боку, таймери -- ресурс цінний та обмежений. На STM32F100, котрим обладнана наша плата, таймерів, здатних генерувати PWM -- десяток, але вони сильно відрізняються за можливостями. Для реальних пристроїв це не так вже і багато! З іншого боку, частина таймерів мають багато каналів. (Для цього контролера п'ять -- по 4 канали, три -- по 2, і три -- єдиний (комплементарні не рахуючи). 

Захоплення ШІМ, на яке ми покладаємося, потребує двох каналів, генерація TRIG -- ще одного. Отож, одного таймера для керування далекоміром має вистачити. 
Заради простоти я не став вішати на четвертий канал ШІМ для візуального відображення віддалі світлодіодом. Залишимо це на домашнє завдання. Видається, це можливо, хоч гарантії, не зробивши, не дам.
Користуватимемося таймером TIM3, його CH1 i CH2 займатимуться захопленням ECHO, а CH3 -- TRIG. Тому, без використання ремапінгу, апаратна конфігурація така:
  • TRIG -- PA6 (TIM3_CH1)
  • ECHO -- PB0 (TIM3_CH3)
  • PC8 -- синій світлодіод
  • PC9 -- зелений світлодіод 
 Думаю, можна зробити краще, вважатимемо приклад нижче лише технологічною демонстрацією.

Логіка роботи програми


вівторок, 15 листопада 2016 р.

Далекомір HC-SR04 -- два таймери/HAL

Традиційно, вирішимо задачу із попереднього посту, користуючись тим же підходом, з використанням HAL та SMT32CubeMX.

Апаратна конфігурація та ж:
  • TRIG -- PA10  (TIM1_CH3)
  • ECHO -- PA6 (TIM3_CH1, CH2 indirect)
  • Світлодіод, яскравість якого показує віддаль до перешкоди -- PA0 (TIM2_CH1)
  • Світлодіоди плати, як завжди, синій на піні PB8 і зелений на PB9
  • TIM1 генеруватиме імпульс заданої довжини ~ 10-15 мкс, в ролі TRIG, на PA10
  • TIM3 вимірюватиме тривалість імпульсу на лінії ECHO, PA6
  • TIM2 -- PWM (ШІМ) на PA0
 Візуально це виглядатиме так:
Клікабельно!

понеділок, 14 листопада 2016 р.

Далекомір HC-SR04 -- два таймери/CMSIS

Лого однойменної групи. Не маю ні найменшого
уявлення, що у них за музика. Здавалося б, невинне
словосполучення: "Two timers".
Дивимося словники: TheFreeDictionary
та UrbanDictionary
Озброївшись знаннями про таймери, спробуємо вирішити задачу роботи із далекоміром більш елегантно. Спершу зробимо марнотратно -- кожній під-задачі виділимо свій таймер. Насправді, назва посту трішки обманює -- використано аж три таймери, а не два:
  • TIM1 генеруватиме імпульс заданої довжини ~ 10-15 мкс, в ролі TRIG
  • TIM3 вимірюватиме тривалість імпульсу на лінії ECHO
  • TIM2 -- не важливий для власне роботи, тому не врахований в заголовку, візуально показуватиме віддаль до перешкоди, за допомогою світлодіоду та PWM (ШІМ)
Спочатку зробимо це засобами CMSIS.

Апаратна конфігурація відрізняється від попередніх прикладів із використанням GPIO, так як канали таймерів прив'язані до конкретних піні (навіть із ремапінгом варіантів не так багато). Для цього прикладу вона наступна:
  • TRIG -- PA10  (TIM1_CH3)
  • ECHO -- PA6 (TIM3_CH1, CH2 indirect)
  • Світлодіод, яскравість якого показує віддаль до перешкоди -- PA0 (TIM2_CH1)
  • Світлодіоди плати, як завжди, синій на піні PB8 і зелений на PB9

Логіка роботи програми


вівторок, 8 листопада 2016 р.

Таймери STM32 -- зміст

Статей про таймери вийшло багато. Щоб краще орієнтуватися, пасує зробити зміст. Потім треба буде його зробити ще й для постів про далекомір. Аналогічний зміст для постів про далекомір.

Проекти із кодом, який використовується в постах, зазвичай можна скачати за посиланням в кінці посту. Історично склалося так, що більшість проектів проекти для CoIDE. В принципі, зараз перейшов на System Workbench for STM32, але якби взявся всі проекти переносити -- написання цих постів точно ніколи б не завершилося.

Розглядається використання CMSIS та HAL+STM32CubeMX. Код Cube та HAL розтинається та аналізується аж до рівня CMSIS -- безпосередньої маніпуляції регістрами.
На жаль, не передбачено простого візуального способу пропустити цей reverse engineering для тих, кому цікаво лише знайти підказку, як скористатися тією чи іншою можливістю. Однак, в тексті все-таки відділяється опис способі використання від аналізу подробиць роботи.

понеділок, 7 листопада 2016 р.

Таймери STM32 -- порівняння розмірів коду для CMSIS i HAL

В процесі написання серії постів про таймери склалася цікава ситуація. Ми маємо пари однотипних проектів, в одному із яких задача вирішується за допомогою CMSIS, у іншому -- HAL. При чому, для "HAL-проектів", код ініціалізація створювався за допомогою STM32CubeMX,  і є доволі громіздким, як ми не раз могли зауважити.
При чому, певна надія на оптимізатор компілятора залишається, але не надмірна -- оптимізації, які маніпулюють апаратними регістрами він просто "не посміє" робити.
Така ситуація дозволяє подивитися, скільки ж це задоволення -- зручне написання коду ініціалізації, коштує. При чому тут, на відміну від постів про далекомір, розмір C runtime i printf() не вноситиме величезну систематичну "похибку" -- він або присутній, або ні, в обох проектах одночасно.

Зауваження. Отримані вами значення для самостійно скомпільованих проектів можуть трохи відрізнятися, як через різні версії компілятора, так і через дрібні виправлення в проекті, з приводу яких немає бажання перекомпільовувати всі комбінації, лише щоб отримати уточнені на пару байт туди або сюди розміри для табличок нижче.

Якщо лінь, переходьте зразу до висновків.