Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Кармин Новиелло - Освоение STM32.pdf
Скачиваний:
2741
Добавлен:
23.09.2021
Размер:
47.68 Mб
Скачать

Управление GPIO

167

Рисунок 5: Диалоговое окно Pin Configuration может использоваться для конфигурации режима

I/O

6.2.2. Режим альтернативной функции GPIO

Большинство GPIO имеют так называемые «альтернативные функции», то есть их можно использовать в качестве I/O как минимум одного внутреннего периферийного устройства. Однако имейте в виду, что любой I/O может подключиться только к одному периферийному устройству одновременно.

Рисунок 6: Используя CubeMX легко обнаружить альтернативные функции вводов/выводов

Чтобы узнать, какие периферийные устройства могут подключиться к I/O, вы можете обратиться к техническому описанию микроконтроллера или просто использовать инструмент CubeMX. Щелчок мышью по выводу в представлении Chip вызывает всплывающее меню. В этом меню мы можем назначить желаемую альтернативную функцию. Например, на рисунке 6 вы можете увидеть, что PA3 может использоваться как USART2_RX (то есть он может использоваться как вывод RX для периферийного устройства USART/UART2, и это возможно для каждого микроконтроллера STM32 с корпусом LQFP48). CubeMX автоматически сгенерирует для нас правильный код инициализации, который показан ниже:

Управление GPIO

168

/* Конфигурирование выводов GPIO : PA2 PA3 */

GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;

GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_LOW;

GPIO_InitStruct.Alternate = GPIO_AF1_USART2;

HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

Те из вас, кто работает с микроконтроллером STM32F1, заметят, что поле GPIO_InitTypeDef.Alternate отсутствует в HAL CubeF1. Его нет, потому что микроконтроллеры STM32F1 предоставляют менее гибкий способ определения альтернативных функций вывода. В то время как другие микроконтроллеры STM32 определяют возможные альтернативные функции на уровне GPIO (конфигурацией специальных регистров GPIOx_AFRL и GPIOx_AFRH), что позволяет подключать до 16 различных альтернативных функций к одному выводу (это возможно только для корпусов с большим числом выводов), GPIO микроконтроллеров STM32F1 имеют достаточно ограниченные возможности переназначения (или, как говорят, «ремаппинга», remapping). Например, в микроконтроллере STM32F103RB только USART3 может иметь две пары выводов, которые могут альтернативно использоваться в качестве вводов/выводов данного периферийного устройства. Обычно два специальных периферийных регистра, AFIO_MAPR и AFIO_MAPR2 «переназначают» сигнальные I/O тех периферийных устройств, которые разрешают эту операцию.

По сути, это и есть причина, по которой данное поле недоступно в HAL CubeF1.

6.2.3. Понятие скорости GPIO

Одним из наиболее часто вводящих в заблуждение параметров в микроконтроллерах STM32 является параметр GPIO_InitTypeDef.Speed. Это поле может принимать значения, представленные в таблице 4, и оно действует только тогда, когда GPIO сконфигурирован в режиме выхода. К сожалению, ST не подобрала более подходящего имени для этих констант в различных CubeHAL.

Таблица 4: Доступные режимы скорости для GPIO

CubeF0/1/3/L0/L1

CubeF4/L4

GPIO_SPEED_LOW GPIO_SPEED_MEDIUM GPIO_SPEED_FAST GPIO_SPEED_HIGH8

GPIO_SPEED_FREQ_LOW GPIO_SPEED_FREQ_MEDIUM GPIO_SPEED_FREQ_HIGH GPIO_SPEED_FREQ_VERY_HIGH

Скорость. Такое манящее слово для всех, кто любит производительность. Но что именно она означает, когда мы говорим о GPIO? Здесь скорость GPIO не связана с частотой переключения, то есть сколько раз вывод переключается из состояния ВКЛ в состояние ВЫКЛ в единицу времени. Параметр GPIO_InitTypeDef.Speed, напротив, определяет

скорость нарастания (slew rate) напряжения на GPIO, то есть скорость, с которой он переходит с уровня 0 В на уровень VDD, и наоборот.

8 Эти режимы доступны только в некоторых высокопроизводительных версиях микроконтроллеров STM32. Проверяйте справочное руководство по вашему микроконтроллеру.

Управление GPIO

169

Рисунок 7: Влияние скорости нарастания на прямоугольный сигнал:

красный = желаемый выходной сигнал (идеальный), зеленый = реальный выходной сигнал

Рисунок 7 четко показывает это явление. Красный меандр – это сигнал, который мы получили бы, если бы скорость отклика была бесконечной, и, следовательно, не было бы задержки отклика. На практике же мы получаем зеленый меандр.

Но насколько этот параметр влияет на скорость нарастания вывода STM32? Прежде всего, мы должны сказать, что каждое семейство STM32 имеет свои характеристики управления I/O. Поэтому вам необходимо проверить техническое описание вашего микро-

контроллера в разделе Absolute Maximum Ratings (Максимально достижимые зна-

чения). Затем, мы можем использовать этот простой тест для измерения скорости нарастания (тест проводится на плате Nucleo-F446RE).

int main(void) {

GPIO_InitTypeDef GPIO_InitStruct;

HAL_Init();

__HAL_RCC_GPIOC_CLK_ENABLE();

/* Конфигурирование вывода GPIO : PC4 */

GPIO_InitStruct.Pin = GPIO_PIN_4;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;

HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

/* Конфигурирование вывода GPIO : PC8 */

GPIO_InitStruct.Pin = GPIO_PIN_8;

GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;

GPIO_InitStruct.Pull = GPIO_NOPULL;

GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;

HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

while(1) {

GPIOC->ODR = 0x110; GPIOC->ODR = 0;

}

}

Управление GPIO

170

Данный код, несомненно, говорит сам за себя. Мы конфигурируем два вывода в качестве выходов. Один из них, PC4, сконфигурирован на скорость GPIO_SPEED_FREQ_LOW. Другой, PC8, – на GPIO_SPEED_FREQ_VERY_HIGH. Рисунок 8 показывает разницу между двумя выводами. Как мы видим, скорость PC4 составляет около 25 МГц, в то время как скорость вывода PC8 составляет около 50 МГц9.

Рисунок 8: На верхнем рисунке показана скорость нарастания вывода PC4, а на рисунке ниже –

скорость нарастания вывода PC8.

Тем не менее, имейте в виду, что «слишком жесткое» управление выводом влияет на общее излучение вашей платы. Профессиональная разработка в наше время сводит к минимуму EMI (электромагнитные помехи). Настоятельно рекомендуется оставить параметр скорости GPIO по умолчанию на минимальном уровне, если не требуется иное.

Что можно сказать об эффективной частоте переключения? ST утверждает в своих технических описаниях, что самая быстрая скорость переключения вывода – каждые два такта шины. В микроконтроллере STM32F446 шина AHB1, к которой подключены все GPIO, работает на частоте 42 МГц. Таким образом, вывод должен переключаться с частотой примерно 20 МГц. Однако мы должны добавить дополнительные накладные расходы, связанные с передачей памяти между регистром GPIO->ODR и значением, которое мы собираемся сохранить в нем (0x110), что стоит еще один тактовый цикл ЦПУ. Таким

9 К сожалению, щупы моего осциллографа имеют вдвое большую нагрузочную емкость, чем необходимо для проведения точных измерений. Согласно техническому описанию STM32F446RE, его максимальная частота переключения составляет 90 МГц при емкости нагрузки CL = 30 пФ, напряжении питания VDD ≥ 2,7 В и активированной компенсационной ячейке (I/O compensation sell). Но я не смог получить эти результаты из-за плохого осциллографа и, вероятно, из-за длины дорожек, соединяющих гребенку штыревых morpho-разъемов Nucleo с выводами микроконтроллера.

Управление GPIO

171

образом, ожидаемая максимальная скорость переключения GPIO составляет ~14 МГц. Осциллограф подтверждает это, как показано на рисунке 910.

Рисунок 9: Максимальная частота переключения вывода, достигнутая с помощью STM32F446

Любопытно, что при управлении I/O через область доступа к битам (битовых лент), англ. bit-banding region, с использованием одинакового количества ассемблерных инструкций резко снижается частота переключения до 4 МГц, как показано на рисунке 10.

Рисунок 10: Частота переключения при переключении вывода через область доступа к битам

Код, используемый для проведения теста, следующий (не относящийся к делу код был опущен):

#define BITBAND_PERI_BASE 0x40000000 #define ALIAS_PERI_BASE 0x42000000

#define BITBAND_PERI(a,b)((ALIAS_PERI_BASE+((uint32_t)a-BITBAND_PERI_BASE)*32+(b*4)))

...

volatile uint32_t *GPIOC_ODR = (((((uint32_t)0x40000000) + 0x00020000) + 0x0800) + 0x14); volatile uint32_t *GPIOC_PIN8 = (uint32_t)BITBAND_PERI(GPIOC_ODR, 8);

...

while(1) {

*GPIOC_PIN8 = 0x1;

*GPIOC_PIN8 = 0;

}

10 Тесты проводились при максимальном уровне оптимизации GCC (-O3), включенной предвыборкой инструкций и всеми внутренними кэшами. Это обуславливает то, что обнаруженная скорость немного выше

14 МГц.