PROGCONT.RU

Форма входа







Регистрпция Вход/

STM32F GPIO или порты ввода-вывода.

 Прежде чем писать как ими управлять давайте разберемся что они из себя представляют, будем разбирать на примере STM32F105RB.
Открываем описание контролера(datasheet) и находим вот такую таблицу, где даны данные о выводах контролера.

Колонка:
 Pins-название корпуса(в нашем случае LQFP64), ниже номер пина.
 Pin name-название пина или его короткое описание.
 Type-Назначение: I/O-может быть как входом так и выходом; I-только как вход; O-только выход; S-выводы необходимые для работы контролера.
 I/O Level-если вывод выделен как FT можно подключать к нему +5V но должен быть настроен только как Input floating, Output open-drain или Alternate function open-drain другие варианты могут вывести контролер из строя так как 5V попадет в его 3.3V питание, без пометки FT выдерживает только напряжение питания контролера.
 Main funnction-как будет настроен вывод после сброса или включения контролера.
 Alternate functions-альтернативная функция. Default-назначение по умолчанию, Remap-возможные варианты переназначения.


 Теперь что нужно знать про электрические параметры, смотрим ниже таблицу.

Строка:
I VDD-максимальные токи входящие в контролер.
I VSS-максимальные токи выходящие из контролера.
I IO-максимальный входящий и выходящий ток вывода I/O
I INJ(PIN)-первая строка(Injected current on five volt tolerant pins) проникающие токи которые нельзя превышать в питание контролера через пин FT(-5mA если напряжение будет опущено ниже земли контролера и 0mA если превысит напряжение питания контролера, то есть если на этом пине будет +5V то его можно использовать как Input floating, Output open-drain или Alternate function open-drain другие варианты могут вывести контролер из строя), вторая строка(Injected current on any other pin) максимальные проникающие токи для пинов где нет пометки FT ниже напряжения земли -5mA и выше питания 5mA.
∑I INJ(PIN)-сумма всех проникающих токов.


Посмотрите схему, что бы понять как работает вывод.

 Внимание, все выводы после включения или сброса контроллера настроены как GPIO_Mode_IN_FLOATING!

 Допустим выбрали нужный нам пин, остается настроить его с помощью SPL(стандартной периферийной библиотеки, вся информация находится в файле stm32f10x_gpio.h), конфигурация пина настраивается через структуру которую сначала надо инициализировать через функцию GPIO_InitTypeDef.

Структура состоит из трех параметров:
.GPIO_Pin-номер пина, пишется как GPIO_Pin_x(вместо x номер вашего порта).
.GPIO_Speed-максимальная скорость с какой может работать пин, тут три варианта:
   GPIO_Speed_10MHz
   GPIO_Speed_2MHz
   GPIO_Speed_50MHz
 Многие думают что это значит на какой частоте будет работать пин, но это не так. Это своего рода защита соседних пинов от наводок, смотрим ниже рисунок, примерно так будут выглядеть переход пина в высокое состояние. Поэтому чем круче подъем или спад напряжения то и индуктивная наводка будет больше на соседние ноги контроллера.

 Если вы превысите частоту переключения назначенную выводу(например мигая светодиодом) то он не будет успевать переходить в высокое и низкое состояние, будет что то среднее.

.GPIO_Mode-режимы вывода могут быть следующими вариантами:
   GPIO_Mode_AIN-настраивается как аналоговый вход для работы ADC(АЦП-аналого цифровой преобразователь), в input data register будет читаться ноль.
   GPIO_Mode_IN_FLOATING-вывод настроен как болтающийся вход его необходимо будет подключить через внешний подтягивающий резистор к питанию или земле иначе в input data register будет белиберда.
   GPIO_Mode_IPD-вывод настроен как вход и подтянут через внутренний резистор к земле контроллера.
   GPIO_Mode_IPU-вывод настроен как вход и подтянут через внутренний резистор к питанию контроллера.
   GPIO_Mode_Out_OD-вывод настроен как выход Open drain, работает только N-MOS(подключает к земле), всегда ограничивайте ток входа резистором.
   GPIO_Mode_Out_PP-вывод настроен как выход Push-pull, работает N-MOS(подключает к земле) и P-MOS(подключает к питанию контроллера), всегда ограничивайте ток входа резистором.
   GPIO_Mode_AF_OD-вывод используется для альтернативных функций(периферии например SPI, выводов таймеров, UART и так далее) как выход Open drain, работает только N-MOS(подключает к земле), всегда ограничивайте ток входа резистором.
   GPIO_Mode_AF_PP-как и выше только выход Push-pull работает N-MOS(подключает к земле) и P-MOS(подключает к питанию контроллера), всегда ограничивайте ток входа резистором.
 Ниже не большой пример для мигания светодиодом.

#include "stm32f10x.h"
void Pause(uint32_t ms);
int main() {
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);//Включаем тактирование порта
   GPIO_InitTypeDef my_pin;//Инициализируем нашу структуру
   my_pin.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;//На этих пинах будем мигать светодиодами
   my_pin.GPIO_Speed = GPIO_Speed_10MHz;
   my_pin.GPIO_Mode = GPIO_Mode_Out_PP;
   GPIO_Init(GPIOC, &my_pin);//Устанавливаем наши настройки для выводов порта GPIOC
while(1){
   GPIO_SetBits(GPIOC, GPIO_Pin_6|GPIO_Pin_7);//Пин подключен к питанию 3.3V
   Pause(200000);
   GPIO_ResetBits(GPIOC, GPIO_Pin_6|GPIO_Pin_7);//Пин подключен к земле
   Pause(200000);
}
return 0;
}
void Pause(uint32_t ms){ for(uint32_t i=0; i<ms; i++){}}

 GPIO_SetBits(GPIOC, GPIO_Pin_6|GPIO_Pin_7); и GPIO_ResetBits(GPIOC, GPIO_Pin_6|GPIO_Pin_7); эти функции установят и сбросят высокое состояние на пине, для изменения состояния вывода можно использовать еще две функции:

GPIO_WriteBit(GPIOC, GPIO_Pin_6|GPIO_Pin_7, Bit_SET);//Высокий уровень
GPIO_WriteBit(GPIOC, GPIO_Pin_6|GPIO_Pin_7, Bit_RESET);//Низкий уровень

 и еще одна функция которая записывает шестнадцатеричное значение в порт.

GPIO_Write(GPIOC, 192);//Устанавливаем высокий уровень на пинах 6 и 7
GPIO_Write(GPIOC, 0);//На всех пинах будет низкий уровень

 Как настроить вывод на вход следующий пример, если на выходе GPIO_Pin_6 будет высокий уровень то на GPIO_Pin_7 тоже высокий и на оборот.

#include "stm32f10x.h"
int main() {
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);

   GPIO_InitTypeDef my_pin_in;//Структура для пина который будет работать на вход
   my_pin_in.GPIO_Pin = GPIO_Pin_6;
   my_pin_in.GPIO_Mode = GPIO_Mode_IPD;//Настраиваем вывод как вход с подтяжкой на землю
   GPIO_Init(GPIOC, &my_pin_in);//Настраиваем 6 пин

   GPIO_InitTypeDef my_pin_out;
   my_pin_out.GPIO_Pin = GPIO_Pin_7;
   my_pin_out.GPIO_Speed = GPIO_Speed_10MHz;
   my_pin_out.GPIO_Mode = GPIO_Mode_Out_PP;
   GPIO_Init(GPIOC, &my_pin_out);
while(1){
//Проверяем состояние пина, подключите к 6 пину питание и на 7 будет высокий уровень
   if(GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6)){GPIO_SetBits(GPIOC, GPIO_Pin_7);}
//Если 6 пин не подключен к питанию то на 7 будет низкий уровень
   if(!GPIO_ReadInputDataBit(GPIOC, GPIO_Pin_6)){GPIO_ResetBits(GPIOC, GPIO_Pin_7);}
}
return 0;
}

 Еще три функции для чтения с порта.

//Читаем состояние порта и накладываем маску для 6 пина, если не ноль то пин 7 высокий уровень
if((GPIO_ReadInputData(GPIOC)&64)){GPIO_SetBits(GPIOC, GPIO_Pin_7);}
//Обратная проверка
if(!(GPIO_ReadInputData(GPIOC)&64)){GPIO_ResetBits(GPIOC, GPIO_Pin_7);}

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

//Проверяем состояние пина, если на 6 высокий и на 7 будет высокий уровень
if(GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_6)){GPIO_SetBits(GPIOC, GPIO_Pin_7);}
//Обратная функция
if(!GPIO_ReadOutputDataBit(GPIOC, GPIO_Pin_6)){GPIO_ResetBits(GPIOC, GPIO_Pin_7);}
//Читаем состояние порта и накладываем маску для 6 пина, если не ноль то пин 7 высокий уровень
if((GPIO_ReadOutputData(GPIOC)&64)){GPIO_SetBits(GPIOC, GPIO_Pin_7);}
//Обратная фунция
if(!(GPIO_ReadOutputData(GPIOC)&64)){GPIO_ResetBits(GPIOC, GPIO_Pin_7);}

 GPIO_PinLockConfig(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin)-функция блокирует вывод, после ее выполнения изменить состояния будет не возможно, толь после сброса, пример ниже.

GPIO_PinLockConfig(GPIOC, GPIO_Pin_7);

 GPIO_PinRemapConfig(uint32_t GPIO_Remap, FunctionalState NewState)-используется для переназначения вывода с Default на Remap, возможные варианты смотрите в описание контроллера(Datasheet), в таблице Pinouts and pin description(первый рисунок в статье).
Варианты для uint32_t 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_PartialRemap2_TIM2
   GPIO_FullRemap_TIM2
   GPIO_PartialRemap_TIM3
   GPIO_FullRemap_TIM3
   GPIO_Remap_TIM4
   GPIO_Remap1_CAN1
   GPIO_Remap2_CAN1
   GPIO_Remap_PD01
   GPIO_Remap_TIM5CH4_LSI
   GPIO_Remap_ADC1_ETRGINJ
   GPIO_Remap_ADC1_ETRGREG
   GPIO_Remap_ADC2_ETRGINJ
   GPIO_Remap_ADC2_ETRGREG
   GPIO_Remap_ETH
   GPIO_Remap_CAN2
   GPIO_Remap_SWJ_NoJTRST
   GPIO_Remap_SWJ_JTAGDisable
   GPIO_Remap_SWJ_Disable
   GPIO_Remap_SPI3
   GPIO_Remap_TIM2ITR1_PTP_SOF
   GPIO_Remap_PTP_PPS
   GPIO_Remap_TIM15
   GPIO_Remap_TIM16
   GPIO_Remap_TIM17
   GPIO_Remap_CEC
   GPIO_Remap_TIM1_DMA
   GPIO_Remap_TIM9
   GPIO_Remap_TIM10
   GPIO_Remap_TIM11
   GPIO_Remap_TIM13
   GPIO_Remap_TIM14
   GPIO_Remap_FSMC_NADV
   GPIO_Remap_TIM67_DAC_DMA
   GPIO_Remap_TIM12
   GPIO_Remap_MISC

FunctionalState NewState-включает(ENABLE) и отключает(DISABLE) переназначение.

 Если вы обратили внимание некоторые переназначение имеют два названия PartialRemap(частичное) и FullRemap(полное) как это будет работать можно найти в Reference manual вашего контроллера, пример на STM32F105RB переназначаем TIM1(выходы).
 Открываем Reference manual RM0008 раздел AF remap and debug I/O configuration register (AFIO_MAPR) страница 186.

 Смотрим где находится TIM1_CH1N.

 Выполняем.

GPIO_PinRemapConfig(GPIO_PartialRemap_TIM1, ENABLE);

 TIM1_CH1N был на PB13 вывод 34, стал PA7 вывод 23.

 GPIO_EXTILineConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource)-Функция подключает вывод к модулю прерывания, для отслеживания и отработки изменений, например при появления напряжения.
Варианты для GPIO_PortSource:
   GPIO_PortSourceGPIOA
   GPIO_PortSourceGPIOB
   GPIO_PortSourceGPIOC
   GPIO_PortSourceGPIOD
   GPIO_PortSourceGPIOE
   GPIO_PortSourceGPIOF
   GPIO_PortSourceGPIOG

Для GPIO_PinSource будет GPIO_PinSource0-15.

 Вот пример настройки прерывания от вывод GPIOA пин 0, когда на выводе появится 3.3V будет выполнятся код в обработчике прерываний void EXTI0_IRQHandler(void) в котором будем программно менять состояние на выводе GPIOC пин 7.

#include "stm32f10x.h"
void Pause(uint32_t ms){ for(uint32_t i=0; i<ms; i++){}}
void EXTI0_Config(void)
{
//Включаем тактирование, настраиваем GPIOC пин 7 как выход
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOC, ENABLE);
   GPIO_InitTypeDef my_pin_out;
   my_pin_out.GPIO_Pin = GPIO_Pin_7;
   my_pin_out.GPIO_Speed = GPIO_Speed_10MHz;
   my_pin_out.GPIO_Mode = GPIO_Mode_Out_PP;
   GPIO_Init(GPIOC, &my_pin_out);
//Включаем тактирование, настраиваем GPIOA пин 0 как вход без подтяжек
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);
   GPIO_InitTypeDef GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
   GPIO_Init(GPIOA, &GPIO_InitStructure);
//Включаем тактирование AFIO что бы работали изменения
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
//Тут наша функция которая и подключает наш вывод к модулю прерываний
   GPIO_EXTILineConfig(GPIO_PortSourceGPIOA, GPIO_PinSource0);
//Настраиваем как должно срабатывать прерывание
   EXTI_InitTypeDef EXTI_InitStructure;
   EXTI_InitStructure.EXTI_Line = EXTI_Line0;
   EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
   EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
   EXTI_InitStructure.EXTI_LineCmd = ENABLE;
   EXTI_Init(&EXTI_InitStructure);
//Тут настройки и включения прерывания.
   NVIC_InitTypeDef NVIC_InitStructure;
   NVIC_InitStructure.NVIC_IRQChannel = EXTI0_IRQn;
   NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
   NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
   NVIC_Init(&NVIC_InitStructure);
}
//Обработчик прерываний
void EXTI0_IRQHandler(void){
   GPIOC->ODR^=GPIO_Pin_7;
   EXTI_ClearITPendingBit(EXTI_Line0);
}
int main()
{
//Тактируемся от HSI
   RCC_DeInit();
   EXTI0_Config();
   while (1){}
   return 0;
}

GPIO_EventOutputConfig(uint8_t GPIO_PortSource, uint8_t GPIO_PinSource) и GPIO_EventOutputCmd(FunctionalState NewState)-данные функции я рассматривать не буду так как вряд ли кто будет делать на контроллерах многопроцессорные системы, опишу в вкратце для чего они. Первая функция подключает CORTEX ядро к выбранному вами выводу для того что бы например когда контроллер выйдет из сна быстро просигнализировать что он в работе другим системам или контроллерам, вторая функция просто включает.


Комментариев нет  Только зарегистрированные пользователи могут оставлять комментарии!