SoftwareSerial данные недоступны

Второй раз задаю один и тот же вопрос без решения, позвольте уточнить по-другому для ясности.

Я написал программу для Arduino, которая использует два последовательных порта: один аппаратный последовательный порт, а другой порт SoftwareSerial.

Нет проблем с аппаратным последовательным портом, проблема связана с программным последовательным портом.

Вывод Tx программного последовательного порта работает, но вывод Rx не работает, т. е. portone.available() всегда равен нулю, во входном буфере последовательного порта программного обеспечения ничего нет.

Я использую Arduino IDE 1.6.12 с платой Uno. Раньше я использовал версию 1.6.9, но она не работает. Вот кусок кода:

#include <SoftwareSerial.h>

String code = "", customer = "";
bool complete = false;
byte c = 0, j = 0;
char customercode[27];
SoftwareSerial portone(10, 11);
void setup() {
  Serial.begin(9600);
  portone.begin(115200);
  pinMode(10, INPUT);
  pinMode(11, OUTPUT);
  if (Serial) {
    Serial.print("Connecting");
  }    
}

void loop() {
  String copy = "";
  char inchar = '0';

  if (Serial.available() > 0) {
    while (Serial.available()) {
      char bytes = (char)Serial.read();
      if (bytes == '1' || bytes == '2' || bytes == '3' || bytes == '4' || bytes == '5' || bytes == '6' || bytes == '7' || bytes == '8' || bytes == '9' || bytes == '0' || bytes == '.' || bytes == '-' && bytes != '#') {
        customercode[c] = bytes;
        c++;
      } else if (bytes == '#') {
        complete = true;
      }
      if (c > 12 && bytes != '#') {
        code += bytes;
      }
    }

    if (c == 13) {
      customer += '+';
      for (byte i = 0; i < 12; i++) {
        customer += customercode[i];    
      }
    }
  }
  portone.listen();
  if (portone.available() > 0) {
    portone.println("AT+CMGF=1");
    portone.println("AT+CNMI=2,2,0,0,0");
    portone.flush();

    while (portone.available()) {
      inchar = (char)portone.read();
      copy += inchar;
    }
    delay(1);
    Serial.print(copy);

  } else if (complete == true && customercode != "" && code != "") {
    sending();    
  }
  Serial.print(portone.available());
  delay(1000);
}

, 👍0

Обсуждение

SoftwareSerial имеет довольно низкую производительность, и 115200 бит/с, вероятно, требуют слишком многого. Можно ли снизить скорость передачи? Можете ли вы поискать в Интернете альтернативные реализации программного последовательного порта?, @Edgar Bonet

раньше я использовал скорость 9600 бод, но ничего не произошло, поэтому я решил изменить, также я много искал в Интернете, но в итоге не нашел решения. вот почему я решил вернуться снова., @kassim


1 ответ


1

Не вызывайте portone.listen(). Этот метод необходим только в том случае, если вы создали несколько портов SoftwareSerial. Он указывает, какой порт вы слушаете, потому что только один из них может принимать одновременно (вы можете передавать на любой из них в любое время). Он также очищает приемный буфер, чтобы данные из одного порта SoftwareSerial не возвращались по ошибке другим портом. В вашем коде это очищает входной буфер перед проверкой portone.available(). Удивительно, он всегда пуст! ;)

Кроме того, не устанавливайте режим контактов для контактов, используемых для объекта SoftwareSerial. Режимы контактов были установлены во время конструктора portone, что происходит до setup. Вы возитесь с выводами, которые были «обещаны» этой библиотеке для ее собственного использования и контроля.

По совету Эдгара, вам следует рассмотреть более эффективную серийную библиотеку программного обеспечения. AltSoftSerial лучше, но он доступен только на определенных контактах. Моя библиотека NeoSWSerial является лучшей и работает на любых двух контактах, но только на 9600, 19200 и 38400. Обе эти библиотеки могут передавать и получать одновременно, в отличие от SoftwareSerial. Вот ответ со всеми кровавыми подробностями.

И вам действительно следует отказаться от использования класса String. Вы, очевидно, знаете, как использовать массивы char (также известные как «С-строки»). Мы не видим функцию sending(), но вы, вероятно, можете просто распечатать несколько фрагментов вместо того, чтобы создавать полную String и печатать ее:

    portone.print( '+' ); // ведущий плюс
    portone.write( (uint8_t *) customerCode, 13 ); // массив байтов, длина

Было бы лучше завершать массивы символов нулевым байтом (окончание NUL) в loop, чтобы их можно было использовать как стандартную строку C вместо массива байтов:

    customerCode[14] = '\0'; // NUL-завершение строки C

Затем вы можете использовать стандартную строку C print в send:

    portone.print( '+' ); // ведущий плюс
    portone.print( customerCode );

Распечатка фрагментов всегда более эффективна, чем создание большого буфера из всех фрагментов. Это позволяет избежать копирования фрагментов и необходимости вдвое большего объема оперативной памяти.     :P

,

portone.print(code) печатает в модуль GSM, тогда как я могу управлять сообщением, чтобы оно печаталось итерациями мирного сообщения, в то время как полное сообщение должно достигать получателя, и контролировать итерации при получении сообщения от GSM-модуль находится между входным буфером Arduino и GSM, так как он отправляется полным., @kassim

@kassim, если я понимаю ваш вопрос, я думаю, вы спрашиваете о вызове print несколько раз, а не один раз. GSM не видит, сколько было сделано вызовов print, а только то, что было отправлено определенное количество символов. Поскольку на каждый символ уходит около 1 мс, Arduino может начать отправку второй части (т. е. customerCode) почти сразу (~ 0,001 мс) после символа «+». GSM не заметит эту крошечную паузу. Он увидит *почти* непрерывный поток символов. Вероятно, он накапливает символы из Arduino так же, как «loop» накапливает «customerCode»., @slash-dev

Я думаю, что проблема была в библиотеке, потому что я добавил библиотеку AltSoftwareSerial, теперь все в порядке., @kassim