Ошибка компилятора версии 1.6.7
- Войдите на сайт для отправки комментариев
У меня в программе выводятся значения времени из DS1307 на четырехразрядный индикатор (можно брать семисегментные или матричные, неважно). Из собственно часов значения поступают в упакованном BCD-коде, но библиотека RTC преобразует их в десятичные значения. Для четырехразрядного индикатора нужны по отдельности значения десятков и единиц часов и минут, что удобнее извлекать как раз из BCD-значений.
Чтобы не переписывать библиотеку, сначала делается обратная операция (decToBcd), а затем распакованные полубайты по отдельности посылаются на индикаторы:
clock.getTime(); C_clock = (decToBcd(clock.minute) & 0x0F)+0x30;//младший полубайт минут writeChar(C_clock,dig3); C_clock = (decToBcd(clock.minute)>>4)+0x30; //старший полубайт минут writeChar(C_clock,dig2); C_clock = (decToBcd(clock.hour) & 0x0F)+0x30; //младший полубайт часов writeChar(C_clock,dig1); C_clock = (decToBcd(clock.hour)>>4)+0x30; //старший полубайт часов writeChar(C_clock,dig0);
Функция вывода writeChar к делу отношения совершенно точно не имеет, так как тупо посылает символ в индикаторы (прибавление числа 0x30 как раз и требуется для формирования кода символа из значения полубайта).
Так вот, скомпилированная в среде 1.6.7, эта процедура работает с ошибкой. При переходе от 9 часов утра к 10 и в полночь (когда 24 меняется на 00) вместо правильного старшего полубайта значения часов (т.е. десятков часов), равного, соотвественно, 1 и 0, зависают предыдущие значения 0 и 2. Перезагрузка контроллера исправляет положение, но только до следующего такого перехода. Кстати, смена порядка загрузки значений (если начинать в обратном порядке, именно с десятков часов) ничего не меняет: ошибка почему-то именно в старшем полубайте часов. Сами часы при этом читаются правильно: контрольный вывод десятичных значений на строчный индикатор это показал.
Скомпилированная ранее в версии 1.0.4, программа такой ошибки не выдавала. Исследования причин проблемы затянулись, потому что после каждого исправления приходилось ждать полсуток до очередного перехода (искусственная загрузка значений часов ошибки не дает). В результате твердо установлено, что дело именно в версии компилятора - чего-то там они переоптимизировали. Ошибка также не возникает в альтернативной Arduino IDE 1.7.10 (естественно, с теми же библиотеками, что применялись и в 1.6.7). В последней версии 1.6.9 не проверял: надоело возиться, если честно.
Это не первая замечанная ошибка подобного рода, который в принципе не должно происходить. В одной программе, где происходит побайтное сравнение введенного пин-кода с образцом по "исключающему ИЛИ", в последнем возникала ошибка, причем детальное исследование показало, что неправильный именно результат операции. Тогда я не догадался, что причина в новом компиляторе, а сейчас схема (довольно навороченная) уже разобрана, компоненты использованы и возвращаться к ней лень. Но теперь я уверен, что и там все заработает правильно, если применить нужную версию.
Юра, а Вы не могли бы, если не трудно, выделить минимальный скетч (как можно меньше по размеру) в котором ошибка воспроизводится и показать его?
Извиняюсь, что не по теме. Чем не нравиться такой вариант:
% - очень "дорогая" операция на дуньках. :)
% - очень "дорогая" операция на дуньках. :)
Да как бы и деление не дешевая.
Единственная надежда, что оптимизатор сможет найти и частное и остаток за один проход алгоритма деления.
Отвечаю всем сразу: оторвал свою обленившуюся задницу от стула и за прошедшие сутки проверил в версии 1.6.9 (ничего не меняя в коде). Все работает без каких-либо сбоев. Так что это, видимо, глюк, характерный только для 1.6.7. Возможно, также для каких-то других промежуточных версий - та история с "исключающим ИЛИ" происходила в версии 1.6.4. Резюме: к промежуточным версиям надо относиться с осторожностью и при возникновении необъяснимых проблем сразу пробовать в другой.
Извиняюсь, что не по теме. Чем не нравиться такой вариант:
Отдельно отвечу: функция decToBcd именно это и делает оптом, так понятнее:
И если уж оптимизировать и экономить, то тогда лучше уж начать с правки библиотеки RTC, где исключить преобразование BcdTodec, ибо оно нам тут не требуется. Меня время исполнения операции не волнует, потому я этим заниматься не стал - часы-минуты нужны в BCD, а все остальное по прежнему в обычном числовом виде, и потом только запутаешься, куда там чего преобразовывать.
Да как бы и деление не дешевая.
Единственная надежда, что оптимизатор сможет найти и частное и остаток за один проход алгоритма деления.
Так используйте функцию div - она именно это и делает.
Отдельно отвечу: функция decToBcd именно это и делает оптом, так понятнее:
Вопрос: где Вы усмотрели тождество.
Отдельно отвечу: функция decToBcd именно это и делает оптом, так понятнее:
Вопрос: где Вы усмотрели тождество.
Не, я понял разницу, не дурак. Но повторяю, что тогда уж начинать с самого начала, с библиотеки - в чипе часы хранятся в BCD. А так, через единообразную функцию, понятнее.
К сведению всех заинтересованных в теме: глюк со старшим разрядом часов опять проявился. 19-го я загрузил в версии 1.6.9, к 20-му ничего не проявилось и я успокоился. Вчера выключали свет и система перезапускалась, в результате ночью выплыла двойка в старшем разряде часов. Пока упростил загрузку так, как посоветовал fogary, загрузил снова и будем посмотреть - вдруг действительно это на что-то повлияет. Наверное, не меньше двух-трех дней надо будет. Если не получится, буду опять играться с версиями, пока не дойду до стабильной.
Испытания завершил, больше ничего придумать не могу. Резюме следующее: глюк проявлялся ТОЛЬКО в расширенной навороченной версии часов, объединенных с разными датчиками, где еще участвует куча библиотек и разных функций. И проявляется она только при компиляции через современные версии (1.6.7, 1.6.9, альтернативную 1.7.10 с теми же самыми библотеками), при загрузке через 1.0.4 никакого глюка не наблюдается. Распаковку кода делал по методу fogary для упрощения, это ни на что не влияет.
Самое же главное - глюки исчезли, когда я выкинул из программы все, кроме собственно часов. Это работало безупречно. То есть налицо какая-то интерефенция библиотек и многочисленных переменных. Я думаю, что там где-то какая-то малозаметная ошибка в распределении ОЗУ под переменные, которая проявляется только вот в таких экстремальных условиях. Искать ее конкетно - выше моих сил, учитывая, что каждое испытание длится более суток минимум.