Введение
Добро пожаловать в Демонстрацию нескольких протоколов на Pico! В этом руководстве мы рассмотрим, как использовать Raspberry Pi Pico (RP2040) для одновременной работы с несколькими протоколами: Serial, I2C, SPI и ADC. Это продвинутый пример, объединяющий несколько ключевых навыков разработки встраиваемых систем. Мы соберем схему в симуляторе Velxio, напишем код и разберем каждый шаг.

Обзор схемы
Рассмотрим компоненты и соединения. Схема использует Raspberry Pi Pico (Nano RP2040 Connect) и несколько периферийных устройств:
- Синий светодиод (led-i2c): Подключен к выводу D12 (GP12) через токоограничивающий резистор. Анод (A) подключен к D12, катод (C) — к GND.
- Желтый светодиод (led-spi): Подключен к выводу D7 (GP7) аналогично.
- Потенциометр (pot-adc): Сигнальный вывод (SIG) подключен к A0 (GP26). VCC — к 3.3V, GND — к GND.
- Зеленый светодиод (led-gpio): Подключен к выводу D2 (GP2).
Все светодиоды имеют общий земляной провод. Потенциометр питается от шины 3.3V. Соединения просты, но обратите внимание, что мы используем встроенные периферийные модули I2C и SPI Pico (хотя на схеме это не показано явно, код предполагает их доступность на стандартных выводах).
Разбор кода
Код написан на Arduino C++ и использует библиотеки Wire и SPI. Разберем его по частям.
Setup
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(115200);
delay(500);
Serial.println("==============================");
Serial.println(" Pico Multi-Protocol Demo");
Serial.println("==============================");
Serial.println();
Начинаем с инициализации встроенного светодиода и последовательного порта на скорости 115200 бод. Задержка дает время для подключения монитора порта.
1. Сканер I2C
Wire.begin();
Serial.println("[I2C] Scanning bus...");
int found = 0;
for (byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
if (Wire.endTransmission() == 0) {
found++;
Serial.print(" Found device at 0x");
if (addr < 16) Serial.print('0');
Serial.println(addr, HEX);
}
}
Serial.print(" Total devices: "); Serial.println(found);
Serial.println();
Этот код сканирует все возможные адреса I2C (1-126) и сообщает о тех, которые подтвердили связь. В симуляторе вы можете увидеть виртуальные устройства по адресам 0x50 (EEPROM) и 0x68 (RTC).
2. Чтение/запись EEPROM по I2C
Serial.println("[I2C] EEPROM test at 0x50...");
Wire.beginTransmission(0x50);
Wire.write(0x00); // register 0
Wire.write(0x42); // data
Wire.endTransmission();
delay(5);
Wire.beginTransmission(0x50);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(0x50, 1);
if (Wire.available()) {
byte val = Wire.read();
Serial.print(" Wrote 0x42, Read 0x");
Serial.print(val, HEX);
Serial.println(val == 0x42 ? " — OK" : " — FAIL");
}
Serial.println();
Мы записываем значение 0x42 в регистр 0 EEPROM по адресу 0x50, затем читаем его обратно для проверки. Это тестирует базовую операцию чтения/записи по I2C.
3. RTC по I2C
Serial.println("[I2C] Reading DS1307 RTC at 0x68...");
Wire.beginTransmission(0x68);
Wire.write(0x00);
Wire.endTransmission();
Wire.requestFrom(0x68, 3);
if (Wire.available() >= 3) {
byte sec = ((Wire.read() & 0x7F) >> 4) * 10 + (Wire.read() & 0x0F);
byte min2 = Wire.read();
(void)sec; (void)min2;
Serial.println(" RTC responded OK");
}
Serial.println();
Здесь мы пытаемся прочитать регистры времени из DS1307 RTC по адресу 0x68. Код читает три байта (секунды, минуты, часы), но только проверяет, ответило ли устройство.
4. SPI Loopback
Serial.println("[SPI] Loopback test...");
SPI.begin();
SPI.beginTransaction(SPISettings(1000000, MSBFIRST, SPI_MODE0));
byte tx = 0xAB;
byte rx = SPI.transfer(tx);
Serial.print(" TX: 0x"); Serial.print(tx, HEX);
Serial.print(" RX: 0x"); Serial.println(rx, HEX);
SPI.endTransaction();
Serial.println();
Это простой тест SPI loopback: отправляется 0xAB и читается полученное значение. В симуляторе выводы MISO и MOSI не соединены внешне, поэтому принятое значение может быть 0xFF или другим. Это тестирует аппаратное обеспечение SPI.
5. ADC
Serial.println("[ADC] Reading analog channels...");
analogReadResolution(12);
int a0 = analogRead(A0);
Serial.print(" A0 (GP26): "); Serial.println(a0);
Serial.println();
Мы устанавливаем разрешение АЦП на 12 бит и читаем значение с A0 (GP26). Измеряется напряжение с движка потенциометра, что дает значение от 0 до 4095.
6. Мигание GPIO
Serial.println("[GPIO] Blinking LED...");
for (int i = 0; i < 3; i++) {
digitalWrite(LED_BUILTIN, HIGH);
delay(200);
digitalWrite(LED_BUILTIN, LOW);
delay(200);
}
Serial.println(" 3 blinks done");
Serial.println();
Serial.println("=== All protocol tests complete ===");
}
В конце мы трижды мигаем встроенным светодиодом, чтобы показать завершение настройки.
Loop
void loop() {
// Heartbeat
static unsigned long last = 0;
if (millis() - last >= 3000) {
last = millis();
Serial.print("[Heartbeat] ");
Serial.print(millis() / 1000);
Serial.println("s");
}
}
Цикл выводит сообщение пульса каждые 3 секунды, показывая, что программа все еще работает.
Ключевые концепции
- Интеграция нескольких протоколов: Объединение Serial, I2C, SPI и ADC в одном скетче учит управлять несколькими периферийными устройствами без конфликтов.
- Адресация I2C: Понимание того, как сканировать и общаться с устройствами по конкретным адресам.
- Настройка SPI: Установка тактовой частоты, порядка битов и режима.
- Разрешение АЦП: Использование
analogReadResolution()для получения более высокой точности. - Отладка через Serial: Использование монитора порта для вывода данных в реальном времени.
Частые ошибки и советы по отладке
- Подтягивающие резисторы I2C: У Pico есть внутренние подтяжки, но для длинных проводов могут потребоваться внешние. В симуляторе это обрабатывается автоматически.
- SPI loopback: Без физического замыкания принятые данные могут быть мусором. Используйте перемычку между MOSI и MISO для настоящего теста loopback.
- Шум АЦП: Потенциометры могут быть шумными; добавление конденсатора между движком и землей помогает.
- Несоответствие скорости Serial: Убедитесь, что ваш монитор порта настроен на 115200 бод.
Предлагаемые расширения
- Добавьте внешний датчик I2C (например, температуры/влажности) и выводите его показания.
- Используйте SPI для управления OLED-дисплеем.
- Реализуйте простой регистратор данных, который читает АЦП и сохраняет значения в EEPROM.
- Добавьте кнопку для переключения режимов тестирования.
Попробуйте сами!
Готовы экспериментировать? Откройте живой пример в Velxio и запустите симуляцию. Вы можете изменять код, добавлять компоненты и видеть результаты мгновенно.
Запустить демонстрацию нескольких протоколов на Pico в Velxio



Удачного программирования!