GPIO STM32 |
![]() |
Добавил(а) microsin |
Вы можете настроить выводы микроконтроллера в режим входа или выхода, перевести выход в низкий (0V) или высокий (3.3V) уровень, выбрать внутренние подтягивающие резисторы (pull resistors), выбрать тип выхода и скорость его переключения. В этой статье будут показаны примеры работы с GPIO микроконтроллера STM32F103RBT6 на оценочной плате STM32F103R-BOARD [1] с помощью функций CMSIS [3]. Непонятные термины и сокращения см. в статье [2]. [Тактирование GPIO] Чтобы можно было работать с выводом, нужно разрешить его тактирование. Это делается с помощью программирования блока RCC (Reset and Clock Control). У микроконтроллера STM32F103xxx все выводы GPIO обслуживаются шиной AHB2. В примерах мы будем использовать порты GPIOB и GPIOC, потому что на плате [1] светодиоды D1 и D2 подключены к ножкам портов PB9 и PB8, а кнопки S2 и S3 к PC0 и PC1. Мы можем разрешить тактирование следующим образом: //RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOB, DISABLE);
//RCC_APB2PeriphResetCmd(RCC_APB2Periph_GPIOC, DISABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
Примечание: в примерах от OLIMEX перед разрешением тактов почему-то тактирование запрещалось, однако на практике оказалось, что это делать не нужно, и поэтому первые строчки я закомментировал. Подробнее про настройку тактирования при первоначальном старте микроконтроллера см. статью [4]. [Настройка GPIO] На следующем шаге необходимо подготовить структуру опций порта GPIO_InitTypeDef, чтобы правильно настроить его поведение. Если Вы подключили библиотеку GPIO к проекту (это файлы stm32f10x_gpio.c и stm32f10x_gpio.h), то можете сделать это следующим образом: // Переменная для настройки опций порта GPIO:
GPIO_InitTypeDef GPIO_InitDef;
Опции порта настраиваются через 3 поля структуры GPIO_InitTypeDef: GPIO_Pin: выбор ножек, для которых будут устанавливаться опции (битовая маска). Каждое из перечисленных выше полей имеет свой набор опций. GPIO_Pin. Ниже показано использование поля GPIO_Pin, которое выбирает настраиваемые выводы портов. // Применение настроек только к порту GPIO_Pin_8: GPIO_InitDef.GPIO_Pin = GPIO_Pin_8; // Если Вы хотите одинаково настроить несколько выводов портов,
// то в поле GPIO_Pin записывается соответствующая маска. Например,
// порты GPIO_Pin_8 и GPIO_Pin_9 будут настроены одинаково: GPIO_InitDef.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9; // Следующая настройка задает одинаковые опции ко всем выводам портов: GPIO_InitDef.GPIO_Pin = GPIO_Pin_All; GPIO_Speed. Поле выбирает скорость работы GPIO (100, 50, 25 или 2 МГц). GPIO_Speed_100MHz GPIO_Mode. Это поле выбирает режим работы порта. GPIO_Mode_AIN: аналоговый вход (АЦП). После того, как поля структуры GPIO_InitDef настроены должным образом, нужно вызывать функцию GPIO_InitDef со ссылкой на эту структуру. Пример функции, которая настраивает порты PB9 и PB8 для управления светодиодами D1 и D2 платки [1]: #define LEDSPORT GPIOB
#define LED1_PIN GPIO_Pin_9
#define LED2_PIN GPIO_Pin_8
inline void LEDs_init (void) { // Структура для настройки портов: GPIO_InitTypeDef GPIO_InitStructure; // Разрешение тактирования GPIOB: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE); // Инициализация полей структуры: GPIO_InitStructure.GPIO_Pin = LED1_PIN | LED2_PIN;// ножки портов PB9 и PB8 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; // двухтактный драйвер GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; // скорость 50 МГц // Настройка портов светодиодов. GPIO_Init(LEDSPORT, &GPIO_InitStructure); } Примечание: в этом примере выходы портов PB9 и PB8 настроены как двухтактные GPIO_Mode_Out_PP, хотя можно было использовать драйвер с общим стоком GPIO_Mode_Out_OD (потому что светодиоды D1 и D2 подключены к +3.3V). [Управление выходами GPIO] Переключать выход в лог. 0 или в лог. 1 может функция GPIO_WriteBit: void GPIO_WriteBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, BitAction BitVal); Первый параметр задает группу ножек портов (для светодиодов D1 и D2 это GPIOB), второй параметр задает маску для управляемых портов, третий параметр задает тип действия с портами (сброс или установка). // Перевод в лог. 0 вывода порта светодиода D1 (светодиод загорится):
GPIO_WriteBit(LEDSPORT, LED1_PIN, Bit_RESET);
// Перевод в лог. 1 вывода порта светодиода D1 (светодиод погаснет): GPIO_WriteBit(LEDSPORT, LED1_PIN, Bit_SET); [Опрос входов GPIO] На платке [1] есть две кнопки S2 и S3, подключенные к ножкам портов PC0 и PC1 соответственно. Ниже показано, как сконфигурировать их на вход с разрешением верхнего подтягивающего резистора (нажатие на кнопку будет переводить уровень входа с лог. 1 на лог. 0). inline void S2S3_init (void) { GPIO_InitTypeDef GPIO_InitStructure; // Разрешение тактирования GPIOC: RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE); // Настройка полей структуры для кнопок: GPIO_InitStructure.GPIO_Pin = S2_PIN | S3_PIN; // ножки кнопок GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; // Входы с pull-up резистором GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;// скорость работы 2 МГц // Инициализация входов кнопок: GPIO_Init(BUTTONSPORT, &GPIO_InitStructure); } // Макрос, возвращающий 1, если кнопка нажата:
#define PRESSED(x) GPIO_ReadInputDataBit(BUTTONSPORT,x)?0:1
Прочитать логический уровень цифрового входа можно функцией GPIO_ReadInputDataBit: uint8_t GPIO_ReadInputDataBit(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin); Первый параметр задает группу ножек портов (для кнопок S2 и S3 это GPIOC), второй задает маску, определяющую конкретный опрашиваемый вывод порта. Пример чтения уровня кнопки S2: if (0 == GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_0)) { // Кнопка нажата, зажжем светодиод D1: GPIO_WriteBit(GPIOB, GPIO_Pin_9, Bit_RESET); } else { // Кнопка отпущена, погасим светодиод D1: GPIO_WriteBit(GPIOB, GPIO_Pin_9, Bit_SET); } [Ссылки] 1. STM32F103R-BOARD. |