Дата поста: 05-02-2018
Недавно коллега меня подсадил на идею создания умного дома, я даже успел заказать себе десятки разных датчиков. Встал вопрос о выборе Микроконтроллера (далее МК) или платы. После некоторых поисков нашёл несколько вариантов. Среди них были и Arduino (включая его клоны, один из которых себе заказал ради того, чтобы просто побаловаться) и Launchpad, но всё это избыточно и громоздко (хотя в плане программирования гораздо проще, но тему холиваров поднимать не буду, у каждого свои вкусы). В итоге решил определяться не с готовой платой, а взять только МК и делать всё с нуля. В итоге выбирал между Atmel ATtiny (2313), Atmel ATmega (решил отказаться т.к. не смог найти за адекватные деньги), STM32 (Cortex на ядре ARM). С тинькой я уже успел побаловаться, так что взял себе STM32VL-Discovery. Это можно назвать вступлением к циклу статей по STM32. Оговорюсь сразу, автором большинства этих статей буду являться не я, т.к. сам только познаю, здесь я публикую их в первую очередь для себя, чтоб удобнее было искать если что-то забуду. И так поехали!
Общие сведения
Микроконтроллеры семейства STM32 содержат в своём составе до семи 16-разрядных портов ввода-вывода c именами от PORTA до PORTG. В конкретной модели микроконтроллера без исключений доступны все выводы портов, общее количество которых зависит от типа корпуса и оговорено в DataSheet на соответствующее подсемейство.
Для включения в работу порта x необходимо предварительно подключить его к шине APB2 установкой соответствующего бита IOPxEN в регистре разрешения тактирования периферийных блоков RCC_APB2ENR:
RCC->APB2ENR |= RCC_APB2ENR_IOPxEN; // Разрешить тактирование PORTx.
Управление портами STM32 осуществляется при помощи наборов из семи 32-разрядных регистров:
- GPIOx_CRL, GPIOx_CRH – задают режимы работы каждого из битов порта в качестве входа или выхода, определяют конфигурацию входных и выходных каскадов.
- GPIOx_IDR – входной регистр данных для чтения физического состояния выводов порта x.
- GPIOx_ODR– выходной регистр осуществляет запись данных непосредственно в порт.
- GPIOx_BSRR – регистр атомарного сброса и установки битов порта.
- GPIOx_BSR – регистр сброса битов порта.
- GPIOx_LCKR – регистр блокировки конфигурации выводов.
Режимы работы выводов GPIO
Режимы работы отдельных выводов определяются комбинацией битов MODEy[1:0] и CNFy[1:0] регистров GPIOx_CRL и GPIOx_CRH (здесь и далее: x-имя порта, y- номер бита порта).
GPIOx_CRL — регистр конфигурации выводов 0...7 порта x:
Структура регистра GPIOx_CRH аналогична структуре GPIOx_CRL и предназначена для управления режимами работы старших выводов порта (биты 8...15).
Биты MODEy указанных регистров определяют направление вывода и ограничение скорости переключения в режиме выхода:
- MODEy[1:0] = 00: Режим входа (состояние после сброса);
- MODEy[1:0] = 01: Режим выхода, максимальная скорость – 10МГц;
- MODEy[1:0] = 10: Режим выхода, максимальная скорость – 2МГц;
- MODEy[1:0] = 11: Режим выхода, максимальная скорость – 50МГц.
Биты CNF задают конфигурацию выходных каскадов соответствующих выводов:
в режиме входа:
- CNFy[1:0] = 00: Аналоговый вход;
- CNFy[1:0] = 01: Вход в третьем состоянии (состояние после сброса);
- CNFy[1:0] = 10: Вход с притягивающим резистором pull-up (если PxODR=1) или pull-down (если PxODR=0);
- CNFy[1:0] = 11: Зарезервировано.
в режиме выхода:
- CNFy[1:0] = 00: Двухтактный выход общего назначения;
- CNFy[1:0] = 01: Выход с открытым стоком общего назначения;
- CNFy[1:0] = 10: Двухтактный выход с альтернативной функцией;
- CNFy[1:0] = 11: Выход с открытым стоком с альтернативной функцией.
С целью повышения помехоустойчивости все входные буферы содержат в своём составе триггеры Шмидта. Часть выводов STM32, снабженных защитными диодами, соединёнными с общей шиной и шиной питания, помечены в datasheet как FT (5V tolerant) — совместимые с напряжением 5 вольт.
Защита битов конфигурации GPIO
Для защиты битов в регистрах конфигурации от несанкционированной записи в STM32 предусмотрен регистр блокировки настроек GPIOx_LCKR
GPIOx_LCKR — регистр блокировки настроек вывода порта:
Для защиты настроек отдельного вывода порта необходимо установить соответствующий бит LCKy. После чего осуществить последовательную запись в разряд LCKK значений "1” — "0” — "1” и две операции чтения регистра LCKR, которые в случае успешной блокировки дадут для бита LCKK значения "0” и "1” . Защита настроечных битов сохранит своё действие до очередной перезагрузки микроконтроллера.
Файл определений для периферии микроконтроллеров STM32 stm32f10x.h
определяет отдельные группы регистров, объединённые общим функциональным назначением (в том числе и GPIO), как структуры языка Си, а сами регистры как элементы данной структуры. Например:
GPIOC->BSRR – регистр BSRR установки/сброса порта GPIOC.
Воспользуемся определениями из файла stm32f10x.h для иллюстрации работы с регистрами ввода-вывода микроконтроллера STM32F100RB установленного в стартовом наборе STM32VLDISCOVERY:
#include "stm32F10x.h"
u32 tmp;
int main (void)
{
RCC->APB2ENR |= RCC_APB2ENR_IOPCEN; // Разрешить тактирование PORTC.
GPIOC->CRH |= GPIO_CRH_MODE8; // Вывод светодиода LED4 PC8 на выход.
GPIOC->CRH &=~GPIO_CRH_CNF8; // Двухтактный выход на PC8.
GPIOC->CRH |= GPIO_CRH_MODE9; // Вывод светодиода LED3 PC9 на выход.
GPIOC->CRH &=~GPIO_CRH_CNF9; // Двухтактный выход на PC9.
GPIOA->CRL&=~GPIO_CRL_MODE0; // Кнопка "USER" PA0 - на вход.
// Заблокировать настройки выводов PC8, PC9.
GPIOC->LCKR = GPIO_LCKR_LCK8|GPIO_LCKR_LCK9| GPIO_LCKR_LCKK;
GPIOC->LCKR = GPIO_LCKR_LCK8|GPIO_LCKR_LCK9;
GPIOC->LCKR = GPIO_LCKR_LCK8|GPIO_LCKR_LCK9| GPIO_LCKR_LCKK;
tmp=GPIOC->LCKR; tmp=GPIOC->LCKR;
}
Запись и чтение GPIO
Для записи и чтения портов предназначены входной GPIOx_IDR и выходной GPIOx_ODR регистры данных.
Запись в выходной регистр ODR порта настроенного на вывод осуществляет установку выходных уровней всех разрядов порта в соответствии с записываемым значением. Если вывод настроен как вход с подтягивающими резисторами, состояние соответствующего бита регистра ODR активирует подтяжку вывода к шине питания (pull-up, ODR=1) или общей шине микроконтроллера (pull-down, ODR=0).
Чтение регистра IDR возвращает значение состояния выводов микроконтроллера настроенных как входы:
// Если кнопка нажата (PA0=1), установить биты порта C, иначе сбросить.
if (GPIOA->IDR & GPIO_IDR_IDR0) GPIOC->ODR=0xFFFF; else GPIOC->ODR=0x0000;
Сброс и установка битов порта
Для атомарного сброса и установки битов GPIO в микроконтроллерах STM32 предназначен регистр GPIOx_BSRR. Традиционный для архитектуры ARM способ управления битами регистров не требующий применения операции типа "чтение-модификация-запись” позволяет устанавливать и сбрасывать биты порта простой записью единицы в биты установки BS (BitSet) и сброса BR (BitReset) регистра BSRR. При этом запись в регистр нулевых битов не оказывает влияния на состояние соответствующих выводов.
GPIOx_BSRR – регистр сброса и установки битов порта:
GPIOC->BSRR=GPIO_BSRR_BS8|GPIO_BSRR_BR9; // Зажечь LED4 (PC8), погасить LED3.
GPIOC->BSRR=GPIO_BSRR_BS9|GPIO_BSRR_BR8; // Зажечь LED3 (PC9), погасить LED4.
Альтернативные функции GPIO и их переназначение (remapping)
Практически все внешние цепи специального назначения STM32 (включая выводы для подключения кварцевых резонаторов, JTAG/SWD и так далее) могут быть разрешены на соответствующих выводах микроконтроллера, либо отключены от них для возможности их использования в качестве выводов общего назначения. Выбор альтернативной функции вывода осуществляется при помощи регистров с префиксом "AFIO”_.
Помимо этого регистры AFIO_ позволяют выбирать несколько вариантов расположения специальных функций на выводах микроконтроллера. Это в частности относится к выводам коммуникационных интерфейсов, таймеров (регистры AFIO_MAPR), выводам внешних прерываний (регистры AFIO_EXTICR) и т. д.
Подробнее смотрите документы "Reference manual” на соответствующую подгруппу микроконтроллеров.
Проекты к статье:
- µVision 4.13a -> STM32GPIO_emcu_uV
- IAR ARM 6.0 -> STM32GPIO_emcu_iar
- IAR ARM 6.21 -> STM32GPIO_emcu_iar_V6.21
Для управления GPIO STM32 Вы можете применить макросы написанные как альтернативу далеко не оптимальным по мнению многих библиотекам от ST: gpio_emcu.h
Дополнительный материал:
- STM32F10xxx Reference manual. Справочное руководство разработчика
- STM32F100xx Reference manual. Справочное руководство разработчика
- STM32F105xx, STM32F107xx Datasheet
- STM32F100x4, STM32F100x6, STM32F100x8, STM32F100xB Data Sheet
- Руководство по созданию проектов для STM32DISCOVERY в IAR
- Руководство по созданию проектов для STM32DISCOVERY в MDK-ARM, uVision