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);
}
@kassim , 👍0
Обсуждение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
- Float печатается только 2 десятичных знака после запятой
- AT-команда не отвечает на последовательный монитор
- Как отправить команду AT на sim800l с помощью SoftwareSerial
- Ардуино для чтения с преобразователя RS232 в последовательный модуль TTL
- Как получить правильный последовательный порт?
- Как связаться с ESP8266 ESP01, отправив данные через программный сериал на Arduino Uno?
- myserial.available() возвращает нулевой байт
- Последовательная связь от Arduino до ESP8266 NodeMCU работает, но от NodeMCU до Arduino не работает
SoftwareSerial имеет довольно низкую производительность, и 115200 бит/с, вероятно, требуют слишком многого. Можно ли снизить скорость передачи? Можете ли вы поискать в Интернете альтернативные реализации программного последовательного порта?, @Edgar Bonet
раньше я использовал скорость 9600 бод, но ничего не произошло, поэтому я решил изменить, также я много искал в Интернете, но в итоге не нашел решения. вот почему я решил вернуться снова., @kassim