В этой статье мы рассмотрим настройку обработки прерываний (IRQ) на Raspberry Pi Pico с использованием FreePascal. Этот вопрос был поднят пользователем Germo, столкнувшимся с проблемой при использовании функции gpio_set_irq_enabled_with_callback.
Проблема:
Germo не смог настроить обработку прерываний от GPIO на своей Raspberry Pi Pico, используя FreePascal. При запуске программы отладчик останавливался на функции gpio_set_irq_enabled_with_callback.
Решение Thaddy:
Thaddy предложил следующий пример кода, демонстрирующий настройку прерывания по спадающему фронту сигнала на GPIO пине:
program gpio_irq_test;
{$MODE OBJFPC}
{$H+}
uses
pico_gpio_c, pico_irq_c;
const
LED_PIN = 25;
IRQ_PIN = 15;
procedure irq_callback(gpio: byte; events: longword); cdecl;
begin
gpio_put(LED_PIN, not gpio_get(LED_PIN)); // Toggle LED on IRQ
end;
begin
stdio_init_all;
gpio_init(LED_PIN);
gpio_set_dir(LED_PIN, GPIO_OUT);
gpio_init(IRQ_PIN);
gpio_set_dir(IRQ_PIN, GPIO_IN);
gpio_pull_up(IRQ_PIN);
gpio_set_irq_enabled_with_callback(
IRQ_PIN,
GPIO_IRQ_EDGE_FALL,
true,
@irq_callback
);
while true do
// Main loop
end;
end.
Разбор кода:
uses pico_gpio_c, pico_irq_c;: Подключает необходимые модули для работы с GPIO и прерываниями. Убедитесь, что эти модули правильно установлены и доступны в вашем проекте FreePascal.
LED_PIN = 25; IRQ_PIN = 15;: Определяет константы для пина светодиода (выход) и пина прерывания (вход). Замените эти значения на пины, которые вы используете в своей схеме.
procedure irq_callback(gpio: byte; events: longword); cdecl;: Определяет процедуру-обработчик прерывания. Важно отметить ключевое слово cdecl, указывающее на соглашение о вызовах C, которое необходимо для правильной работы с библиотеками, написанными на C. Внутри процедуры irq_callback происходит переключение состояния светодиода при возникновении прерывания. Параметры gpio и events содержат информацию о пине, вызвавшем прерывание, и типе события.
gpio_init(LED_PIN); gpio_set_dir(LED_PIN, GPIO_OUT);: Инициализирует пин светодиода как выход.
gpio_init(IRQ_PIN); gpio_set_dir(IRQ_PIN, GPIO_IN);: Инициализирует пин прерывания как вход.
gpio_pull_up(IRQ_PIN);: Включает подтягивающий резистор на пине прерывания. Это важно, чтобы пин не "плавал" и имел определенное состояние, когда на него не подается сигнал.
gpio_set_irq_enabled_with_callback(IRQ_PIN, GPIO_IRQ_EDGE_FALL, true, @irq_callback);: Ключевая функция! Включает прерывание на указанном пине.
IRQ_PIN: Номер пина, на котором нужно включить прерывание.
GPIO_IRQ_EDGE_FALL: Тип прерывания - по спадающему фронту сигнала. Другие возможные значения: GPIO_IRQ_EDGE_RISE (по восходящему фронту), GPIO_IRQ_LEVEL_LOW (низкий уровень), GPIO_IRQ_LEVEL_HIGH (высокий уровень).
true: Включает прерывание.
@irq_callback: Указатель на процедуру-обработчик прерывания.
while true do // Main loop: Бесконечный цикл, в котором программа ожидает прерывания.
Важные моменты и альтернативные решения:
Соглашение о вызовах cdecl: Как правильно отметил Thaddy, использование cdecl для процедуры-обработчика прерывания критически важно. Неправильное соглашение о вызовах может привести к краху программы или непредсказуемому поведению.
Модули и линковка: Убедитесь, что вы правильно подключили необходимые модули (pico_gpio_c, pico_irq_c) и указали необходимые библиотеки для линковки (pico_multicore, pico_stdlib, hardware_gpio). Это можно сделать в настройках вашего проекта FreePascal.
Тип прерывания: Выбор типа прерывания зависит от вашей конкретной задачи. Если вам нужно реагировать на изменение состояния пина, используйте GPIO_IRQ_EDGE_RISE или GPIO_IRQ_EDGE_FALL. Если вам нужно реагировать на определенный уровень сигнала, используйте GPIO_IRQ_LEVEL_LOW или GPIO_IRQ_LEVEL_HIGH.
Подтягивающие резисторы: Использование подтягивающих (или подтягивающих вниз) резисторов необходимо для обеспечения стабильного состояния пина, когда на него не подается сигнал. В примере Thaddy используется gpio_pull_up(IRQ_PIN), но в зависимости от вашей схемы вам может потребоваться gpio_pull_down(IRQ_PIN).
Альтернативное решение (использование прерываний в стиле Object Pascal): Хотя пример Thaddy использует C-совместимый подход с cdecl, можно попробовать реализовать обработку прерываний в более объектно-ориентированном стиле, используя классы и события. Это может потребовать написания оберток (wrappers) вокруг C-функций, но позволит вам работать с прерываниями более интуитивно. Пример такой обертки (псевдокод):
Этот пример демонстрирует создание класса TGPIOInterruptHandler, который инкапсулирует логику настройки и обработки прерывания. Событие OnInterrupt позволяет вам подписаться на прерывание и обрабатывать его в вашем коде.
Заключение:
Настройка прерываний на Raspberry Pi Pico с использованием FreePascal требует внимательности к деталям, особенно в отношении соглашений о вызовах и правильной линковки библиотек. Пример Thaddy является хорошей отправной точкой. Рассмотрите возможность использования объектно-ориентированного подхода для более удобной работы с прерываниями. Убедитесь, что вы правильно настроили тип прерывания и подтягивающие резисторы в соответствии с вашей схемой.
В статье рассматривается настройка обработки прерываний на Raspberry Pi Pico с использованием FreePascal, демонстрируя пример кода и объясняя ключевые моменты, такие как соглашение о вызовах `cdecl`, подключение модулей и выбор типа прерывания.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.