3. STM32. Програмування STM32F103. GPIO
У попередній статті ми використовували простеньку програму, яка блимає світлодіодом. Трохи модифікуємо її і спробуємо розібратися, як налаштувати виводи мікроконтролера для роботи на вхід і вихід. C13 налаштуємо як вихід. До нього підключений світлодіод на тестовій платі. B0 налаштуємо на вхід і підключимо до нього кнопку. У натиснутому положенні кнопка має замикати ногу B0 на землю.
Код програми
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
int main(void)
{
int i;
GPIO_InitTypeDef GPIO_InitStructure;
/* Initialize LED which connected to PC13 */
// Enable PORTC Clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
/* Configure the GPIO_LED pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
//GPIO_SetBits(GPIOC, GPIO_Pin_13); // Set C13 to High level ("1")
GPIO_ResetBits(GPIOC, GPIO_Pin_13); // Set C13 to Low level ("0")
/* Initialize Button input PB0 */
// Enable PORTB Clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* Configure the GPIO_BUTTON pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
while (1) {
if (GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0) != 0) {
/* Toggle LED which connected to PC13*/
GPIOC->ODR ^= GPIO_Pin_13; // Invert C13
/* delay */
for(i=0;i<0x100000;i++);
/* Toggle LED which connected to PC13*/
GPIOC->ODR ^= GPIO_Pin_13;
/* delay */
for(i=0;i<0x100000;i++);
}
else {
GPIO_SetBits(GPIOC, GPIO_Pin_13);
}
}
}
Перш за все роздивимось, що ми інклудимо:
#include "stm32f10x.h"
#include "stm32f10x_gpio.h"
#include "stm32f10x_rcc.h"
stm32f10x.h - стосується конкретної серії мікроконтролера; stm32f10x_gpio.h - стосується GPIO виводів портів, з чим ми і будемо працювати; stm32f10x_rcc.h - А це що таке? Справа у тому, що у STM32 усі модулі (GPIO, ADC, EXTI, USART, I2C, SPI, та інші) після включення мікроконтролера відключені від тактування. І ми маємо програмно вмикати тактування тій периферії, яку плануємо використовувати. Крім того, ми можемо налаштувати частоту тактування деяких модулів окремо. Докладно про тактування буде у наступній статті.
Зараз нам треба засвоїти, що перед тим, як використовувати чи то порт, чи то інтерфейс, чи то який-небудь модуль, треба подати на нього тактування. У stm32f10x_rcc.h описані функції, які керують тактуванням.
Дивимося у програмі рядок, який вмикає тактування порту GPIOC:
/* Initialize LED which connected to PC13 */
// Enable PORTC Clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
Далі виконуємо налаштування вивода порта. В нашому випадку PC13 (на тестовій платі до нього підключений світлодіод) налаштовуємо як вихід. Налаштування виконуються через структуру GPIO_InitTypeDef.
/* Configure the GPIO_LED pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &GPIO_InitStructure);
Нарешті можемо задати високий чи низький рівень на виході PC13:
//GPIO_SetBits(GPIOC, GPIO_Pin_13); // Set C13 to High level ("1")
GPIO_ResetBits(GPIOC, GPIO_Pin_13); // Set C13 to Low level ("0")
Коли задаємо високий рівень, світлодіод не горить, низький - горить.
Далі виконуємо конфігурацію PB0. Він буде працювати як вхід з підтяжкою до "1" (GPIO_Mode_IPU). Тобто, коли кнопка не натиснута (нога PB0 висить у повітрі), на вході PB0 буде "1".
/* Initialize Button input PB0 */
// Enable PORTB Clock
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
/* Configure the GPIO_BUTTON pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
Стан кнопки опитується функцією:
GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0)
Програма опитує стан кнопки і блимає світлодіодом тільки коли кнопка не натиснута, тобто коли на вході B0 високий рівень.
Підключимо замість кнопки датчик руху HC-SR501. Зверніть увагу, живлення датчика 5В. Тепер світлодіод буде блимати, коли сенсор руху зафіксує рух. Вітаю! Тепер можна трохи погратися: помахати перед сенсором руху руками, поганяти перед ним кота, собаку, інших домашніх тварин.
Пам`ятка
Структура GPIO_InitTypeDef для налаштування виводів порта має наступні параметри:- GPIO_Pin - номера пінів, які конфігуруються. Приклад для декількох пінів: GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_2;
- GPIO_Speed - задає швидкість для обраних пінів. Може мати наступні значення: GPIO_Speed_10MHz, GPIO_Speed_2MHz, GPIO_Speed_50MHz
- GPIO_Mode - задає режим роботи пінів. Може мати наступні значення:
- GPIO_Mode_AIN — аналоговий вхід;
- GPIO_Mode_IN_FLOATING — вхід без підтяжки (Float)
- GPIO_Mode_IPD — вхід з підтяжкою до землі (Pull-down)
- GPIO_Mode_IPU — вхід з підтяжкою до живлення (Pull-up)
- GPIO_Mode_Out_OD — вихід з відкритим стоком (Open Drain)
- GPIO_Mode_Out_PP — вихід з двома станами (Push-Pull)
- GPIO_Mode_AF_OD — вихід з відкритим стоком для альтернативних функцій (Alternate Function). Використовується коли виводи керуються периферією, яка може бути задіяна на цьому виводі. Наприклад USART, I2C тощо.
- GPIO_Mode_AF_PP — те саме що і перед цим, але з двома станами.
Зауваження
Ви могли звернути увагу, що у програмі ми двічі викликаємо функцію RCC_APB2PeriphClockCmd для різних портів:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
Це можна зробити і один раз таким чином:
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC | RCC_APB2Periph_GPIOB, ENABLE);
Програма буде менша за розміром. Так зазвичай і роблять. Вмикають тактування усім модулям, налаштовують усі переривання і так далі. Це правильний шлях до оптимізації програми. Але на етапі вивчення мікроконтролера, тільки задля наочності, я буду писати саме так, як у цьому прикладі. Щоб було ясно: що і за чим треба увімкнути і як налаштувати, щоб налаштувати ту чи іншу периферію. Це буде не завжди раціонально, але завжди зрозуміло.
Бажаю успіхів!
Дивись також:
- 1. STM32. Програмування STM32F103. Тестова плата. Прошивка через UART та через ST-Link
- 2. STM32. Програмування. IDE для STM32
- 3. STM32. Програмування STM32F103. GPIO
- 4. STM32. Програмування STM32F103. Тактування
- 5. STM32. Програмування STM32F103. USART
- 6. STM32. Програмування STM32F103. NVIC
- 7. STM32. Програмування STM32F103. ADC
- 8. STM32. Програмування STM32F103. DMA
- 9. STM32. Програмування STM32F103. TIMER
- 10. STM32. Програмування STM32F103. TIMER. Захоплення сигналу
- 11. STM32. Програмування STM32F103. TIMER. Encoder
- 12. STM32. Програмування STM32F103. TIMER. PWM
- 13. STM32. Програмування STM32F103. EXTI
- 14. STM32. Програмування STM32F103. RTC
- 15. STM32. Програмування STM32F103. BKP
- 16. STM32. Програмування STM32F103. Flash
- 17. STM32. Програмування STM32F103. Watchdog
- 18. STM32. Програмування STM32F103. Remap
- 19. STM32. Програмування STM32F103. I2C Master
- 20. STM32. Програмування STM32F103. I2C Slave
- 21. STM32. Програмування STM32F103. USB
- 22. STM32. Програмування STM32F103. PWR
- 23. STM32. Програмування STM32F103. Option bytes
- 24. STM32. Програмування STM32F103. Bootloader
- STM32. Скачати приклади
- System Workbench for STM32 Інсталяція на Ubuntu
- Keil uVision5 – IDE для STM32
- IAR Workbench – IDE для STM32
- Керування безколекторним двигуном постійного струму (BLDC) за допомогою STM32
- Керування PMSM за допомогою STM32
Всередині нескінченного циклу код поплив, ну і зайве треба видалити. А можливо краще в цьому прикладі блимати світлодіодом не toggle, а саме "підняти, почекати, опустити, почекати". Так наглядніше буде і завжди під рукою команди для "підняти" та "опустити".
"stm32f10x.h – стосується GPIO виводів портів, з чим ми і будемо працювати;" - потрібно виправити помилку.
Дякую. Виправив.
В циклі красоту наведіть будь ласка. Там зайвий код, про який я вде писав і в попередній статті вже пофіксили. І окріми того сам код поплив (пару переносів строки не вистачає)
Коли вмикати переферію не застосовуючи функцію RCC_APB2PeriphClockCmd. Треба робити затримку після вмикання переферії, чи відразу можна перейти до інших маніпуляцій з портом?
GPIO_InitTypeDef GPIO_InitStructure; Я так розумію що це "GPIO_InitStructure" створення указника на структуру "GPIO_InitTypeDef". У даному разі нема значення як налаштовані всі інші пині порта. Якщо потрібно налаштувати один пін з порта, то указник треба стровати якось так: "GPIOC_InitPinLed"?
#define GPIO_Pin_13 ((uint16_t)0x2000) /*!< Pin 13 selected */ Для зручності написання коду можливо міняти ці дефайни в проєкті? Або створювати свої з тими значеннями зсунення біт?
Можете назвати і GPIOC_InitPinLed - як завгодно. Та коли на цьому ж порту доведеться додати, скажімо, кнопки, тоді доведеться знов якось перейменувати. Для зручності можна робити так: #define LED_PIN GPIO_Pin_13 І далі у коді використовувати LED_PIN, а не GPIO_Pin_13. GPIO_Pin_13 чіпати не треба. Його зроблено, щоб полегшити життя і не морочити собі голову з бітами.
Недавні записи
- Text to speech. Українська мова
- LCD Display ST7567S (IIC)
- Розпізнавання мови (Speech recognition)
- Selenium
- Комп'ютерний зір (Computer Vision)
- Деякі думки про точність вимірювань в електроприводі
- Датчики Холла 120/60 градусів
- Модуль драйверів напівмосту IGBT транзисторів
- Драйвер IGBT транзисторів на A316J
- AS5600. Варіант встановлення на BLDC мотор
Tags
docker sensors rtc led timer wifi remap sms css websocket mongodb bme280 rfid bluetooth esp8266 nodemcu bkp piezo bmp280 i2c mpu-6050 encoder examples avr brushless ngnix nvic displays bldc java-script pmsm barometer pwm lcd ethernet stm32 raspberry-pi capture usart gpio exti atmega meteo solar smd dma adc eeprom eb-500 flask python ssd1306 uart options flash mpx4115a html gps st-link 3d-printer servo dc-dc foc git books battery hih-4000 watchdog dht11 web tim programmator ssd1331 mpu-9250 usb rs-232 motor max1674 soldering
Архіви