Учимся напрямую работать с выводами GPIO в программах на языке С/С++. Вывод в порт, чтение логического уровня на входе.

В фирменном руководстве пользователя подробно рассказано о том, как работать с портами из программы на языке Python или при помощи инструмента командной строки. Сейчас я расскажу, как работать с портами ввода-вывода на низком уровне, непосредственно из кода C/C++. Далее будем считать, что у вас уже установлена и настроена среда разработки для Omega2.

Для удобства в нашем учебном примере будем использовать встроенный трехцветный светодиод на фирменной док-плате Onion Omega2. Если вы не используете док-плату или хотите подключить внешние светодиоды, просто измените в исходном коде примера номера выводов. На док-плате синий светодиод подключен к GPIO15, зеленый – GPIO16, красный – GPIO17. Активный уровень низкий, то есть, чтобы встроенный светодиод светился, в соответствующий разряд GPIO надо записать логический ноль.

Для работы с линиями GPIO на низком уровне нам нужно обращаться непосредственно к аппаратным регистрам MT7688. Воспользуемся готовым решением от Onion. Впоследствии вы можете упростить структуру проекта и оптимизировать код, но сейчас мы не будем на это отвлекаться. Скачайте исходные файлы примера Fast-Gpio и распакуйте архив. Создайте в NetBeans IDE новый проект C/C++ Apllication, выберите язык C++, не забудьте указать указать правильный тулчейн для кросс-компиляции. Откройте каталог проекта (по умолчанию он находится в каталоге /Documents/NetBeansProjects/). Скопируйте в подкаталог проекта /include все файлы заголовков с расширением “.h“. В основной каталог проекта скопируйте файлы fastgpioomega2.cpp и module.cpp.

Подключите добавочные файлы к проекту (простого копирования недостаточно!). В проводнике проекта Netbeans IDE щелкните правой кнопкой мыши на секции Include, выберите опцию Add Existing Items… и в открывшемся окне выберите файлы fastgpioomega2.h, fastgpio.h, module.h и main.h. Аналогичным способом добавьте в секцию Source файлы fastgpioomega.cpp и module.cpp. У вас должна получиться структура проекта как на рисунке:

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

#include <cstdlib>
#include <main.h>
#include "fastgpio.h"

// определяем номера портов
#define RED     17 // встроенный на док-плату
#define GREEN   16 // встроенный на док-плату
#define BLUE    15 // встроенный на док-плату
#define INPUT   0

using namespace std;

int main(int argc, char** argv) {
    int level;

    FastGpio	*gpioObj;
    
    gpioObj = new FastGpioOmega2();
    
    //Линии GPIO15...GPIO15 настроим на выход
    //Начальный уровень высокий
    gpioObj->SetDirection(RED, 1);
    gpioObj->Set(RED, 1);
    gpioObj->SetDirection(GREEN, 1);
    gpioObj->Set(GREEN, 1);
    gpioObj->SetDirection(BLUE, 1);
    gpioObj->Set(BLUE, 1);

    //GPIO0 настроим как вход
    gpioObj->SetDirection(INPUT, 0);
    
    //Читаем уровень на линии GPIO0
    gpioObj->Read(INPUT, level);
    
    if(level == 1){
        gpioObj->Set(RED, 0);
        printf("Input level is HIGH\n");
    }
    else {
        gpioObj->Set(BLUE, 0);
        printf("Input level is LOW\n");
    }

    return 0;
}

В целом код примера примитивен и понятен. Обратите внимание, что при чтении состояния входа мы не присваиваем значение переменной level, а передаем ссылку на эту переменную в качестве аргумента функции.

Больше про Omega2 и Arduino вы можете прочитать в моей книге