Невозможно заменить SoftwareSerial на Serial1 на плате Mega.
Этот скетч хорошо работает с определением SoftwareSerial, и на мониторе отображаются значения Modbus устройства. Но теперь я хочу заменить SoftwareSerial на Serial1. и у меня нет данных.
Это скетч с SoftwareSerial:
#include <SoftwareSerial.h>
#define SSerialRX 10 //Пин последовательного приема
#define SSerialTX 11 //Вывод последовательной передачи
#define SSerialTxControl 40 // Управление направлением RS485
#define RS485Transmit HIGH
#define RS485Receive LOW
SoftwareSerial RS485Serial(SSerialRX, SSerialTX); // прием, передача
byte byteSend;
void setup()
{
Serial.begin(9600);
pinMode(SSerialTxControl, OUTPUT);
digitalWrite(SSerialTxControl, RS485Transmit); // Инициализация трансивера
RS485Serial.begin(9600);
}
void loop()
{
delay(500);
if (RS485Serial.available())
{ for(int i=0; i<7; i++)
{
byteSend = RS485Serial.read(); // Читаем байт
Serial.print(byteSend, HEX);
Serial.print(" ");
}
}
digitalWrite(SSerialTxControl, RS485Transmit); // Инициализация трансивера
byte request[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A};
RS485Serial.write(request, sizeof(request));
digitalWrite(SSerialTxControl, RS485Receive);
Serial.println(" ");
}
И скетч, который я пробовал с Serial1 (контакты 19(Rx) и 18(Tx)):
#define SSerialTxControl 40 //Управление направлением RS485
#define RS485Transmit HIGH
#define RS485Receive LOW
byte byteSend;
void setup()
{
Serial.begin(9600);
pinMode(SSerialTxControl, OUTPUT);
digitalWrite(SSerialTxControl, RS485Transmit); // Инициализация трансивера
Serial1.begin(9600);
}
void loop()
{
delay(500);
if (Serial1.available())
{ for(int i=0; i<7; i++)
{
byteSend = Serial1.read(); // Читаем байт
Serial.print(byteSend, HEX);
Serial.print(" ");
}
}
digitalWrite(SSerialTxControl, RS485Transmit); // Инициализация трансивера
byte request[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x01, 0x84, 0x0A};
Serial1.write(request, sizeof(request));
digitalWrite(SSerialTxControl, RS485Receive);
Serial.println(" ");
}
Можете ли вы помочь мне найти мою ошибку?
@Teddol, 👍1
Обсуждение1 ответ
Как лучше всего решить эту проблему, используя Serial1?
При использовании любого последовательного устройства вам необходимо собирать символы, пока не получите полное сообщение. Если каждое сообщение будет иметь фиксированное количество байтов, вы можете подождать, пока возвращаемое значение вызова Serial::available() не укажет, что оно содержит необходимое количество символов, а затем собрать их в буфер и обработать. Но это предполагает, что вы никогда не получите неправильно сформированное сообщение. Если вы это сделаете, входящие байты не будут синхронизированы с вашей программой. Лучший способ — собирать байты в буфер (но ничего с ними не делать) до тех пор, пока вы не получите полное сообщение (по количеству байтов, символу новой строки или как-то еще, когда вам нужно признать, что оно завершено) или пока ваш буфер не переполнится. , а затем либо обработайте их, либо, если ваш буфер заполнен и содержимое не выглядит как допустимое сообщение, отбросьте его и попытайтесь повторно синхронизировать с источником. Это может означать чтение и игнорирование байтов до тех пор, пока вы не получите новую строку, и обработку факта, что вы получили искаженное сообщение, или указание вашему источнику перезапустить или сбросить настройки. Точный метод (или хотите ли вы вообще обнаружить плохие сообщения) зависит от конкретной ситуации. Кто-нибудь умрет, если вы потерпите неудачу? Может ли что-то загореться, сгореть детали, потерять ценные данные за несколько недель...? Или это эксперимент, последствия неудачи которого равны нулю или, по крайней мере, не стоят усилий по его обнаружению?
- Не нашел датчик отпечатков пальцев :( Arduino Mega 2560 Adafruit Fingerprint Sensor
- Серийный порт не инициализируется на Arduino Mega 2560, если питание не подается через порт USB.
- Серийное программное обеспечение и оборудование одновременно
- Прослушивание последовательных портов
- Arduino Mega чтение с внешнего датчика. Проблема
- Последовательная связь между Arduino
- Как разделить входящую строку?
- AT-команда не отвечает на последовательный монитор
ваш код ожидает 7 байт после запроса, доступен ли хотя бы один, @Juraj
https://majko.co.uk/blog/reading-serial-arduino, @Majenko
Извините, но я не понимаю, что вы имеете в виду? Есть ли разница в длине byteSend при использовании SoftwareSerial или Serial1?, @Teddol
Разница, вероятно, связана с тем, что SoftwareSerial::read() занимает полное время символа (около 105 мксек при скорости 9600 бод), поскольку отдельные биты собираются программным обеспечением. При использовании аппаратного UART вызов ::read() занимает всего несколько микросекунд, поскольку биты собираются аппаратно, без задержки программного обеспечения (много...). Таким образом, в аппаратном случае цикл() может выполнять вызов ::read() гораздо чаще, чем могут поступать символы. Короткий ответ: в программной версии вам просто повезло!, @JRobert
Так как же лучше всего решить эту проблему, используя Serial1?, @Teddol
Я пробовал советы Маженко, но на мониторе ничего не было..., @Teddol
Вам нужно дождаться, пока все будет передано, прежде чем отключать управляющий сигнал. Попробуйте добавить Serial1.flush() https://github.com/arduino/ArduinoCore-avr/blob/master/cores/arduino/HardwareSerial.cpp#L205. При поиске на github.com библиотек arduino rs485 каждая библиотека, которую я может найти использование Serial.flush или задержку, позволяющую передать байт перед понижением уровня управляющего сигнала., @Jot
Хорошо, я попытаюсь., @Teddol