Обсуждаем контроллеры компании Atmel.
Ответить

Re: CodeVision AVR в вопросах и ответах

Чт авг 27, 2020 16:15:24

алгоритм в общем-то прост. данные должны содержать некую регулярность, которую и надо искать. например, пакет всегда начинется с IF и имеет общий размер 11 байт, т.е. кроме первых двух еще 9.

каждый принятый байт надо сравнивать сначала с 'I' - как только встретится, следующий должен быть 'F' - если следующий не совпал, снова начинаем ждать 'I'. когда первые 2 совпали - тупо принимаем 9 байт, обрабатываем их и снова начинаем ждать 'I'...

как-то так.

Re: CodeVision AVR в вопросах и ответах

Чт авг 27, 2020 17:21:33

ARV писал(а):каждый принятый байт надо сравнивать сначала с 'I' - как только встретится, следующий должен быть 'F' - если следующий не совпал, снова начинаем ждать 'I'. когда первые 2 совпали - тупо принимаем 9 байт, обрабатываем их и снова начинаем ждать 'I'...

Спасибо.
Вся длинна 13 байт IF и 11 цифр.
Где то так и сделал в третий раз, но оказалось не все так просто.
Так как после IF должны быть только цифры то выше приведенный алгоритм не подошел, т.к. в некоторых случаях после IF следовали другие символы, видать другие команды.
Так что после того как совпали IF начал проверять что каждый новый 2....13 принятый байт это цифра, если какой либо нет то очищаю принятый буфер и устанавливаю индекс приемного счетчика на ноль, и начинаю анализировать вновь принятые байты.
Теперь вроде работает как надо. :)

Ivanoff-iv писал(а):а кодевижен хороший и в твоих проблемах не виноват

Злой вы какой то.
Написали много а толку ноль.
Если нечего сказать - то лучше всего молчать.

Re: CodeVision AVR в вопросах и ответах

Чт авг 27, 2020 18:00:43

почему?
в вашем вопросе я не уловил, что буквы (префикс) обязательно "if" и нужно просто принять ряд цифр идущих следом...
тогда всё становится гораздо проще:
заводим в этом прерывании локальную статик унсигнед-чар переменную "х"=-2;
при приёме байта: (обозначим его а)
Код:
иф (x<=10))
    {
    иф ((а>="0")&&(a<="9")) //проверяем что принята цифра
        {
        у[х]=а-"0";         //записываем в массив числовые значения принятых цифр
        иф(х<10) {х++;}    //если посылка не полная переходим к следующей ячейке
        else {х=-2; установим флаг успешного приёма;}; //если полная
        }
    else x=-2; //если принята не цифра - возвр. в исходное состояние с поиском "I"
    };
иф (х==-1) {иф (а=="f") {х++;} else x=-2;};  //поиск "F"
иф (х==-2) {иф (а=="i") х++;};  //поиск "I"

и когда в коде увидим взведённый флаг приёма - забираем цифры из массива у.
(порядок ифов такой, чтобы выполнение одного условия не вызвало цепного выполнения остальных, можно кейс или елзе-иф применить...)
я не злой :) видишь :)) улыбаюсь... я люблю помогать людям, но твоё ТЗ показалось мне совсем непонятным... (нужно чтото принять есть 2 буквы... а буквы IF в начале я посчитал вообще - так, для примера...)
Последний раз редактировалось Ivanoff-iv Пт авг 28, 2020 06:11:36, всего редактировалось 3 раз(а).

Re: CodeVision AVR в вопросах и ответах

Чт авг 27, 2020 18:28:23

Ivanoff-iv писал(а):иф (x<=10)) {иф ((а>="0")&&(a<="9")) {иф(х<10) {у[х]=а-"0"; х++;} else {х=-2; установим флаг успешного приёма;};} else x=-2;};

Спасибо конечно.
Но так как я и сказал что я -1(хуже нуля) в С , то написанное, мне представляется какой то не ведомой мне магической строкой, извините.

Ivanoff-iv писал(а):локальную статик унсигнед-чар переменную "х"=-2;

Тут тоже не понял, вроде как без знаковая переменная а имеет значение -2, или я и вправду стар и туп :)

Всяко разно спасибо за желание помочь.
Написал свой кривой код и пусть он работает.

Re: CodeVision AVR в вопросах и ответах

Чт авг 27, 2020 20:15:15

извняюсь, не хотел "давить"
-2 в переменной унсигнед чар это 0xFE (вобщем как и в знаковой) или 254 по русски :)
так мы убиваем сразу 3 зайцев -
1 сравнивать её будет проще (в условии когда считаем цифры, уже одно ограничение останется, а не 2)
2 при заполнении массива переменную х можно использовать в качестве номера элемента
3 считать проще (11 элементов от 0 до 10)
сама переменная обращается в 0 при переполнении (я поправил код, а то и переполнение не использовалось - но это не страшно, и ещё ошибку допустил, а это уже хуже...)

Добавлено after 1 hour 29 minutes 54 seconds:
строка действительно получилась слегка трудноватой для понимания, её следует разбить на несколько расставив перед иф'ами переносы и отступы, я это всё писал с телефона на выгуле собаки и обрамить правильным тегом и выравниваниями (чтоб оно читабельней выглядело) не смог...

Добавлено after 48 seconds:
сейчас попробую поправить...

Re: CodeVision AVR в вопросах и ответах

Чт авг 27, 2020 23:49:43

dibor писал(а):сейчас попробую поправить...

Спасибо.
Попробую ваш вариант тоже, он выглядит намного короче чем я накалякал.

Добавлено after 48 minutes 28 seconds:
Нихт арбайтен :(
даже после исправления синтаксиса '0' вместо "0" и т.д.

Добавлено after 41 minute 49 seconds:
Так работает:
Код:
    char a;
    static char y[14];
    bit done;
    static unsigned char x=-2;
    status = UCSR0A;
     a = UDR0;

if (x<=11)
    {
    if ((a>='0')&&(a<='9'))
        {
        if(x<11) {y[x]=a; x++;}
        else {x=-2; done=1;};
        }
    else x=-2;
    };
if (x==-1) {if (a=='F') {x++;} else x=-2;};
if (x==-2) {if (a=='I') x++;};

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 04:50:13

ещё ошибку нашел...
у[х]=а; нужно вынести из иф и поставить его перед (внутри этой скобки останется только х++;)
и в сравнения верни 10 вместо 11.
ошибка проявляется тем, что нужна ещё одна (12я) цифра в посылке, чтобы взвести флаг. т.е. правильная посылка вида "ИФ###########" будет пропущена, если следом пойдёт буква.
Ошибку в коде исправил, заодно добавил комментарии...
_______
размер массива у достаточно 11, кстати, ты его используешь?
если нет, то убирай его совсем (и все операции с ним тоже),
если да, то почему тут объявлен? его ведь не видно будет из другой части кода?

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 11:10:05

Ivanoff-iv писал(а):у[х]=а-"0";

Что это????
так не работает!
Так работает:
Код:
if (x<=10)
    {
    if ((data>='0')&&(data<='9'))
        {
        y[x]=data;
        if(x<10) {x++;}
        else {x=-2; done=1;};
        }
    else x=-2;
    };
if (x==-1) {if (data=='F') {x++;} else x=-2;};
if (x==-2) {if (data=='I') x++;};


Массив y переписывается в другой когда приняты все данные
Код:
   if (done == 1)
   {
      strcpy(Command_string, y);
        done = 0;
   }


Спасибо!
Еще чему то научился :)

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 11:14:47

Так работает:
Код:
    bit done;
    static unsigned char x=-2;

Done не инициализирована и может быть 1 с самого начала, x присваиваются отрицательные значения, но объявлена она как unsigned ...

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 11:52:50

Reflector,
-2 в переменной унсигнед чар это 0xFE (вобщем как и в знаковой) или 254 по русски :)
беззнаковой я её обозначил только для того, чтобы не случилось казуса при сравнении:
мне нужно выделить интервал [0-10], я поставил одно условие (x<11) если переменная будет со знаком, то и -1 и -2 тоже подпадут под это условие, а в беззнаковом -1 и -2 будут поняты как 255 и 254 соответственно, и в интервал не попадают, что и требовалось.
dibor,
Ivanoff-iv писал(а):у[х]=а-"0";
ну, про кавычки ты уже сам понял, поэтому я и не стал их исправлять...
у[х]=а; загружает в массив ровно то, что прилетело в УАРТ
у[х]=а-'0'; перед загрузкой вычтет порядковый номер символа "0", а т.к. цифры идут по порядку - то останется только значение принятого числа... т.е. произойдет преобразование "0"->0, "1"->1, "2"->2... и.т.д.

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 13:14:52

беззнаковой я её обозначил только для того, чтобы не случилось казуса при сравнении

Можно было спокойно нумеровать состояния начиная с 0, как обычно и делают, потом в одном месте отнять два(у[х - 2] = а). По идее компилятор даже дополнительно отнимать ничего не будет, а просто загрузит для начала массива адрес уменьшенный на 2. Как минимум это избавляет от казусов при чтении исходников :)

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 13:31:32

Да можно,но:
1)вместо if (x<=10) придется писать if ((x>=2)&&(x<=(10+2)))
2 условия вместо одного - код станет длиннее
2)вместо у[х] = а; придется писать у[х - 2] = а;
3)имхо код не станет понятней
так тут сразу видно, что 2 итерации подготовительные

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 13:44:49

Reflector писал(а):Done не инициализирована и может быть 1 с самого начала

Не может.
Если не инициализирована то всегда 0, так написано в документации.

Ivanoff-iv писал(а):у[х]=а-'0'; перед загрузкой вычтет порядковый номер символа "0"

Так не работает!
От каждого принятого символа а будет отниматься '0' ???

Все работает как я опубликовал.
Прекрасный трюк со значением х

Спасибо еще раз.

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 14:01:42

да, так и будет
специально в своем проекте (над которым сейчас работаю) написал outb-='0'; (outb - имеющаяся в проекте переменная)
и квавр в ассемблерной вкладке выдал:
; 0000 002D outb-='0';
LDI R30,LOW(48)
SUB R10,R30

это значит, что из переменной отнялось 48 (0x30 - как-раз то число, которым символ "0" закодирован) и ошибок это не вызвало.
а что не получается у тебя? ошибки компиляции кода или результат работы неправильный?

Добавлено after 3 minutes 35 seconds:
всё, я понял - тебе символы и нужны (а не значения), тогда да, отнимать ничего не надо.

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 16:11:58

Да, бэйсиковый я человек, привык к готовым функциям а тут ничего нет :(
Как вставить символ в уже существующий стринг?
Или надо по символьно переписывать в другой массив с добавлением дополнительного символа?
К примеру надо из стринга 144000000 сделать 144.000.000 для более удобного отображения.

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 16:14:00

Да можно,но:
1)вместо if (x<=10) придется писать if ((x>=2)&&(x<=(10+2)))
2 условия вместо одного - код станет длиннее
2)вместо у[х] = а; придется писать у[х - 2] = а;
3)имхо код не станет понятней

У меня нет компилятора для AVR, тем более CodeVision, но запускаю в Compiler Explorer простенький пример для AVR GCC 9.2.0:
Код:
constexpr unsigned char x = -1;
static_assert(x == -1);

И получаю ошибку компиляции, потому то при сравнении все приводится к int и получаем (0xFF == 0xFFFF), а на STM32 int 32-х битный, там вместо -1 подставит 0xFFFFFFFF. Ну ладно, собираю тестовый пример с твоим кодом, уже для STM32:
Спойлер
Код:
   static char str[] = "IF12GIF01234567895I";
   static char y[10];
   bool done = false;
   uint8_t x = -2;

   for (char* p = str; *p; p++)
   {
      char a = *p;

      if (x <= 10)
      {
         if (a >= '0' && a <= '9')
         {
            y[x] = a;
            if (x < 10)
            {
               x++;
            }
            else
            {
               x = -2;
               done = true;
               break;
            }
         }
         else x = -2;
      }
      if (x == (uint8_t)-1)
      {
         if (a == 'F') x++;
         else x = -2;
      }
      if (x == (uint8_t)-2)
      {
         if (a == 'I') x++;
      }
   }

   rtt.printf<"{}, {}\n">(done, y);   // true, 01234567895

Добавил break и пару приведений к uint8_t, чтобы вообще работало, но в развернутом виде код уже не выглядит таким компактным, как изначально... Теперь пишу свою реализацию:
Спойлер
Код:
   static char str[] = "IF12GIF01234567895I";
   static char y[10];
   bool done = false;
   uint8_t x = 0;

   for(char* p = str; *p; p++)
   {
      char a = *p;
      
      if (x == 0)
      {
         if (a == 'I') x = 1;
      }
      else if (x == 1)
      {
         x = (a == 'F') ? 2 : 0;
      }
      else
      {
         if(a >= '0' && a <= '9')
         {
            y[x - 2] = a;
            if (x++ == 12)
            {
               done = true;
               x = 0;
               break;
            }
         }
         else x = 0;
      }
   }

   cout.printf<"{}, {}\n">(done, y);

Начальное состояние нулевое, никаких дополнительных условий не появилось, нет приведений и для -Os размеры двум бинарников абсолютно одинаковые.

ps. В настройках CodeVision есть "Promote char to int", который по умолчанию еще и вроде выключен, видимо потому код со сравнением (x == -1) и работает...

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 16:27:01

Reflector писал(а):ps. В настройках CodeVision есть "Promote char to int", который по умолчанию еще и вроде выключен, видимо потому код со сравнением (x == -1) и работает...

У меня в настройках это выключено.
Не нравится x==-1 замените на x==255.

Думаю пример приведенный Ivanoff-iv самый короткий.
Так что пригодится еще кому нибудь.

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 17:10:07

Reflector, спасибо за предупреждение... на эти подводные грабли мне ещё предстояло наступить (я начинал в квавр и работаю в квавр, а на СТМ только собираюсь переходить)
впринципе -1 и -2 можно заменить любыми числами >11, только переходы в подготовительных этапах нужно сделать не инкрементом, а присвоением.
dibor, если у тебя получается выводить массив, то проще всего точки добавить прямо в него ещё на этапе заполнения:
при заполнении внутри проверки на окончание посылки там, где инкремент х, допиши
иф ((х%4)==3) {у[х]='.'; х++;};
или иф ((х&0х03)==3) {у[х]='.'; х++;};
// эти выражения дадут одинаковый результат, но второе выполнится быстрее.
и в сравнениях 10 замени на 12.
так он после каждой третьей из четырёх, позиции будет вставлять точку.

Добавлено after 2 minutes 57 seconds:
кстати квавр вроде не понимает конструкции вида иф(х++==12)... :(

Re: CodeVision AVR в вопросах и ответах

Пт авг 28, 2020 18:27:00

Ivanoff-iv писал(а):то проще всего точки добавить прямо в него ещё на этапе заполнения

Этот массив использую для преобразования в число и т.д. поэтому это не вариант, хотя можно заполнять еще один массив параллельно.
Неужели нет наработанных функций как в Васике MID, Right, Insertchar ??

Re: CodeVision AVR в вопросах и ответах

Пн авг 31, 2020 11:54:13

Как преобразовать массив с данными
Mass [3]= {1,5,2} \\то есть три переменные в одну
I=152;

Если я правильно думаю то надо так
I= mass[1]×100+mass[2]×10+mass[3]×1

Да только проблема в том что отправляются 152 в виде знаков asc2
Ответить