Программа демонстрирует параллельную работу ядра микроконтроллера (printf) и PIO (мигание светодиодом), использование аппаратного ускорения для точного управления временем, автоматизацию сборки с помощью CMake.
PIO (Programmable I/O) - программируемые периферийные блоки RP2040, позволяют создавать собственные протоколы и тайминги.
#include <stdio.h>
#include "pico/stdlib.h"
#include "hardware/pio.h" // Работа с PIO (Programmable I/O)
#include "blink.pio.h" // Автогенерируемый заголовок для PIO программы
// Инициализация программы PIO для мигания светодиодом
void blink_program_init(PIO pio, uint sm, uint offset, uint pin) {
pio_gpio_init(pio, pin); // Настройка GPIO для работы с PIO
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true); // Направление вывода (OUTPUT)
// Получение конфигурации по умолчанию для программы blink
pio_sm_config c = blink_program_get_default_config(offset);
// Настройка набора выводов (в данном случае один пин)
sm_config_set_set_pins(&c, pin, 1);
// Инициализация state machine с заданной конфигурацией
pio_sm_init(pio, sm, offset, &c);
}
// Основная функция для запуска мигания светодиодом
void blink_pin_forever(PIO pio, uint sm, uint offset, uint pin, uint freq) {
// Инициализация программы PIO
blink_program_init(pio, sm, offset, pin);
// Включение state machine
pio_sm_set_enabled(pio, sm, true);
// Расчет и установка значения задержки:
// 125000000 - тактовая частота RP2040 (125 МГц)
// Делим на (2 * freq) так как мигание включает ВКЛ/ВЫКЛ
// -3 для компенсации задержки выполнения инструкций
pio->txf[sm] = (125000000 / (2 * freq)) - 3;
}
int main() {
stdio_init_all(); // Инициализация стандартного ввода/вывода
// Используем PIO блок 0
PIO pio = pio0;
// Загрузка программы blink в память PIO
uint offset = pio_add_program(pio, &blink_program);
// Запуск мигания на встроенном светодиоде с частотой 1 Гц
blink_pin_forever(pio, 0, offset, PICO_DEFAULT_LED_PIN, 1);
// Основной цикл
while (true) {
printf("Hello, world!\n"); // Вывод в консоль
sleep_ms(1000); // Пауза 1 секунда
}
}
Лист. 1. main.c
; Программа мигания светодиодом для PIO (Programmable I/O)
.program blink ; Объявление программы
pull block ; Ожидание данных из FIFO (блокирующий режим)
out y, 32 ; Копирование 32 бит данных в регистр Y (значение задержки)
.wrap_target ; Начало точки цикла (для бесконечного выполнения)
mov x, y ; Копирование значения Y в X (установка счетчика)
set pins, 1 ; Включение светодиода (установка пина в HIGH)
lp1: ; Метка первого цикла задержки
jmp x-- lp1 ; Уменьшение X и переход к lp1 пока X > 0
mov x, y ; Сброс счетчика
set pins, 0 ; Выключение светодиода (установка пина в LOW)
lp2: ; Метка второго цикла задержки
jmp x-- lp2 ; Уменьшение X и переход к lp2 пока X > 0
.wrap ; Конец точки цикла (возврат к .wrap_target)
Лист. 2. blink.pio
# Минимальная требуемая версия CMake
cmake_minimum_required(VERSION 3.13)
# Настройка стандартов языка
set(CMAKE_C_STANDARD 11) # C11
set(CMAKE_CXX_STANDARD 17) # C++17
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Генерация файла компиляции
# === Секция для совместимости с VS Code ===
if(WIN32)
set(USERHOME $ENV{USERPROFILE}) # Домашняя директория Windows
else()
set(USERHOME $ENV{HOME}) # Домашняя директория Linux/Mac
endif()
# Версии компонентов SDK
set(sdkVersion 2.1.1)
set(toolchainVersion 14_2_Rel1)
set(picotoolVersion 2.1.1)
# Подключение специфичных для VS Code настроек
set(picoVscode ${USERHOME}/.pico-sdk/cmake/pico-vscode.cmake)
if (EXISTS ${picoVscode})
include(${picoVscode})
endif()
# ==========================================
# Установка целевой платы (Raspberry Pi Pico)
set(PICO_BOARD pico CACHE STRING "Board type")
# Подключение SDK Pico
include(pico_sdk_import.cmake)
# Создание проекта
project(v06 C CXX ASM) # Проект поддерживает C, C++ и ассемблер
# Инициализация SDK Pico
pico_sdk_init()
# Добавление исполняемого файла (основной файл main.c)
add_executable(v06 main.c)
# Настройка имени и версии программы
pico_set_program_name(v06 "v06") # Имя программы
pico_set_program_version(v06 "0.1") # Версия программы
# Генерация заголовочного файла из PIO программы
pico_generate_pio_header(v06 ${CMAKE_CURRENT_LIST_DIR}/blink.pio)
# Настройка стандартного ввода/вывода
pico_enable_stdio_uart(v06 0) # Отключение UART
pico_enable_stdio_usb(v06 1) # Отключение USB
# Подключение стандартной библиотеки Pico
target_link_libraries(v06 pico_stdlib)
# Настройка путей для include-файлов
target_include_directories(v06 PRIVATE ${CMAKE_CURRENT_LIST_DIR})
# Подключение дополнительных библиотек
target_link_libraries(v06 hardware_pio) # Библиотека для работы с PIO
# Генерация дополнительных выходных файлов (.uf2, .hex и т.д.)
pico_add_extra_outputs(v06)
Лист. 3. CMakeLists.txt
- Замечания:
- Проект создан и компилируется в Visual Studio Code с установленным дополнением Raspberry Pico SDK.
- State Machine - конечный автомат, выполняющий PIO программу.
- wrap_target/.wrap - создание бесконечного цикла в PIO программе
- pico_add_program() - загрузка PIO программы в память микроконтроллера
- pico_generate_pio_header() - автоматическая генерация C-заголовка из PIO файла
- pico_add_extra_outputs() - создание файлов прошивки (.uf2, .hex, .bin)
- project(v06 C CXX ASM) Проект создан в папке PIO_Blink/v06 имя проекта v06 выбрано VS Code автоматически