сайт для палких паяльників

3. STM32. Программирование STM32F103. GPIO
(на русском языке)

У попередній статті ми використовували простеньку програму, яка блимає світлодіодом. Трохи модифікуємо її і спробуємо розібратися, як налаштувати виводи мікроконтролера для роботи на вхід і вихід. C13 налаштуємо як вихід. До нього підключений світлодіод на тестовій платі. B0 налаштуємо на вхід і підключимо до нього кнопку. У натиснутому положенні кнопка має замикати ногу B0 на землю.

STM32F103_GPIO

Код програми

#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, &amp;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, &amp;GPIO_InitStructure);

Стан кнопки опитується функцією:

GPIO_ReadInputDataBit(GPIOB, GPIO_Pin_0)

Програма опитує стан кнопки і блимає світлодіодом тільки коли кнопка не натиснута, тобто коли на вході B0 високий рівень.

Підключимо замість кнопки датчик руху HC-SR501. Зверніть увагу, живлення датчика 5В. Тепер світлодіод буде блимати, коли сенсор руху зафіксує рух. Вітаю! Тепер можна трохи погратися: помахати перед сенсором руху руками, поганяти перед ним кота, собаку, інших домашніх тварин.

DSCN6944 DSCN6932

Пам’ятка

Структура 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);

Програма буде менша за розміром. Так зазвичай і роблять. Вмикають тактування усім модулям, налаштовують усі переривання і так далі. Це правильний шлях до оптимізації програми. Але на етапі вивчення мікроконтролера, тільки задля наочності, я буду писати саме так, як у цьому прикладі. Щоб було ясно: що і за чим треба увімкнути і як налаштувати, щоб налаштувати ту чи іншу периферію. Це буде не завжди раціонально, але завжди зрозуміло.

Бажаю успіхів!

Дивись також:

4 комментария: 3. STM32. Програмування STM32F103. GPIO

  • Сергій говорить:

    Всередині нескінченного циклу код поплив, ну і зайве треба видалити. А можливо краще в цьому прикладі блимати світлодіодом не toggle, а саме “підняти, почекати, опустити, почекати”. Так наглядніше буде і завжди під рукою команди для “підняти” та “опустити”.

  • Сергій говорить:

    “stm32f10x.h – стосується GPIO виводів портів, з чим ми і будемо працювати;” – потрібно виправити помилку.

      • Сергій говорить:

        В циклі красоту наведіть будь ласка. Там зайвий код, про який я вде писав і в попередній статті вже пофіксили. І окріми того сам код поплив (пару переносів строки не вистачає)

Translate
Архіви

© 2011-2017 Андрій Корягін, Кременчук - Київ, Україна