Официальный сайт компании Arduino по адресу arduino.cc
% (modulo) оператор и функция millis()
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Всем привет.
Заинтересовался данным оператором и хотел бы у нашего сообщества уточнить некоторую вещь. Буду очень признателен.
Начал рыться в интернете и выяснил как правильно пользоваться данной функцией и что она делает и как считает.
x=5%6 6x0+5 x=5 --- x1=6%5 5х1+1 x1=1
На данный момент использую функцию millis(), прекрасный заменитель delay(), в различных скетчах.
if (millis() - time > 1000){ //---// time = millis(); }
Но недавно увидел выражение
if (millis()%1000 == 0){ //---// }
Первый и второй вариант выполняют одно и тоже, но второй вариант более экономичный как по написанию, так и по использованию ресурсов микроконтроллера.
Расскажите пожалуйста, как работает второй вариант. Ведь millis() постоянно нарастает, а функция постоянно выполняется раз в секунду. Получается при использовании millis() с % каким-то образом обнуляют счетчик или что? Бред конечно, но не могу просто понять.
И есть ли минусы у второго варианта? Переполнения вроде нет.
миллис растет и остаток от деления на 1000 растёт, до целой тысячи
если что то будет задерживать процессор (прерывание какое нибудь), то ==0 может не выполняться с разной периодичностью
ну и на границе uint32 100% будет один неверный интервал
Второй вариант может отработать несколько раз подряд, а может и пропустить цикл. Не годится ни для чего серьезнее мигания светодиодами.
Получается при использовании millis() с % каким-то образом обнуляют счетчик или что?
похоже, вы так и не поняли, что такое оператор %. Это же просто взятие остатка от деления. Что тут может быть непонятного? Это действие в школе проходят. по-моему в классе в четвертом...
Выражение millis()%1000 ничего не обнуляет, оно просто отбрасывает из значения счетчика все что больше тысячи. Для простоты можете считать, что в результате от числа просто отбрасываются все цифры левее третьей:
1234 -> 234
123456 -> 456
5000 -> 0
Что касается использования конструкции
для замена delay и прочего измерения интервалов - то это плохая практика. не привыкайте к ней. Дело в том. что условие в скобках if срабатывет только при точном равенстве , которое длится только одну тысячную периода. Если ваша программа исполняется медленеее 1 миллисекунды - вы можете просткочить этот момент и интервал времени начнется заново, соответвенно ваша задержка уже будет не 1 сек. а две. А через две секунды оно может так же проскочить и так далее
>> И есть ли минусы у второго варианта?
добавлю к сказанному - это еще и тормоза...
Регулярно использую "%".
Но в основном для ограничения верхнего значения переменной, если нижний предел значения 0.
Выглядит примерно так:
int value;
if(//условие)value++;
if(//другое условие )value--;
value=(value+Max_value)%(Max_value+1);
Позволяет в одной строке зациклить значения при выборе значения переменной
для нижней границы работает. для верхней нет - то есть дает не Max_value, а Max_value-1
Значит написал немного не то, что использую
Потому, что таких проблем вроде не было
И действительно:
h=((h+24)-1)%24;
Вот так оно должно выглядеть.
Конкретно эта строка взята из часов, а точнее из установки времени.
Дальше идёт:
tm.Hour=h;
RTC.write(tm);
h=((h+24)-1)%24;
Вот так оно должно выглядеть.
и опять что-то не то. Это выражение эквивалентно записи h = h-1; - что явно не то, что вы хотели сделать, никакого выравнивания по границе тут нет
Может просто вот так:
value=(value+Max_value)%(Max_value);
Дешевле на min/max проверять, чем остаток искать. В ассемблере первое будет простым джампом по условию, а второе, полагаю, - целой подпрограммой с делением, умножением, вычитанием...