Помогите с приемом данных по UART

Ruan
Offline
Зарегистрирован: 04.09.2016

Друзья, помогите решить следующую задачу. Хочу по 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;
        }

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Пользуйтесь Serial.parseInt и не мучайтесь. Только предварительно установите достаточно большой таймаут, чтобы если вводящий зазевался, она не соскочила. Всё будет просто и понятно.

А прыгала она у Вас потому, в сериале остался несчитанным перевод строки и потому available() не было нулём. После ввода нужно вычитывать всё лишнее.

dimax
dimax аватар
Offline
Зарегистрирован: 25.12.2013

К сказанному Евгением можно добавить - оператор goto обычно не используют тыц.   А  конструкции типа ((1 <= val <= 40) нужно переписать как полагается. И в выражениях типа timer = val*60*1000; указывать тип данных выражения: 

timer=(uint32_t) val*60*1000

Ruan
Offline
Зарегистрирован: 04.09.2016

Благодарю. Скажите, а разве Serial.read() не вычитает из буфера автоматически? Как в таком случае available() обнулить? Перевод строки задается автоматически?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ruan пишет:

Благодарю. Скажите, а разве Serial.read() не вычитает из буфера автоматически? Как в таком случае available() обнулить? Перевод строки задается автоматически?

Serial.read вычитывает ровно один байт, назевисимо от того, сколько их там скопилось. Вычитать всё можно 100500 способами. например:

while (Serial.available()) Serial.read();

Перевод строки взялся оттого, что Вы Enter нажали, когда вводили число.

Ruan
Offline
Зарегистрирован: 04.09.2016

Евгений, с parseInt() ращобрался как делать. Хочется разобраться и с текущим кодом. Перескоков у меня не происходит , когда я в меню ком порта выбираю вместо значения по умолчанию "новая строка"   " нет новой строки" тогда программа работает как надо. При вставке в код


1 while (Serial.available()) Serial.read(); 

Ничего не меняется, перескок остается. Как убрать эту проблемму программно? Вот куда я поместил вашу строку

void loop() {
  Serial.println("Vvedite freq");
  while (Serial.available()==0) {
    };
    val = Serial.read()-'0';
    if (1 <= val && val <= 30) {
      freq1 = val;
      Serial.println(val);
      while (Serial.available()) Serial.read();
Duty_1: Serial.println("Vvedite duty");
       while (Serial.available()==0){
        };
       val = Serial.read()-'0';
       if ((1 <= val && val <= 100)){
        duty1 = val;
Freq_2: Serial.println("Vvedite low frequency");
       while (Serial.available()==0){};
       val_2 = Serial.read();
       if ((30 <= val_2 && val <= 500)){
        freq2 = val_2;

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ну, знаете, с этим кодом вообще ничего не понятно. Например, что означают строки 5 и 6 - что Вы этим хотели сказать? Подобных конструкций в стартовом посте много. Что Вы хотели сделать-то? Похоже, Вы вводите символы и как-то странно преобразуете их в числа.

Код неполный ( в старотовм посте тоже) поэтому чего тут скажешь.

Ruan
Offline
Зарегистрирован: 04.09.2016

В 5 и 6 . После ввода числа проверяем находится оно в требуемом диапозоне (от 1 до 30) если да то продолжаем далее. Суть проекта в следующем: введеное значени частоты (скважности) должно находиться в определенном диапозоне, если оно находится в требуемом диапазоне, то переходим на следующий шаг, если нет , то вывод сообщения об ошибке и повторяем процедуру.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ruan пишет:

В 5 и 6 . После ввода числа проверяем находится оно в требуемом диапозоне (от 1 до 30)

Вы же вводите с терминала? Вы вводите один байт! Т.е. одну цифру! Не число, а одну цифру! Она может быть от '0' до '9'. После вычитания '0' в строке 5  - она станет от 0 до 9. Но никак не до 30. Следующую цифру надо вводить следующим read(). Понятно? Копайте в эту сторону.

Ruan
Offline
Зарегистрирован: 04.09.2016

Да Евгений, это исправил. И исправил перескок вставкой delay(100), но делал это на абум, поэтому не совсем понимаю как это сработало, потому что в других примерах задержку не видел чтобы ставили. Теперь фрагмент выглядит так. Может вы знаете почему без delay не работает. Кстати и считывание не происходит нормально без задержки вот  тут  val = val*10 + (Serial.read()-'0');
                            delay(100);

void loop() {
  Serial.println("Vvedite freq");
  while (Serial.available()==0) {
    };
    val = 0;
    while (Serial.available()){
    val = val*10 + (Serial.read()-'0');
    delay(100);
    }
    if (1 <= val && val <= 30) {
      freq1 = val;
     Serial.println(val);
      delay(100);
      while (Serial.available()) Serial.read();
Duty_1: Serial.println("Vvedite duty");

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Вот смотрите. К Вам пришёл первый байт, а второй ещё не успел. Вы считали первый и ушли, т.к. в сериале ничего нет. Потом пришёл второй, а он уже воспринялся как начало следующего ввода. Задержка же даёт Вам возможность получить все байты сразу и их вычитать.

Ruan
Offline
Зарегистрирован: 04.09.2016

Евгений, можете подсказать или дать ссылку (не могу найти толковой информации) о режимах передачи. Их дается 4 на выбор, когда какую используем и зачем? И еще один вопрос. Как сделать так чтобы терминал общался на русском языке, мне требуется выводить сообщения на русском в проекте?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ruan пишет:

о режимах передачи. Их дается 4 на выбор, когда какую используем и зачем? 

Это просто последовательный интерфейс. Поищите по словам режимы работы COM потра. Ну, например, - http://www.softelectro.ru/rs232prog.html или ещё где поищите.

Ruan пишет:

Как сделать так чтобы терминал общался на русском языке, 

Никогда об этом не думал - не было нужно. Здесь на форуме была тема, там народ что-то писал, поищите.