Arduino M0 - программный интерфейс Serial (SERCOM) - не работает на пинах D3 и D4

traveler
Offline
Зарегистрирован: 27.09.2018

Всем доброго дня! Столкнулся с необходимостью инициализировать программный интерфейс Serial на Arduino M0 (библиотека SoftwareSerial на платах с 32-битными процессорами не работает). Имеющийся аппаратный интерфейс занят конвертером TTL-RS485, а подключить по интерфейсу SPI нужно еще один девайс - SIM800L.

Почитал ресурсы, еще почитал (тут именно про пины D3 и D4), и еще почитал. В результате получилось инициализировать Serial на пинах D11(RX) и D10(TX):

#include <Arduino.h>                   
#include "wiring_private.h"             // Библиотека даёт возможность изменения функций пинов МК (pinPeripheral() function)

Uart SIM800L (&sercom1, 11, 10, SERCOM_RX_PAD_0, UART_TX_PAD_2);    // Назначаем функции пинам МК: RX - pin D11 | TX - pin D10

String _response = "";                  // Объявляем строковый массив для хранения ответов модуля SIM800L (функции sendATcommand и waitResponse)

void setup() {
  SerialUSB.begin(57600);
  while (!SerialUSB) {};                // Ожидание инициализации com-порта
  SerialUSB.println(F("Start programm!"));
  SIM800L.begin(57600);

  pinPeripheral(10, PIO_SERCOM);        // TX (Assign pins 10 & 11 SERCOM functionality)
  pinPeripheral(11, PIO_SERCOM);        // RX (Assign pins 10 & 11 SERCOM functionality)

  sendATcommand("AT", true);            // Автоопределение скорости обмена данными с модулем SIM800L
}

void SERCOM1_Handler()
{
  SIM800L.IrqHandler();
}

void loop()
{
  if (SIM800L.available()) SerialUSB.println(waitResponse());
  if (SerialUSB.available()) SIM800L.write(SerialUSB.read());
}

String sendATcommand(String cmd, bool waiting)
{
  String _resp = "";
  SerialUSB.println(cmd);
  SIM800L.println(cmd);
  if (waiting)
    {
      _resp = waitResponse();
      SerialUSB.println(_resp);
    }
  return _resp;
}

String waitResponse()
{
  String _resp = "";
  unsigned long _timeout = millis() + 10000;
  while (!SIM800L.available() && millis() < _timeout) {};
  if (SIM800L.available())
    {
      _resp = SIM800L.readString();
    }
  else
    {
      SerialUSB.println(F("Timeout wait answer SIM800L is over!"));
    }
  return _resp;
}

Этот код работает... При обращении к модулю SIM800L - возвращаются ответы от модуля.

При попытке инициализировать Serial на пинах D3(RX) и D4(TX) следующим образом:

#include <Arduino.h>   
#include "wiring_private.h"             // Библиотека даёт возможность изменения функций пинов МК (pinPeripheral() function)

Uart SIM800L (&sercom2, 3, 4, SERCOM_RX_PAD_1, UART_TX_PAD_0);

String _response = "";                  // Объявляем строковый массив для хранения ответов модуля SIM800L (функции sendATcommand и waitResponse)

void setup() {
  SerialUSB.begin(57600);
  while (!SerialUSB) {};                // Ожидание инициализации com-порта
  SerialUSB.println(F("Start programm!"));
  SIM800L.begin(57600);

  pinPeripheral(4, PIO_SERCOM_ALT);         // TX (Assign pins 10 & 11 SERCOM functionality)
  pinPeripheral(3, PIO_SERCOM_ALT);         // RX (Assign pins 10 & 11 SERCOM functionality)

  sendATcommand("AT", true);            // Автоопределение скорости обмена данными с модулем SIM800L
}

void SERCOM2_Handler()
{
  SIM800L.IrqHandler();
}

void loop()
{
  if (SIM800L.available()) SerialUSB.println(waitResponse());
  if (SerialUSB.available()) SIM800L.write(SerialUSB.read());
}

String sendATcommand(String cmd, bool waiting)
{
  String _resp = "";
  SerialUSB.println(cmd);
  SIM800L.println(cmd);
  if (waiting)
    {
      _resp = waitResponse();
      SerialUSB.println(_resp);
    }
  return _resp;
}

String waitResponse()
{
  String _resp = "";
  unsigned long _timeout = millis() + 10000;
  while (!SIM800L.available() && millis() < _timeout) {};
  if (SIM800L.available())
    {
      _resp = SIM800L.readString();
    }
  else
    {
      SerialUSB.println(F("Timeout wait answer SIM800L is over!"));
    }
  return _resp;
}

Этот вариант кода при обращении к модулю SIM800L возвращает превышение таймаута ожидания ответа от модуля "Timeout wait answer SIM800L is over!".

Кто "копал" SERCOM и M0 - подскажите куда копать в какую сторону? Пины D11 и D10 использовать не могу - на них висит SPI и SD-Card Module, помогите советом кто в теме, буду очень признателен!!!

traveler
Offline
Зарегистрирован: 27.09.2018

В общем и целом разобрался. Скорее всего, тему поднял не в соответсвующей ветке форума. Для кого интересно... Использовать можно sercom1, sercom2, sercom3, sercom4. Использовать sercom0 и sercom5 неполучиться, т.к. они задействованы аппаратно и обратный вызов не возможен - компиляция не проходит из-за ошибки оверхеда. Приведу пример для пинов D7(RX) и D6(TX):

#include <Arduino.h>
#include "wiring_private.h"

Uart mySerial (&sercom3, 7, 6, SERCOM_RX_PAD_3, UART_TX_PAD_2);  // Инициализация объекта класса UART на пинах 6(TX) и 7(RX)

void setup() {
mySerial.begin(57600);

  pinPeripheral(6, PIO_SERCOM_ALT);     // TX pin UART (SERCOM) - переопределение пинов МК
  pinPeripheral(7, PIO_SERCOM_ALT);     // RX pin UART (SERCOM) - переопределение пинов МК
}

void SERCOM3_Handler() {mySerial.IrqHandler();}  // Функция обработки прерывания

void loop() {
}

Аналогично работает на остальных пинах, с вышеуказанными sercom'и.