Вопросы по С/С++ (СИ)

Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

[uquote="ПростоНуб",url="/forum/viewtopic.php?p=3696163#p3696163"]Billi34, мда, это Вам не GCC. У MikroC мозгов намного меньше и о таких косяках он предупреждать не умеет.[/uquote]
:shock:
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="ПростоНуб",url="/forum/viewtopic.php?p=3696168#p3696168"]Напишите просто if(t)[/uquote]Думаешь это поможет пониманию? :)
Реклама
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3696160#p3696160"]Компилятор, однозначно, в топку.[/uquote]
Что мне скачать ? AVR Studio я ставил для другого проекта- для меня слишком сложная среда разработки. Я еще не умею так разрабатывать.

Добавлено after 2 minutes 54 seconds:
[uquote="VladislavS",url="/forum/viewtopic.php?p=3696174#p3696174"][uquote="ПростоНуб",url="/forum/viewtopic.php?p=3696168#p3696168"]Напишите просто if(t)[/uquote]Думаешь это поможет пониманию? :)[/uquote]
Я понимаю что знак равно совсем не равно. Только компилятор "прожевал" это и никто не скажет что так нельзя.
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Billi34",url="/forum/viewtopic.php?p=3696177#p3696177"]Только компилятор "прожевал" это и никто не скажет что так нельзя.[/uquote]Почему же нельзя? Можно! В ногу себе стрелять, в принципе, тоже можно...
Реклама
Эиком - электронные компоненты и радиодетали
Собутыльник Кота
Аватара пользователя
Сообщения: 2723
Зарегистрирован: Пт сен 07, 2018 20:20:02
Откуда: деревня в Тульской губернии

Сообщение ПростоНуб »

[uquote="VladislavS",url="/forum/viewtopic.php?p=3696174#p3696174"][uquote="ПростоНуб",url="/forum/viewtopic.php?p=3696168#p3696168"]Напишите просто if(t)[/uquote]Думаешь это поможет пониманию? :)[/uquote]
Возможно. В любом случае, для приведенного кода это правильно )

Добавлено after 9 minutes 34 seconds:
[uquote="Billi34",url="/forum/viewtopic.php?p=3696177#p3696177"]Я понимаю что знак равно совсем не равно. Только компилятор "прожевал" это и никто не скажет что так нельзя.[/uquote]
В том то и дело, что так можно. Результат операции присваивания определен и равен присваиваемому значению.
Например, выражение:

Код: Выделить всё

  uint8_t i,j,l,k;
  i=((k=3),((j=k*12)+(l=k*3+1)));
совершенно корректно: сначала k будет присвоено значение 3, потом j значение 36 и l значение 10, а затем уже i - значение 46.

Вот только выражение t==1 принимает значение ложь, если t не равно единице, а выражение t=1 - всегда истинно.
Реклама
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

таким образом : if(t==1)
{A}
B

если t равно единице выполняется А
если t равно нулю выполняется В

в моем случае

(t=1) при любом значении t выполняется А
Реклама
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Billi34",url="/forum/viewtopic.php?p=3696263#p3696263"]таким образом : if(t==1)
{A}
B[/uquote]

если t равно единице, то выполняется А, затем B и всё что дальше.
если t равно нулю, то В и всё что дальше.
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

:)
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

Чуть чуть переделал. Теперь по ходу выполнения кода на строке 43 выполняется задержка 0.25 сек. Далее (строка 45) ожидается фронт по PIND.B1 для выполнения фиг. скобок следующих за этим условием: if(PIND.B1&&t). Но по факту фронт на PIND.B1 придет примерно через 0.25 сек. Естественно МК "пролетает" это условие. Как заставить МК ожидать фронт?
Вложения
NewUnit.c
(3.26 КБ) 288 скачиваний
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

[uquote="Billi34",url="/forum/viewtopic.php?p=3696923#p3696923"]Как заставить МК ...[/uquote]Поменять подход к реализации алгоритма.

Почитай про конечные автоматы. Запусти таймер и с определённой частотой анализируй состояние системы. Это тебе позволит точнее с временем работать. А состояния конечного автомата хорошо ложатся на оператор switch. Тебе останется только прописать условия перехода из каждого состояния в другое и соответствующие действия. Поверь, это куда проще отлаживать, чем блуждания по твоим goto с кучей неинформативных переменных-флагов. И не надо спорить, лучше день потерять, потом за 5 минут долететь. Ты и так уже на эту лабуду столько времени убил.
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

Ну я же учусь. goto уже не используются, если вы заметили. switch тоже весьма загадочный оператор, для меня.


1.4.6. Оператор break
Оператор break обеспечивает прекращение выполнения самого внутреннего из объединяющих его операторов switch, do, for, while. После выполнения оператора break управление передается оператору, следующему за прерванным.

очень интересная инфа. Чем то напоминает так не любимый вами goto. Это на самом деле так?
ARV
Ум, честь и совесть. И скромность.
Аватара пользователя
Сообщения: 18788
Зарегистрирован: Чт дек 28, 2006 08:19:56
Откуда: Новочеркасск

Сообщение ARV »

[uquote="Billi34",url="/forum/viewtopic.php?p=3697111#p3697111"]Чем то напоминает так не любимый вами goto. Это на самом деле так?[/uquote]это на самом деле так, это по сути псевдоним оператора goto, как и оператор continue. :) у программистов всегда так: если что-то считается плохим, его можно или обозвать иначе, или прописать с стандарте, как хорошее - и проблема автоматически исчезает :)))
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...

Мой уютный бложик... заходите!
Контактная информация:
Собутыльник Кота
Аватара пользователя
Сообщения: 2567
Зарегистрирован: Вт май 01, 2018 19:44:47

Сообщение VladislavS »

Представляете какой смачный многовариантный goto можно сделать с помощью оператора switch :)
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

БИНГО!!!!!!!!!!!!!!!!!!!
ПаЛуЧиЛоСь.
Заработало как я хотел.
8) 8) 8) 8) 8) 8) 8)

САМ!
САМ!
САМ! Сделал.
Надеюсь прилепился тот файл, с окончательной версией кода.
Вложения
NewUnit.c
(3.14 КБ) 289 скачиваний
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Кошмар.

Код: Выделить всё

 Delay_ms(800) ;  //пауза длиной 0.8 сек
Вот скажите, зачем Вам нужны такие паузы, когда вся система стоит колом?
Контактная информация:
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

Это как говорится "версия для радио". за эти 0.8 сек МК "дергает некоторыми своими ногами". Я сознательно убрал этот код что б вы не пытались его оптимизировать. А попытка оптимизации будет 100% Ваше мышление заточено под ужатие, оптимизацию-поиск изящных решений. А мне вполне достаточно такого вида как у меня. Объем кода очень маленький. Везде умещаюсь.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Лучше попробуйте делать всё это не в основном цикле, а в прерывании.

Заведите аппаратный таймер, для удобства так, чтобы прерывания срабатывали раз в 1мс. Заведите 1 переменную - счётчик, и 2 переменную - событие.

В прерывании от таймера проверяйте, нажата ли кнопка. Если нажата, счётчик нажатий увеличивайте на 1. Если не нажата, счётчик обнуляйте.

При обнулении счётчика (отпускании кнопки) нужно проверить счётчик, если там больше 100 - значит это было полноценное короткое нажатие. Записываем это короткое нажатие в переменную-событие.

Если кнопка нажата долго, и счётчик досчитал до 600 - значит, в переменную-событие нужно записать информацию о длинном нажатии.

Больше ничего в прерывании делать не надо. Только считать и, при необходимости, обновлять переменную-событие.

В основном цикле программы никаких задержек не нужно. Просто в начале цикла вычитываем переменную событие, с обнулением. Если что-то было - выполняем, если ничего не было - ничего и не делаем.

Всё просто. И ни одной задержки, МК 99.9% времени работает в основном полезном цикле.
Контактная информация:
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

Каждый должен заниматься своим делом. Это было для души.
Последний раз редактировалось Billi34 Пн сен 09, 2019 11:42:38, всего редактировалось 1 раз.
Друг Кота
Аватара пользователя
Сообщения: 4905
Зарегистрирован: Чт апр 11, 2013 11:19:59
Откуда: Минск

Сообщение WiseLord »

Ну, если не нужен _понятный_ код, вдвое меньше по размеру и без задержек, в которых МК просто бесполезно висит - то дело хозяйское.

P.S. Вот упрощённый пример для понимания, как это должно работать:
Спойлер

Код: Выделить всё

// Кнопки
#define BTN0    PIND.B0
#define BTN1    PIND.B1

// События
#define EVT_NO          0
#define EVT_BTN0        0x01            // 00000001
#define EVT_BTN1        0x02            // 00000010
#define EVT_BTN0_LONG   (EVT_BTN0 << 4) // 00010000
#define EVT_BTN1_LONG   (EVT_BTN1 << 4) // 00100000

// Длительность нажатий
#define LONG_PRESS      600
#define SHORT_PRESS     100

static volatile uint8_t event = EVT_NO;  // Переменная для хранения события

void isr_timer(void)  // Аппаратное прерывание от таймера, каждые 1мс
{
    static uint16_t btnCounter = 0; // Cчётчик нажатий
    static uint8_t btnPrev = 0;     // Предыдущее нажатие

    uint8_t btnNow = 0;

    // Опрашиваем кнопки
    if (!BTN0)              // нажата кнопка 0
        btnNow |= EVT_BTN0;
    if (!BTN1)              // нажата кнопка 1
        btnNow |= EVT_BTN1;

    if (btnNow) {               // Если кнопка нажата
        if (btnNow == btnPrev) {    // если это всё та же кнопка
            btnCounter++;           // просто наращиваем счётчик
            if (btnCounter == LONG_PRESS) {
                event = (btnNow << 4);      // сохраняем "длинное" событие
            }
        } else {
            btnPrev = btnNow;           // кнопка сменилась, запоминаем
        }
    } else {
        if (btnCounter > SHORT_PRESS && btnCounter < LONG_PRESS) {
            event = btnNow;     // короткое нажатие - сохраняем событие
        }
        btnCounter = 0; // сбрасываем счётчик
    }
}

uint8_t getEvent(void)
{
    uint8_t ret = event;    // значение для возврата
    event = 0;              // событие "забрали", можно обнулять

    return ret;
}

int main(void)
{
    // настраиваем порты
    // ...
    // настраиваем таймер на прерывания раз в 1мс
    // ..
    // поехали...

    uint8_t evt;

    while (1) {
        evt = getEvent();

        switch (evt) {
        case EVT_BTN0:
            // обрабатываем короткое нажатие кнопки 0
            break;
        case EVT_BTN1:
            // обрабатываем короткое нажатие кнопки 1
            break;
        case EVT_BTN0_LONG:
            // обрабатываем длинное нажатие кнопки 0
            break;
        case EVT_BTN1_LONG:
            // обрабатываем длинное нажатие кнопки 1
            break;
        }
    }

    return 0;
}
Контактная информация:
Открыл глаза
Аватара пользователя
Сообщения: 64
Зарегистрирован: Чт июн 09, 2016 18:24:41

Сообщение Billi34 »

:) Спасибо.
Я обязательно по изучаю Ваш пример. Уже появились идейки "нарастить" функционал программы.
Сопутствующий вопрос: это всё ещё на Си или уже С++? Будут ли работать операторы из вашего кода в моем компиляторе?
Ответить

Вернуться в «Разные вопросы по МК»