Работа с портами ввода-вывода (GPIO) микроконтроллера Миландр на CMSIS

Операции над портами ввода-вывода или GPIO (general-purpose input/output) делятся на чтение и запись. К GPIO относят порты (выводы МК) не относящиеся к специализированным интерфейсам, таким как например UART, CAN, USB, JTAG и т.д., то есть портами GPIO мы управляем полностью сами, без какого либо встроенного в МК контроллера.

Порт GPIO может находиться в трех состояниях:

  • Высокое (логическая единица или напряжение более 2.4 В на выходе). Используется при операции записи в GPIO.
  • Низкое (логический ноль или напряжение менее 0.4 В на выходе). Используется при операции записи в GPIO.
  • Высокоимпедансное. Используется при операции чтения в GPIO. Может совмещаться с подтяжкой к питанию или нулю сопротивлением около 50 кОм.

Запись в GPIO

Ниже приведен пример программы для записи в GPIO. По умолчанию, после старта программы значения в регистрах GPIO нулевые и строчки инициализации содержащие нулевые значения могут быть опущены. В скобках указаны пункты спецификации на МК описывающие данные регистры.


// Пример записи в GPIO. Мигаем светодиодом VD5 (PORTB 0)
#include "MDR32F9Q2I.h" // Заголовок с наименованиями CMSIS

#define PIN_LED 0	// Номер вывода светодиода
#define PORT_LED MDR_PORTB	// Порт светодиода

int main (void)
{
  MDR_RST_CLK->PER_CLOCK |= (1 << 22); // Разрешение тактирования порта B (п.14.7.8)

  PORT_LED->OE |= (1 << PIN_LED); // Вход или выход. 0 - вход, 1 - выход (п.16.1.2)
  PORT_LED->ANALOG |= (1 << PIN_LED); // Аналог или цифра. 0 - аналоговый, 1 - цифровой (п.16.1.4) (п.4 т.2)
  PORT_LED->PWR |= (1 << PIN_LED * 2); // Передатчик. 0 - отключен, 1 - медленный, 2 - средний, 3 - быстрый (п.16.1.7)
  PORT_LED->FUNC &= ~(1U << PIN_LED); // Функция. 0 - порт (GPIO), 1 - основная, 2 - альтернативная, 3 - переопределенная (п.16.1.2) (п.4 т.2)
  PORT_LED->PULL &= ~(1U << PIN_LED); // Подтяжка к нулю. 0 - выключена, 1 - включена (п.16.1.5)
  PORT_LED->PULL &= ~(1U << (PIN_LED + 16)); // Подтяжка к питанию. 0 - выключена, 1 - включена (п.16.1.5)
  PORT_LED->PD &= ~(1U << PIN_LED); // Тип выхода. 0 - управляемый драйвер, 1 - открытый сток (п.16.1.6)
  PORT_LED->PD &= ~(1U << (PIN_LED + 16)); // Триггер Шмидта. 0 - выключен, 1 - включен (п.16.1.6)
  PORT_LED->GFEN &= ~(1U << PIN_LED); // Фильтр. 0 - выключен, 1 - включен (п.16.1.8)

  while(1){ // Основной бесконечный цикл
    for(int i = 0; i < 100000; i++){} // Задержка	
    PORT_LED->RXTX ^= (1 << PIN_LED); // Инвертировать значение вывода (п.16.1.1)
  }
}

Чтение из GPIO

Для чтения из порта, он должен быть настроен как вход. Ниже пример программы где мы используем чтение и запись из GPIO используя порт кнопки как вход (чтение из GPIO) и порт светодиода как выход (запись в GPIO). Используется минимальный код, все значения регистров, которые по умолчанию имеют значение ноль, мы не приводим, если нужен полный код инициализации GPIO - берем его из предыдущего примера с записью в GPIO.


// Пример записи в GPIO. При нажатии кнопки SEL (по центру) тушится светодиод VD5 (PORTB 0)
#include "MDR32F9Q2I.h" // Заголовок с наименованиями CMSIS

#define PORT_LED MDR_PORTB	// Порт светодиода
#define PIN_LED 0	// Номер вывода светодиода

#define PORT_BTN MDR_PORTC	// Порт кнопки
#define PIN_BTN 2	// Номер вывода кнопки


int main (void)
{
  MDR_RST_CLK->PER_CLOCK |= (1 << 22); // Разрешение тактирования порта B (п.14.7.8)
  MDR_RST_CLK->PER_CLOCK |= (1 << 23); // Разрешение тактирования порта C (п.14.7.8)

  PORT_LED->OE |= (1 << PIN_LED); // Вход или выход. 0 - вход, 1 - выход (п.16.1.2)
  PORT_LED->ANALOG |= (1 << PIN_LED); // Аналог или цифра. 0 - аналоговый, 1 - цифровой (п.16.1.4) (п.4 т.2)
  PORT_LED->PWR |= (1 << PIN_LED * 2); // Передатчик. 0 - отключен, 1 - медленный, 2 - средний, 3 - быстрый (п.16.1.7)
  
  PORT_BTN->ANALOG |= (1 << PIN_BTN); // Аналог или цифра. 0 - аналоговый, 1 - цифровой (п.16.1.4) (п.4 т.2)

  while(1){ // Основной бесконечный цикл
    for(int i = 0; i < 100000; i++){} // Задержка	
    if(PORT_BTN->RXTX & (1 << PIN_BTN)){ // Если сигнал высокий
      PORT_LED->RXTX |= (1 << PIN_LED); // Зажигаем светодиод
    }else{
      PORT_LED->RXTX &= ~((1U << PIN_LED)); // Тушим светодиод
    }
  }
}
2024-04-24



Понравилась страница?
Добавить в закладки
Или поделиться!

Связанные темы

Управление тактовой частотой микроконтроллера Миландр К1986ВЕ92QI (MDR32F9Q2I)
Работа с портами ввода-вывода (GPIO) микроконтроллера Миландр на CMSIS
Прерывания в микроконтроллерах Миландр. Системный таймер.
Настройка среды разработки для микроконтроллеров Миландр (К1986ВЕ92QI)
Прошивка микроконтроллера К1986ВЕ92QI на отладочной плате LDM-K1986BE92QI через UART и SWD с использованием ST-LINK
Работа с UART микроконтроллера К1986ВЕ92QI (MDR32F9Q2I)