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

В предыдущей статье мы рассматривали простенькую программу, которая мигает светодиодом. Немного модифицируем ее и попробуем разобраться, как настроить выводы микроконтроллера для работы на вход и выход. 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;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;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);

Программа будет меньше по размеру. Так обычно и делают. Включают тактирование всем модулям, настраивают все прерывания и так далее. Это правильный путь к оптимизации программы. Но на этапе изучения микроконтроллера, для наглядности, я буду писать именно так, как в этом примере. Чтобы было ясно: что и зачем надо включить и как настроить, чтобы настроить ту или иную периферию. Это будет не всегда рационально, но всегда понятно.

Желаю успехов!

Смотри также:

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

  • Илья говорить:

    Добрый, а если пользоваться CubeMX то впринципе не нужно самому прописывать конфигурацию выводов, так же с тактированием?

    • andre говорить:

      CubeMX – это генератор проектов. В нем можно мышкой потыкать и, в принципе, избавить себя от инициализации периферии. Но дальше все равно Вам придется программировать и разбираться с библиотекой HAL.

      • Илья говорить:

        ну да, если захочется добавить пин, или доп устройство повесить скажем на uart, не полезешь же в cube пересобирать проект

Translate
Архіви

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