Урок 1. Кнопка, светодиод. Функции управления вводом/выводом. Первая программа

В этом уроке напишем первую программу, научимся считывать значение цифровых входов и устанавливать состояние выходов. Реализуем управление такими простыми элементами, как кнопка и светодиод на платформе Maixduino.

Что нужно знать

Существует 3 фреймворка для разработки приложений для процессора К210:

  • Standalone SDK для Kendryte K210;
  • Kendryte FreeRTOS SDK — Этот SDK предназначен для Kendryte K210, который содержит поддержку FreeRTOS;
  • Arduino (на основе Standalone SDK).

Для работы с периферийными устройствами на Maixduino существует 3 основных компонента: GPIO, GPIOHS и FPIOA.

  • GPIO (General Purpose Input Output / Интерфейс ввода/вывода общего назначения) — чип имеет 8 GPIO общего назначения.
  • GPIOHS (General Purpose Input Output High Speed / Высокоскоростной интерфейс ввода/вывода общего назначения) – чип имеет 32 высокоскоростных GPIO. Похоже на обычный GPIO, но быстрее.
  • FPIOA (Field Programmable I/O Array / Программируемый массив ввода/вывода) позволяет пользователю соотносить 256 внутренних функций с 48 физическими входами / выходами на чипе.

Из этого следует, что Maixduino более гибок, чем простой Arduino на базе микроконтроллеров AVR. Мы можем сопоставить любое устройство с любым физическим контактом (контактами), например, кнопки, светодиоды, устройства I2C и SPI, и т. д.

Создание нового проекта

  1. Открываем PlatformIO: Home и выбираем New Project, чтобы создать новый проект;
    Урок 1. Управление I/O. Кнопка, светодиод - PIO Home
  2. Задаём название проекта в поле Name;
  3. В Boards ищем плату Sipeed MAIXDUINO;
    Урок 1. Управление I/O. Кнопка, светодиод - Board
  4. Выбираем Фреймворк Kendryte FreeRTOS SDK;
  5. В Location можно указать путь, где будет храниться проект, но можно оставить по умолчанию.
    Урок 1. Управление I/O. Кнопка, светодиод - Finish

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

Настройка проекта

В папке src необходимо создать два файла: main.cpp и project_cfg.h. В первом файле мы напишем программу, а во втором мы определим макросы и настроим функции выводов.

Урок 1. Управление I/O. Кнопка, светодиод - Проект

В корневом каталоге есть файл platformio.ini — файл конфигурации проекта PlatformIO. По умолчанию PlatformIO автоматически определяет порт загрузки. Но Вы можете настроить собственный порт, используя параметр upload_port. Список портов вы можете найти в Диспетчер Устройств или во вкладке Devices в PIO Home.

В platformio.ini вы также можете изменить скорость загрузки, используя параметр upload_speed, порт монитора, параметр monitor_port, и скорость монитора порта, параметр monitor_speed. Порт загрузки и порт монитора должны совпадать.

Пример файла platformio.ini

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:sipeed-maixduino]
platform = kendryte210
board = sipeed-maixduino
framework = kendryte-freertos-sdk

upload_port = COM3
upload_speed = 1500000

monitor_port = COM3
monitor_speed = 115200

Как работать с GPIO

Если мы хотим записывать или читать данные из GPIO, мы должны сначала его настроить. Как упоминалось выше, K210 имеет 48 контактов и 256 функций для них. Но поскольку на плате формфактора Arduino количество контактов ограничено, используются не все 48 контактов.

Сначала, чтобы определить, какие контакты и где они назначены, мы должны открыть схему платы — Maixduino-4.30(schematic).pdf. Тут нужно найти разъемы (Connector).Урок 1. Управление I/O. Кнопка, светодиод - Connector

Все контакты разъема P3 (HEADER-1X6) подключены к ESP-32, поэтому его нельзя использовать с K210. Но разъемы P2 и P5 идут на K210, и их можно использовать в качестве контактов ввода-вывода общего назначения.

Настройка порта

Перед настройкой вывода на выход или на вход ему необходимо назначить одну функцию из 32 GPIOHS или 8 GPIO. Это можно сделать двумя способами:

  1. с использованием функции int fpioa_set_function (int number, fpioa_function_t function);
  2. с конфигурацией объекта g_fpioa_cfg.

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

В приведенных ниже примерах показано, как соотносить функцию GPIOHS0 на вывод под номером 3 (это вывод IO3 на разъеме P5). Обратите внимание, что перечисление выполняется относительно FUNC_GPIOHS0. В дальнейшем будут использоваться только значения от 0 до 31. Поэтому желательно использовать макросы (#define).

Пример 1:

fpioa_set_function(3, static_cast<fpioa_function_t>(FUNC_GPIOHS0 + 0));

Пример 2:

#ifndef PROJECT_CFG_H
#define PROJECT_CFG_H

#include <pin_cfg.h>

const fpioa_cfg_t g_fpioa_cfg = {
    /* Версия */
    .version = PIN_CFG_VERSION,
    /* Число функций */
    .functions_count = 1,
    /* Офисание функций */
    .functions = {
        /*  */
        {3, static_cast<fpioa_function_t>(FUNC_GPIOHS0 + 0)},
    },
};
#endif

После этого необходимо открыть устройство gpio0 с помощью функции io_open.

/* Открываем GPIO0 устройство */
gpio = io_open("/dev/gpio0");

И наконец настраиваем режим работы вывода (пина) – на вход или выход.

/* Устанавливаем режим работы пина 0 на вход. */
gpio_set_drive_mode(gpio, 0, GPIO_DM_INPUT);
/* Устанавливаем режим работы пина 0 на выход. */
gpio_set_drive_mode(gpio, 0, GPIO_DM_OUTPUT);
/* Устанавливаем режим работы пина 0 на вход с подтягивающим резистором (pull-up resistor). */
gpio_set_drive_mode(gpio, 0, GPIO_DM_INPUT_PULL_UP);
/* Устанавливаем режим работы пина 0 на вход с стягивающим резистором (pull-down resistor). */
gpio_set_drive_mode(gpio, 0, GPIO_DM_INPUT_PULL_DOWN);

Примеры программ

Чтобы лучше понять, как всё это работает, приведу два примера программ. Комментарии также будут добавлены в код для более подробного описания.

Пример 1 — мигаем светодиод

В первом примере будем мигать светодиодом, подключенным к одному из выводов платы. В файле project_cfg.h настроим функцию вывода, используемый для мигания светодиода. В файле main.cpp настроим вывод на выход и создадим задачу blinkLedTask, которая будет вызываться с интервалом 100 мс, и при каждом вызове светодиод будет менять свое состояние с ВКЛ на ВЫКЛ и наоборот.

Схема подключения

Светодиод подключается на 13-й контакт Maixduino/Arduino через резистор, ограничивающий ток.

Урок 1. Управление I/O. Схема подключения светодиода - Maixduino+LED

Файл project_cfg.h

#ifndef PROJECT_CFG_H
#define PROJECT_CFG_H

#include <pin_cfg.h>

/**
 * Номер внутреннего пина
 */
#define LED_IO (0)

/**
 * Номер физического пина
 */
#define LED_PIN (3)

const fpioa_cfg_t g_fpioa_cfg = {
    /* Версия */
    .version = PIN_CFG_VERSION,
    /* Число функций */
    .functions_count = 1,
    /* Офисание функций */
    .functions = {
        /*  */
        {LED_PIN, static_cast<fpioa_function_t>(FUNC_GPIOHS0 + LED_IO)},
    },
};
#endif

Файл main.cpp

#include "project_cfg.h"
#include <FreeRTOS.h>
#include <devices.h>
#include <syslog.h>
#include <task.h>

/**
 * Указатель на устройство GPIO
 */
static handle_t gpio;

/**
 * Текущее состояние светодиода
 */
static gpio_pin_value_t ledState;

/**
 * Прототип задачи включения/выключения светодиода
 * 
 * @param pvParameters Функции задач принимают параметр, имеющий тип указателя на void (т. е. void*). Значение, указанное в pvParameters, будет передано в задачу.
 */
static void blinkLedTask(void *pvParameters);

/**
 * 
 */
int main() {
  BaseType_t retCode;

  /* Открываем GPIO0 устройство */
  gpio = io_open("/dev/gpio0");
  /* Перехват ошибок в процессе разработки */
  configASSERT(gpio);
  /* Устанавливаем режим работы LED_IO пина на выход. */
  gpio_set_drive_mode(gpio, LED_IO, GPIO_DM_OUTPUT);
  /* Задаём начальное состояние светодиода (выключаем) */
  ledState = GPIO_PV_LOW;
  /* Пишем состояние в пин */
  gpio_set_pin_value(gpio, LED_IO, ledState);

  /* Создаём задачу с мигающим светодиодом */
  retCode = xTaskCreateAtProcessor(1, &blinkLedTask, "Blink Led task", 512, nullptr, 3, nullptr);
  /* Проверяем, если задача была успешно создана */
  if (retCode == pdPASS) {
    /* В случае успеха выводим информационное сообщение */
    LOGI("MFRB", "Blink Led task is running");
  } else {
    /* В случае неудачи выводим предупреждающее сообщение */
    LOGW("MFRB", "Blink Led task start problems");
  }

  for (;;) {
  }

  return 0;
}

static void blinkLedTask(void *pvParameters) {
  while (1) {
    /* Меняем состояние в 1/0 */
    if (GPIO_PV_HIGH == ledState) {
      ledState = GPIO_PV_LOW;
    } else {
      ledState = GPIO_PV_HIGH;
    }
    /* Пишем новое состояние в пин */
    gpio_set_pin_value(gpio, LED_IO, ledState);

    /* Помещаем задачу в состояние Blocked на фиксированное количество тиков прерываний.
    Находясь в состоянии Blocked, задача не использует процессорное время, 
    поэтому процессор загружен только полезной работой.
    С помощью макроса pdMS_TO_TICKS мы конвертируем миллисекунды в тики */
    vTaskDelay(pdMS_TO_TICKS(100));
  }
}

Пример 2 — кнопка и светодиод

Во втором примере помимо светодиода подключим еще и кнопку. Если кнопка не нажата, светодиод будет менять свое состояние (мигать) каждые 500 мс, а при нажатии — каждые 100 мс. Вывод, подключенный к кнопке, настроен на вход с подтягивающим резистором gpio_set_drive_mode(gpio, BTN_IO, GPIO_DM_INPUT_PULL_UP);.

Схема подключения

Светодиод подключается на 13-й контакт Maixduino/Arduino через резистор, ограничивающий ток, а кнопка на 12-й контакт и GND.

Урок 1. Управление I/O. Схема подключения светодиода - Maixduino+LED+Button

Файл project_cfg.h

#ifndef PROJECT_CFG_H
#define PROJECT_CFG_H

#include <pin_cfg.h>

/**
 * Номер внутреннего пина
 */
#define LED_IO (0)
#define BTN_IO (1)

/**
 * Номер физического пина
 */
#define LED_PIN (3)
#define BTN_PIN (10)

const fpioa_cfg_t g_fpioa_cfg = {
    /* Версия */
    .version = PIN_CFG_VERSION,
    /* Число функций */
    .functions_count = 2,
    /* Офисание функций */
    .functions = {
        /*  */
        {LED_PIN, static_cast<fpioa_function_t>(FUNC_GPIOHS0 + LED_IO)},
        {BTN_PIN, static_cast<fpioa_function_t>(FUNC_GPIOHS0 + BTN_IO)},
    },
};
#endif

Файл main.cpp

#include "project_cfg.h"
#include <FreeRTOS.h>
#include <devices.h>
#include <syslog.h>
#include <task.h>

/**
 * Указатель на устройство GPIO
 */
static handle_t gpio;

/**
 * Текущее состояние светодиода
 */
static gpio_pin_value_t ledState;

/**
 * Прототип задачи включения/выключения светодиода
 * 
 * @param pvParameters Функции задач принимают параметр, имеющий тип указателя на void (т. е. void*). Значение, указанное в pvParameters, будет передано в задачу.
 */
static void blinkLedTask(void *pvParameters);

/**
 * 
 */
int main() {
  BaseType_t retCode;

  /* Открываем GPIO0 устройство */
  gpio = io_open("/dev/gpio0");
  /* Перехват ошибок в процессе разработки */
  configASSERT(gpio);
  /* Устанавливаем режим работы LED_IO пина на выход. */
  gpio_set_drive_mode(gpio, LED_IO, GPIO_DM_OUTPUT);
  /* Устанавливаем режим работы BTN_IO пина на вход с подтягивающим резистором. */
  gpio_set_drive_mode(gpio, BTN_IO, GPIO_DM_INPUT_PULL_UP);
  /* Задаём начальное состояние светодиода (выключаем) */
  ledState = GPIO_PV_LOW;
  /* Пишем состояние в пин */
  gpio_set_pin_value(gpio, LED_IO, ledState);

  /* Создаём задачу с мигающим светодиодом */
  retCode = xTaskCreateAtProcessor(1, &blinkLedTask, "Blink Led task", 512, nullptr, 3, nullptr);
  /* Проверяем, если задача была успешно создана */
  if (retCode == pdPASS) {
    /* В случае успеха выводим информационное сообщение */
    LOGI("MFRB", "Blink Led task is running");
  } else {
    /* В случае неудачи выводим предупреждающее сообщение */
    LOGW("MFRB", "Blink Led task start problems");
  }

  for (;;) {
  }

  return 0;
}

static void blinkLedTask(void *pvParameters) {
  /* Состояние кнопки */
  gpio_pin_value_t btnState;
  /* Время повторения */
  unsigned int timeInMs;
  while (1) {
    /* Считываетм состояние кнопки. */
    btnState = gpio_get_pin_value(gpio, BTN_IO);
    if (btnState == GPIO_PV_LOW) {
      /* Если кнопка нажата, мы меняем повторяемость задачи на 100 мс. */
      timeInMs = 100;
    } else {
      /* Если нет - 500 мс. */
      timeInMs = 500;
    }

    /* Меняем состояние в 1/0 */
    if (GPIO_PV_HIGH == ledState) {
      ledState = GPIO_PV_LOW;
    } else {
      ledState = GPIO_PV_HIGH;
    }
    /* Пишем новое состояние в пин */
    gpio_set_pin_value(gpio, LED_IO, ledState);

    /* Помещаем задачу в состояние Blocked на фиксированное количество тиков прерываний.
    Находясь в состоянии Blocked, задача не использует процессорное время, 
    поэтому процессор загружен только полезной работой.
    С помощью макроса pdMS_TO_TICKS мы конвертируем миллисекунды в тики */
    vTaskDelay(pdMS_TO_TICKS(timeInMs));
  }
}

Материалы

Kendryte · GitHub
Maixduino-4.30(schematic)
Maixduino — одноплатный компьютер с ускорителем AI, RISC-V AI, форм-фактор Arduino и беспроводной модуль ESP32

Похожие записи

Комментарии 34

  • It’s a shame you don’t have a donate button! I’d certainly donate to this superb blog!
    I guess for now i’ll settle for bookmarking and adding your
    RSS feed to my Google account. I look forward to brand new
    updates and will talk about this blog with my
    Facebook group. Chat soon!

  • First of all I want to say awesome blog! I had a quick question that I’d like to
    ask if you do not mind. I was interested to find out how you center yourself and clear your head
    before writing. I have had difficulty clearing my thoughts in getting my ideas out there.
    I truly do take pleasure in writing but it just
    seems like the first 10 to 15 minutes are wasted simply just
    trying to figure out how to begin. Any suggestions or hints?
    Many thanks!

  • This text is invaluable. How can I find out more?

  • Hey! This is kind of off topic but I need some advice from an established blog.
    Is it very hard to set up your own blog? I’m not very techincal but
    I can figure things out pretty quick. I’m thinking about setting up my own but I’m
    not sure where to begin. Do you have any points or suggestions?

    Thank you

  • Very good write-up. I absolutely appreciate this
    website. Keep it up!

  • Highly energetic post, I liked that bit. Will there be
    a part 2?

  • Wow! After all I got a webpage from where I can truly get helpful information concerning my study and knowledge.

  • آخرین اخبار و گزارش های
    جدید را در goodlibrary.іr مشاهده کنید

    Alѕо visit mу websiute — ,Stay informed ԝith Урок 1.
    Кнопка, светодиод. Функции
    управления вводом/выводом. Первая программа
    Karma

  • I was extremely pleased to find this great site. I need to to thank you for ones
    time for this particularly fantastic read!!

    I definitely really liked every bit of it and I have you book-marked to see new stuff in your blog.

  • I love it when individuals come together and share views.

    Great site, keep it up!

  • Very good article. I certainly love this site. Continue the good work!

    Look at my blog post: kttc.marketminute.com

  • It is appropriate time to make a few plans for the long
    run and it is time to be happy. I’ve learn this put up and if I may just I want to suggest you some interesting
    things or tips. Perhaps you could write subsequent articles relating to this article.
    I wish to learn more things about it!

  • I blog frequently and I seriously thank you for
    your information. Your article has really peaked my interest.
    I will take a note of your blog and keep checking for new information about once per week.
    I subscribed to your Feed as well.

  • Sehr präzise Informationen! Die Tipps sind sehr praktisch und leicht umsetzbar.
    Danke für Ihren Beitrag!

  • My family every time say that I am wasting my time here at
    web, however I know I am getting familiarity all the time by reading such
    pleasant articles.

  • Undeniably consider that which you said. Your favourite reason seemed to be on the internet the easiest
    thing to take into accout of. I say to you, I definitely get irked at the same time as folks think about issues that they just
    do not understand about. You managed to hit the nail upon the top
    and outlined out the entire thing with no need
    side effect , people can take a signal. Will likely be back
    to get more. Thanks

  • Excellent way of explaining, and good article to get facts regarding my presentation focus, which i am going to present in academy.

  • My partner and I stumbled over here different website and thought I
    should check things out. I like what I see so i am just following
    you. Look forward to looking into your web page yet again.

  • Hi there, every time i used to check web site posts here
    early in the daylight, as i love to find out more
    and more.

  • Hi there to every one, the contents existing at this site are actually remarkable for people
    knowledge, well, keep up the good work fellows.

  • I know this site gives quality based articles and extra
    data, is there any other site which gives these kinds of information in quality?

  • according to information According to the American Society of Addiction Medicine, some psychological and behavioral changes in detailed consultation to developing addiction include addictive cravings, impulsivity, impaired executive function,.

    My page … https://xxxbf.tv/tags

  • Hello my friend! I want to say that this post is awesome,
    nice written and come with almost all important infos.
    I would like to see more posts like this .

  • Introducing Tyler Wagner: Allstate Insurance, the leading insurance
    agency located in Las Vegas, NV. Boasting extensive expertise in the insurance industry,
    Tyler Wagner and his team are dedicated to providing exceptional customer service and tailored
    insurance solutions.

    From auto insurance to home insurance, to life and business insurance,
    we’ve got you covered. Our wide range of coverage options
    ensures that you can find the right policy to protect what matters most.

    Understanding the importance of risk assessment, our team strives to provide personalized insurance quotes that reflect your unique situation. By utilizing our
    deep knowledge of the insurance market and state-of-the-art underwriting processes, Tyler Wagner ensures
    that you receive the most competitive premium calculations.

    Navigating insurance claims can be challenging, but our agency by your
    side, you’ll have a smooth process. Our streamlined
    claims processing system and dedicated customer service team make sure that your claims
    are processed efficiently and with the utmost care.

    Moreover, we are well-versed in insurance law and regulation, guaranteeing that our policies is always
    in compliance with current legal standards. Our knowledge
    offers an added layer of security to our policyholders,
    knowing that their insurance is sound and dependable.

    At Tyler Wagner: Allstate Insurance, we believe that a good insurance policy is a key part of financial planning.
    It’s an essential aspect for safeguarding your future and ensuring the well-being of your
    loved ones. That’s why, we make it our mission to understand your individual
    needs and help you navigate through the choice among insurance options,
    making sure that you have all the information you need and confident in your decisions.

    Selecting Tyler Wagner: Allstate Insurance means partnering with a trusted insurance broker in Las Vegas,
    NV, who values your peace of mind and excellence. Our team isn’t just here to sell policies;
    we’re here to support you in creating a protected future.

    Don’t wait to reach out today and learn how Tyler Wagner:
    Allstate Insurance can transform your insurance experience
    in Las Vegas, NV. Experience the difference that comes
    from having an insurance agency that genuinely cares
    about you and works tirelessly to securing your peace of mind.

  • It’s difficult to find knowledgeable people in this particular subject, but
    you seem like you know what you’re talking about! Thanks

  • Fantastic site. A lot of useful information here. I’m sending it to some friends
    ans additionally sharing in delicious. And certainly, thanks on your effort!

    Here is my page — Water Damage Restoration

  • Пополнить и забрать сумму в 2023 году с https://unioncityhvacpros.com/ Покерок вы сможете просто. в него и предстоит вписать бонусный код.

  • I am sure this post has touched all the internet users, its really really fastidious post on building up new weblog.

    My site: https://Wiki.Evil-Admin.com/index.php?title=Serviced_Apartments_-_Good_To_Corporate_And_Long_Terms_Stays

  • Wow, superb weblog layout! How long have you ever been blogging for?
    you made blogging glance easy. The total glance of your website is wonderful, as well as the content![X-N-E-W-L-I-N-S-P-I-N-X]I simply could
    not leave your site before suggesting that I really loved the standard info an individual supply on your visitors?
    Is gonna be again regularly to investigate cross-check new posts.

  • Hi there to all, how is everything, I think every one is getting more from this web site,
    and your views are fastidious in support of new people.

  • Precisely what I was searching for, regards for putting up.

  • Great web site you have here.. It’s hard to find high-quality
    writing like yours nowadays. I truly appreciate individuals like you!
    Take care!!

  • Wonderful website you have here but I was curious about
    if you knew of any message boards that cover the same topics
    discussed here? I’d really love to be a part of online community where I can get comments from other knowledgeable
    people that share the same interest. If you have any suggestions, please
    let me know. Many thanks!

  • Hello there, just became aware of your blog through Google, and found
    that it is really informative. I’m going to watch out for brussels.

    I will be grateful if you continue this in future. A lot of people
    will be benefited from your writing. Cheers!

Добавить комментарий для edwin Отменить ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *