Помогите с приемом данных по UART
- Войдите на сайт для отправки комментариев
Друзья, помогите решить следующую задачу. Хочу по UART устанавливать частоту ШИМ. Алгоритм такой: на экран выводится просьба ввести частоту (или скважность), далее то, что мы вводим записываем и пересчитываем. Проблема такая: 1) порт выводит “Vvedite freq” мы вводим число и если оно от 1 до 6, то далее, по идее,
Serial.println("Vvedite duty");
while (Serial.available()==0){};
мы должны ждать ввода скважности, а до того буфер должен быть равен 0 и программа крутиться в пустом цикле. Но у меня получается, что программа сразу после ввода freq продолжает выдавать в порт подряд (т.е. я не ввожу значение duty, а порт выводит следующие надписи друг за другом)
Vvedite duty
Vvedite low frequency
2) Если я хочу ввсти значени частоты например 500, как мне надо его считать, чтобы получить это значение? И сколько байт оно будет занимать?
void loop() { Serial.println("Vvedite freq"); while (Serial.available()==0) { }; val = Serial.read()-'0'; if (1 <= val && val <= 6) { freq1 = val; Duty_1: Serial.println("Vvedite duty"); while (Serial.available()==0){}; val = Serial.read()-'0'; if ((1 <= val <= 100)){ duty1 = val; Freq_2: Serial.println("Vvedite low frequency"); while (Serial.available()==0){}; val_2 = Serial.read(); if ((30 <= val_2 <= 500)){ freq2 = val_2; Duty_2: Serial.println("Vvedite duty low"); while (Serial.available()==0){}; val = Serial.read(); if ((1 <= val <= 20)){ duty2 = val; Period1 = 1/freq1; Impuls1 = Period1*duty1/100; Pause1 = Period1 - Impuls1; freq2=1/freq2*1000000; TimePr: Serial.println("Введите время процедуры"); while (Serial.available()==0){}; val = Serial.read(); if ((1 <= val <= 40)){ timer = val*60*1000; } else { Serial.print("Время процедуры должно от 1 до 40 мин"); delay (1000); goto TimePr; }
Пользуйтесь Serial.parseInt и не мучайтесь. Только предварительно установите достаточно большой таймаут, чтобы если вводящий зазевался, она не соскочила. Всё будет просто и понятно.
А прыгала она у Вас потому, в сериале остался несчитанным перевод строки и потому available() не было нулём. После ввода нужно вычитывать всё лишнее.
К сказанному Евгением можно добавить - оператор goto обычно не используют тыц. А конструкции типа ((1 <= val <= 40) нужно переписать как полагается. И в выражениях типа timer = val*60*1000; указывать тип данных выражения:
timer=(uint32_t) val*60*1000
Благодарю. Скажите, а разве Serial.read() не вычитает из буфера автоматически? Как в таком случае available() обнулить? Перевод строки задается автоматически?
Благодарю. Скажите, а разве Serial.read() не вычитает из буфера автоматически? Как в таком случае available() обнулить? Перевод строки задается автоматически?
Serial.read вычитывает ровно один байт, назевисимо от того, сколько их там скопилось. Вычитать всё можно 100500 способами. например:
Перевод строки взялся оттого, что Вы Enter нажали, когда вводили число.
Евгений, с parseInt() ращобрался как делать. Хочется разобраться и с текущим кодом. Перескоков у меня не происходит , когда я в меню ком порта выбираю вместо значения по умолчанию "новая строка" " нет новой строки" тогда программа работает как надо. При вставке в код
Ничего не меняется, перескок остается. Как убрать эту проблемму программно? Вот куда я поместил вашу строку
Ну, знаете, с этим кодом вообще ничего не понятно. Например, что означают строки 5 и 6 - что Вы этим хотели сказать? Подобных конструкций в стартовом посте много. Что Вы хотели сделать-то? Похоже, Вы вводите символы и как-то странно преобразуете их в числа.
Код неполный ( в старотовм посте тоже) поэтому чего тут скажешь.
В 5 и 6 . После ввода числа проверяем находится оно в требуемом диапозоне (от 1 до 30) если да то продолжаем далее. Суть проекта в следующем: введеное значени частоты (скважности) должно находиться в определенном диапозоне, если оно находится в требуемом диапазоне, то переходим на следующий шаг, если нет , то вывод сообщения об ошибке и повторяем процедуру.
В 5 и 6 . После ввода числа проверяем находится оно в требуемом диапозоне (от 1 до 30)
Вы же вводите с терминала? Вы вводите один байт! Т.е. одну цифру! Не число, а одну цифру! Она может быть от '0' до '9'. После вычитания '0' в строке 5 - она станет от 0 до 9. Но никак не до 30. Следующую цифру надо вводить следующим read(). Понятно? Копайте в эту сторону.
Да Евгений, это исправил. И исправил перескок вставкой delay(100), но делал это на абум, поэтому не совсем понимаю как это сработало, потому что в других примерах задержку не видел чтобы ставили. Теперь фрагмент выглядит так. Может вы знаете почему без delay не работает. Кстати и считывание не происходит нормально без задержки вот тут val = val*10 + (Serial.read()-'0');
delay(100);
Вот смотрите. К Вам пришёл первый байт, а второй ещё не успел. Вы считали первый и ушли, т.к. в сериале ничего нет. Потом пришёл второй, а он уже воспринялся как начало следующего ввода. Задержка же даёт Вам возможность получить все байты сразу и их вычитать.
Евгений, можете подсказать или дать ссылку (не могу найти толковой информации) о режимах передачи. Их дается 4 на выбор, когда какую используем и зачем? И еще один вопрос. Как сделать так чтобы терминал общался на русском языке, мне требуется выводить сообщения на русском в проекте?
о режимах передачи. Их дается 4 на выбор, когда какую используем и зачем?
Это просто последовательный интерфейс. Поищите по словам режимы работы COM потра. Ну, например, - http://www.softelectro.ru/rs232prog.html или ещё где поищите.
Как сделать так чтобы терминал общался на русском языке,
Никогда об этом не думал - не было нужно. Здесь на форуме была тема, там народ что-то писал, поищите.