STM32.GPIO Использование StdPeriph_Lib

Для работы с портами ввода/вывода посредством стандартных библиотечных ф-й понадобятся следующие файлы:

  • stm32f10x_gpio.h  и  stm32f10x_gpio.c – для работы с портами;
  • stm32f10x_rcc.c и stm32f10x_rcc.h – для управления тактированием портов.

Имеется ряд функций для работы с портами. Ниже приводится описание каждой.

 

GPIO_Init – инициализация порта или его отдельных пинов.

void GPIO_Init (GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct )

Чтобы разобраться с работой этой функции, необходимо ввести понятие инициализационной структуры. Именно эта структура передается функции в качестве второго аргумента. Данная структура имеет следующий вид:

typedef struct 
{
  uint16_t GPIO_Pin;              //номер вывода или группы выводов, которые инициализируем
  GPIOSpeed_TypeDef GPIO_Speed;   //задает частоту сигнала, на которой работает вывод
  GPIOMode_TypeDef  GPIO_Mode;    //задает режим работы вывода
} GPIO_InitTypeDef ;

Немного подробнее о полях инициализационной структуры.

Поле GPIO_Mode может принимать следующие значения:

  • GPIO_Mode_AIN                — аналоговый вход;
  • GPIO_Mode_IN_FLOATING  — цифровой  вход, третье состояние;
  • GPIO_Mode_IPD                — цифровой вход, подтяжка к земле;
  • GPIO_Mode_IPU                — цифровой вход, подтяжка к плюсу питания;
  • GPIO_Mode_Out_OD          — выход общего назначения, открытый сток;
  • GPIO_Mode_Out_PP           — симметричный выход общего назначения;
  • GPIO_Mode_AF_OD           -  выход альтернативной ф-ии, открытый сток;
  • GPIO_Mode_AF_PP            -  симметричный выход альтернативной ф-ии

Поле GPIO_Speed задает скорость работы вывода настроенного как выход и может принимать следующие значения:

  • GPIO_Speed_10MHz
  • GPIO_Speed_2MHz
  • GPIO_Speed_50MHz

Поле GPIO_Pin определяет номер вывода, который инициализируем. Может принимать следующие значения:

  • GPIO_Pin_0
  • GPIO_Pin_1
  • GPIO_Pin_2
  • GPIO_Pin_3
  • GPIO_Pin_4
  • GPIO_Pin_5
  • GPIO_Pin_6
  • GPIO_Pin_7
  • GPIO_Pin_8
  • GPIO_Pin_9
  • GPIO_Pin_10
  • GPIO_Pin_11
  • GPIO_Pin_12
  • GPIO_Pin_13
  • GPIO_Pin_14
  • GPIO_Pin_15
  • GPIO_Pin_All

Я думаю, что этот список в пояснении не нуждается, за исключением последнего варианта — GPIO_Pin_All. Данное значение присваивается, когда необходимо инициализировать весь порт.

Рассмотрим пример использования ф-ии GPIO_Init. Предположим, необходимо настроить вывод 2 порта PORTB для работы в качестве симметричного вывода общего назначения с максимальной частотой переключения 50 МГц:

GPIO_InitTypeDef  GPIO_InitStructure;                 //обьявляем структуру
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //включаем тактирование порта B
//заполняем поля структуры согласно поставленной задаче
GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;           //задаем номер вывода
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;     //режим работы
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;     //скорость 
GPIO_Init(GPIOB, &GPIO_InitStructure);                //вызов функции инициализации

В качестве аргумента функции выступает имя порта и указатель на инициализационную структуру.

Если нужно одновременно инициализировать несколько выводов порта, то необходимо переменной GPIO_InitStructure.GPIO_Pin присвоить соответствующее значение. Например, необходимо настроить одинаково вывода 2 и 3. Это будет выглядеть следующим образом:

GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3;

GPIO_WriteBit – для управления выводами порта (установка в единицу или ноль)

void GPIO_WriteBit ( GPIO_TypeDef * GPIOx, uint16_t GPIO_Pin, BitAction BitVal )
  • GPIOx – имя порта, к которому обращаемся (х может принимать значение от A до G, зависит от   конкретного контроллера);
  • GPIO_Pin – определяет номера вывода (или группы выводов), которым управляем;
  • BitVal – состояние, в которое нужно перевести вывод. Может принимать значения: Bit_RESET или Bit_SET;

Пример использования данной функции:

GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_SET);      //установить GPIOB.2
GPIO_WriteBit(GPIOB, GPIO_Pin_2, Bit_RESET);    //сбросить   GPIOB.2

GPIO_ResetBits, GPIO_SetBits – сброс и установка выбранных битов порта

void GPIO_ResetBits(GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)  //сброс выбранного вывода порта
void GPIO_SetBits  (GPIO_TypeDef * GPIOx,uint16_t GPIO_Pin)  //установка выбранного вывода порта

GPIO_ReadInputDataBit  — чтение состояния выбранного вывода порта

uint8_t GPIO_ReadInputDataBit  (GPIO_TypeDef *  GPIOx, uint16_t  GPIO_Pin)

С помощью аргумента GPIOx задается имя порта, а аргумента GPIO_Pin – номер вывода порта. Результат функции – состояние вывода порта (0 или 1)

GPIO_ReadInputData — чтение состояния выбранного порта

uint16_t GPIO_ReadInputData  (GPIO_TypeDef *  GPIOx)

В отличии от предыдущей команды, позволяет прочитать все 16 разрядов выбранного порта

 

GPIO_ReadOutputDataBit   — чтение  состояния одного бита регистра данных порта

GPIO_ReadOutputData — чтение состояния всего регистра данных порта

 

Приведенные выше функции являются одними из наиболее используемых. На основании их напишем фрагмент программы, которая посредством кнопки, подключенной между GPIOA.2 и землей, управляет светодиодом, подключенным между GPIOB.6 и землей через ограничительный резистор. При нажатии на кнопку состояние светодиода должно меняться на противоположное.

GPIO_InitTypeDef  GPIO_InitStructure;                 //обьявляем инициализационную структуру
//инициализировать вывод порта, к которому подключена кнопка
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); //включаем тактирование порта A
GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_2;           //задаем номер вывода
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_IPU;        //цифровой вход, подтяжка к плюсу
GPIO_Init(GPIOA, &GPIO_InitStructure);                //вызов функции инициализации
//инициализировать вывод порта, к которому подключен светодиод
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); //включаем тактирование порта B
GPIO_InitStructure.GPIO_Pin   = GPIO_Pin_6;           //задаем номер вывода
GPIO_InitStructure.GPIO_Mode  = GPIO_Mode_Out_PP;     //симметричный выход общего назначения
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;      //скорость 
GPIO_Init(GPIOB, &GPIO_InitStructure);                //вызов функции инициализации
 
//бесконечный цикл, в котором проверяется состояние кнопки
while(1)
{
  if(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)==0)      //нажата кнопка
  {
 
    //меняем состояние светодиода на противоположное
    if(GPIO_ReadOutputDataBit(GPIOB,GPIO_Pin_6)) GPIO_ResetBits(GPIOB,GPIO_Pin_6);
    else                                         GPIO_SetBits  (GPIOB,GPIO_Pin_6);
 
    delay_ms(100);                                    //задержка против дребезга
    while(GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_2)==0);//ждать отпускания кнопки
    delay_ms(100);                                    //задержка против дребезга
  }
}

Есть другой, более "красивый" способ инвертирования состояния выхода:

GPIOB->ODR ^= GPIO_Pin_6;

Приведенный выше пример ожидания нажатия кнопки является далеко не оптимальным. Было бы правильно организовать проверку состояния вывода в обработчике прерывания таймера. Цель этого примера – проиллюстрировать использование библиотечных ф-й для работы с портами и не более того.

 

Рассмотрим оставшиеся функции.

GPIO_PinLockConfig – защита выбранной конфигурации вывода порта

 void GPIO_PinLockConfig  (GPIO_TypeDef *  GPIOx, uint16_t  GPIO_Pin)

После вызова этой функции конфигурация выбранного вывода порта будет защищена от дальнейших изменений. Отключение защиты произойдет только после системного сброса.

 

GPIO_PinRemapConfig – управляет подключением периферийных устройств к альтернативным выводам

По умолчанию за периферийными устройствами закреплены определенные выводы контроллера. Например, сигналы RX и TX модуля USART1 по умолчанию подключены к выводам PA10, PA9 соответственно. Но есть возможность подключить эти сигналы к другим выводам – PB7, PB6. Рассматриваемая ф-я как раз позволяет выполнять подключение к основным выводам или альтернативным. Она имеет следующий вид:

void GPIO_PinRemapConfig  (uint32_t GPIO_Remap, FunctionalState NewState)

GPIO_Remap указывает на  периферийное устройство, подключение которого будем переназначать.

NewState определяет действие: ENABLE – подключить к альтернативному набору выводов, DISABLE – вернуться к основному набору.

Например, чтобы подключить USART1 к альтернативным выводам необходимо выполнить следующее:

GPIO_PinRemapConfig (GPIO_Remap_USART1,ENABLE);

Приведу имена GPIO_Remap для некоторых периферийных устройств:

  • GPIO_Remap_SPI1
  • GPIO_Remap_I2C1
  • GPIO_Remap_USART1
  • GPIO_Remap_USART2
  • GPIO_PartialRemap_USART3
  • GPIO_FullRemap_USART3
  • GPIO_PartialRemap_TIM1
  • GPIO_FullRemap_TIM1
  • GPIO_PartialRemap1_TIM2
  • GPIO_FullRemap_TIM2

Полный список этих имен находится в файле stm32f10x_gpio.h

О первоисточнике можете узнать тут