Cьогодні я розповім, як я боровся із дрижанням кнопки, в розрізі мікроконтролера STM32 ( в данному випадку STM32F042F6P6 ) та бібліотеки HAL & CubeMX. Будемо використовувати зовнішні переривання.
Як відомо при натисканні на кнопку, зазвичай відбувається багаторазове замикання і розмикання її контактів. Схематично це може бути представлене в такий спосіб:
Я не буду розповідати по всі свої експерименти в боротьбі із цим "нехорошим" явищем, тому зупинюсь лише на кінцевому варіанті, який мене влаштував.
Підключення кнопок. Після різних варіантів підключення, я зупинився на "фірмовому" варіанті від STMicroelectronics, який застосований в платах Discovery:
Таку схему я зібрав для 4-ох кнопок, с такимиж номіналами резисторів та конденсаторів.
Як я вже писав ми використовуємо зовнішні переривання. Як відомо зовнішні переривання активізуються при зміни логічного рівня на нозі контролера. У STM32 за зовнішні переривання відповідає EXTI контролер.
Стартуємо. Будемо створювати прошивку для нашого МК при допомозі програми CubeMX. Цей інструмент, хоча і з'явився вже давно, був мною незаслужено обділений увагою. Щож я думаю ми заповнимо цю прогалину...
Відкриваємо програму, створюємо новий проект
Ми будемо використовувати відлагоджувальну плату для STM32F0xxFx описану раніше, та в якості пограматора плату STM32F4 Discovery.
Вибираємо наш МК, в даному випадку у мене STM32F042F6P6.
Далі налаштовуємо наші піни. Спочатку ввімкнемо інтерфейс SWD, звісно якщо ми будемо прошивати МК через програматор ST-Link. Це ноги РА13,РА14. Якщо цього не зробити, то потрібно буде завжди при прошивці контролера натискати кнопку RESET, що не дуже зручно.
Забіжу наперед, ми маємо підключити крім кнопок ще дисплей - потрібно 5 ніжок, нехай це будуть РА0,РА1,РА2,РА3,РА4. Також три піна виділимо для світлодіодів, нехай це будуть РВ1,РF0,РF1. Всі ці ножки налаштовуються як GPIO_Output:
Налаштовуємо ножки під кнопки. Використовуємо піни PA5,PA6,PA7, вмикаємо на них контролер зовнішніх переривань EXTI:
Тепер ще один момент. Як ми вже писали для реагування на натискання кнопки використовуємо контролер зовнішніх переривань EXTI. Обробник переривання спільний для цих тьох пінів - EXTI4_15_IRQHandler . Тобто з 4 по 15 пін має одне зовнішнє переривання. Оскільки ми не плануємо обробляти два натискання одночасно, то в принципі це все нас влаштовує.
Забігаючи на перед опишу, як же ми будемо боротись саме с дрижанням кнопки. Для цього скористаємось затримкою на час перехідних процесів в кнопці, і щоб її організувати так щоб не зашкодити виконанню основної програми, застосуємо іще таймер , наприклад TIM14. Вмикаємо його:
Далі заходимо на вкладку Clock Configuration і виставляємо частоту на якій буде працювати ядро та переферія контролера. в даному випадку я встановив максимально можливу для STM32F0xx - 48 MHz. Також все буде тактуватись від внутрішнього генератора HSI . Хоча STM32F042 має більш стабільний HSI48 , призначений для апаратного USB, всеж використовуємо звичайний HSI, оскільки планується перенос проекта на STM32F030.
Наступна вкладка Configuration . Розпочнем із того що ввімкнемо наші обробники переривань для EXTI та TIM14.
Далі налаштуємо наші піни, які використовуються для кнопок. Підтяжки не вмикаємо, оскільки вони в нас вже є (див. вище схему підключення кнопки). Також зовнішнє переривання налаштовуємо по обох фронтах Rising & Filling, саме так сама досяглась сама стабільна робота...
Далі налаштовуємо таймер TIM14. Прескалер виставляємо 47999, щоб таймер "тікав" з частотою 1 раз в мілісекунду. А період поставимо 100, в нашому випадку це буде 100 мс. Чому вибране це число? Приблизно такий час зазвичай складає дрижання кнопки.
Ну ось тепер можна генерувати наш проект.
Я люблю Keil, тому саме цей компілятор я вибрав в налаштування CubeMX. 5-ту версію. "Пустий" проект "заважив" - Program Size: Code=3564 RO-data=240 RW-data=8 ZI-data=1088
Починаємо наповнювати проект.
Дисплей. Для більшої інформативності прикріпив до проекта дисплей під назвою NOKIA 5110 на контролері PCD8544:
Бібліотека для нього перша яка "нагуглилась" з "ногодригом" - http://vg.ucoz.ru/forum/9-100-1 Ми її трішки адаптували під себе та бібліотеку HAL.
// Управление линией LCD_CS
#define LCD_CS1 HAL_GPIO_WritePin(LCD_PORT, SCE, GPIO_PIN_SET)
#define LCD_CS0 HAL_GPIO_WritePin(LCD_PORT, SCE, GPIO_PIN_RESET)
// Управление линией LCD_RST
#define LCD_RST1 HAL_GPIO_WritePin(LCD_PORT, RST, GPIO_PIN_SET)
#define LCD_RST0 HAL_GPIO_WritePin(LCD_PORT, RST, GPIO_PIN_RESET)
// Управление линией LCD_DC
#define LCD_DC1 HAL_GPIO_WritePin(LCD_PORT, DC, GPIO_PIN_SET)
#define LCD_DC0 HAL_GPIO_WritePin(LCD_PORT, DC, GPIO_PIN_RESET)
// Управление линией LCD_SCK
#define LCD_SCK1 HAL_GPIO_WritePin(LCD_PORT, SCLK, GPIO_PIN_SET)
#define LCD_SCK0 HAL_GPIO_WritePin(LCD_PORT, SCLK, GPIO_PIN_RESET)
// Управление линией LCD_MOSI
#define LCD_MOSI1 HAL_GPIO_WritePin(LCD_PORT, MOSI, GPIO_PIN_SET)
#define LCD_MOSI0 HAL_GPIO_WritePin(LCD_PORT, MOSI, GPIO_PIN_RESET)
Підключення пінів прописане в файлі pcd8544.h :
#define SCLK GPIO_PIN_0
#define MOSI GPIO_PIN_1
#define DC GPIO_PIN_2
#define RST GPIO_PIN_3
#define SCE GPIO_PIN_4
#define LCD_PORT GPIOA
На початку головного цикла вставимо "заставочку". А так будемо на екрані відслідковувати стан світлодіодів LED-ON та LED-OFF . Саміж світлодіоди будуть вмикатись кнопками. Поїхали...
Реалізація. Алгоритм такий
- спрацьовує зовнішнє переривання від кнопки;
-в обробнику переривання EXTI4_15_IRQHandler вимикаємо зовнішнє переривання ЕХТІ та вмикаємо таймер ТІМ14;
-таймер відпрацьовує 100 мс і в обробнику TIM14_IRQHandler провіряє. яка кнопка підтянута до "+";
-в залежності від натисненої кнопки засвічується свій світлодіод та виводиться відповідний напис на екрані дисплея;
Нас цікавить файл stm32f0xx_it.с , тут прописується що ми будемо робити в перериванні.
Перша функція обробник переривання EXTI4_15_IRQHandler , робимо те про, що ми писали вище:
HAL_NVIC_DisableIRQ(EXTI4_15_IRQn); // вимикаємо ЕХТІ
HAL_TIM_Base_Start_IT(&htim14); // вмикаємо ТІМ14
Наступна функція оброник перериваня TIM14_IRQHandler
HAL_TIM_Base_Stop_IT(&htim14); // вимикаємо ТІМ14
// ===== тут наш код обробки=========
HAL_NVIC_EnableIRQ(EXTI4_15_IRQn); // вмикаємо ЕХТІ
От і все. Компілюємо проект , прошиваємо МК . Все працює бездоганно.
Сам проект в Keil 5 - http://radiomanoff.at.ua/load/stm32f0xx_button/1-1-0-39
Та невеличке відео, за створення якого дуже дякую моєму сину Ярославу....
|