Назад

Демонстрация нескольких протоколов на Pico: Serial, I2C, SPI и ADC на RP2040

Введение

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

Схема pico-multi-protocol на холсте симулятора Velxio

Обзор схемы

Рассмотрим компоненты и соединения. Схема использует Raspberry Pi Pico (Nano RP2040 Connect) и несколько периферийных устройств:

Все светодиоды имеют общий земляной провод. Потенциометр питается от шины 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 секунды, показывая, что программа все еще работает.

Ключевые концепции

Частые ошибки и советы по отладке

Предлагаемые расширения

Попробуйте сами!

Готовы экспериментировать? Откройте живой пример в Velxio и запустите симуляцию. Вы можете изменять код, добавлять компоненты и видеть результаты мгновенно.

Запустить демонстрацию нескольких протоколов на Pico в Velxio

Панель инструментов редактора Velxio с кнопками компиляции и запуска

Панель инструментов холста Velxio над окном симуляции

Модальное окно выбора компонентов Velxio с просмотром деталей по категориям

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


Поделиться:
David Montero

Автор

David Montero

Creator of Velxio, the open-source circuit and Arduino simulator.

GitHub velxio.dev

Похожие статьи


Предыдущая статья
Velxio против Wokwi, Tinkercad, Proteus и Fritzing: честное сравнение
Следующая статья
Чтение аналоговых датчиков на Raspberry Pi Pico с Velxio