Недавно коллега меня подсадил на идею создания умного дома, я даже успел заказать себе десятки разных датчиков. Встал вопрос о выборе Микроконтроллера (далее МК) или платы. После некоторых поисков нашёл несколько вариантов. Среди них были и Arduino (включая его клоны, один из которых себе заказал ради того, чтобы просто побаловаться) и Launchpad, но всё это избыточно и громоздко (хотя в плане программирования гораздо проще, но тему холиваров поднимать не буду, у каждого свои вкусы). В итоге решил определяться не с готовой платой, а взять только МК и делать всё с нуля. В итоге выбирал между Atmel ATtiny (2313), Atmel ATmega (решил отказаться т.к. не смог найти за адекватные деньги), STM32 (Cortex на ядре ARM). С тинькой я уже успел побаловаться, так что взял себе STM32VL-Discovery.  Это можно назвать вступлением к циклу статей по STM32. Оговорюсь сразу, автором большинства этих статей буду являться не я, т.к. сам только познаю, здесь я публикую их в первую очередь для себя, чтоб удобнее было искать если что-то забуду. И так поехали!

Общие сведения

Микроконтроллеры семейства STM32 содержат в своём составе до семи 16-разрядных портов ввода-вывода c именами от PORTA до PORTG. В конкретной модели микроконтроллера без исключений доступны все выводы портов, общее количество которых зависит от типа корпуса и оговорено в DataSheet на соответствующее подсемейство.

Для включения в работу порта x необходимо предварительно подключить его к шине APB2 установкой соответствующего бита IOPxEN в регистре разрешения тактирования периферийных блоков _RCCAPB2ENR:

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:

STM32_GPIO_CRL0 STM32_GPIO_CRL1

Структура регистра 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 — регистр блокировки настроек вывода порта:

STM32_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 – регистр сброса и установки битов порта:

STM32_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__ позволяют выбирать несколько вариантов расположения специальных функций на выводах микроконтроллера. Это в частности относится к выводам коммуникационных интерфейсов, таймеров (регистры _AFIOMAPR), выводам внешних прерываний (регистры _AFIOEXTICR) и т. д.

Подробнее смотрите документы “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

Источники:

 

Сделующая часть: Программирование STM32. Часть 2. Система тактирования STM32

Комментарии

comments powered by Disqus