Привет. Изучаю взаимодействие микроконтроллера с блютузом через SoftwareSerial. Для теста написала метод, который читает буфер до символа новой строки и просто выводит эту часть. И так пока буфер не иссякнет. Столкнулась с поведением, понять которое не хватает мозгов.
Итак, сам метод
void isr() {
static char bt_command[64] = "";
while (mySerial.available()) {
char c = mySerial.read();
if (c == '\r') continue;
if (c != '\n' && c != '*') {
int len = strlen(bt_command);
bt_command[len + 1] = '\0';
bt_command[len] = c;
}
else if (strlen(bt_command) > 0) {
Serial.write("Command: ");
Serial.write(bt_command);
Serial.write('\n');
bt_command[0] = '\0';
}
}
}
Если я вызываю этот метод из loop(), то всё чётко. Такой вывод:
У вас в коде написана жуткая чушь, простите.
Вот смотрите - вот этой строкой вы привязываете свое прерывание к ЛЮБОМУ изменению уровня на пине RX:
Поведайте мне, зачем вы это делаете? Вы вообще понимаете, как идет передача по UART ? байт передается в виде последовательных битов, значит на каждый символ, переданный в порт, у вас прерывание будет вызываться многократно. И каждый раз вы будете пытаться прочитать из порта всю строку.
Это однозначно не будет работать.
Еще раз - зачем все это? Почему не позволить классу Сериал делать это самостоятельно?
Спасибо за пояснение. Я не просто так пишу в разделе для новичков.
Что я хочу? Я хочу реагировать на входящие данные мгновенно. В цикле loop могут быть свои задержки и наверняка будут. Хочется обойти.
Почему не позволить классу Сериал делать это самостоятельно?
Сериал и так умеет в принимать данные и складывать их в буфер, пока работает основная программа. Для того чтобы реагировать на входящие данные быстро - почаще проверяйте наличие в буфере Сериал новых символов да и все.
Serial - да, на хардварном уровне имеет поддержку приема.
Software serial - таковой не имеет, все делает МК в рамках выполнения пользовательских инструкций. Смотрит на пин, складывает биты в байты, байты в буфер и т.д.
Пока МК чухается в монопольно занявшем его ISR, всё летит мимо софтсериала.
Идеальный метод применения этого костыля - метнуть в него запрос и ждать ответа, крутясь во while(). Остальные способы будут привносить “помехи” в поток данных разнообразной степени серьёзности.
я только чуть уточню - СофтСериал тоже делает это асинзронно, хотя и не на аппаратном уровне, но в прерывании.
а смысл? С таким же успехом можно крутится в while(), проверяя mySerial.available() - без всей этой жути в прерывании.
У меня все тот же вопрос - зачем делать за СофтСериал то, что он прекрасно умеет и сам?
мне не хватило мозгов подружить rx tx и tx rx сериала. Казалось бы просто соединить и всё, но даже тестовый скетч не запустился у меня. И так и эдак и я забила. Пока
Но даже если представить, что у меня всё завелось на сериале, то я ведь всё равно тем же способом буду данные собирать. И на прерывание не повесить это дело. Всё сводится к loop. Так что вся суть вашего беспокойства в том, что я потеряла пару пинов?)
Вы путаете теплое с мягким. Так, как вы написали через прерывание - одинаково не будет работать ни с Сериал на стандартных пинах, ни с СофтСериал на других пинах.
А пины вы не потеряли, использовать на одних и тех же пинах и Монитор порта и Блютуз все одно сложно, так что неудивительно, что у вас не получилось.
В целом, нормально объяснили, почему идут искажения. Придется от прерываний отказываться для ресивера. Жаль, что всё же не прояснилось, почему именно в одном и том же месте эти искажения идут.
Отосплюсь и буду думать как по новому логику выстраивать
Давно не залезал в исходники софтварсериала, но подозреваю, что с прерываниями он дружит только при посадке на INTn пины, т.е. надеяться на работу по ISR нужно крайне осмотрительно.