Продолжаем разбирать код, впрочем у меня оно уже полгода работает,и через полгода вернувшись к тексту всё понятно, дело привычки. Впрочем, все рекомендации принимаем к сведению.Уменьшив код,можно еще накидать дополнительных функций.
Да почему же, действительно, в секундном прерывании я лишнего написал,поправил,проверил,если буду снимать устройство,или для будущего проекта,то уже с изменениями, исполнение сего кода у меня уменьшилось с 2.5мкс до 1мкс.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Еще вопрос о правилах "хорошего тона". Можно писАть
Код:
if (delay != 0) delay --;
а можно
Код:
if (delay) delay --;
Насколько эстетичны такие сокращения с точки зрения "профессиональных любителей" ? Ну типа, фыркаете ли Вы, видя такое в чужом коде, или нормально относитесь ?
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Ну типа, фыркаете ли Вы, видя такое в чужом коде, или нормально относитесь ?
дело не в том, фыркают ли другие... дело в том, видите ли вы полезный смысл в написанном или нет. у каждого своё понимание перфекционизма, но любой перфекционизм ради перфекционизма плох.
если вы НИКОГДА не будете проверять В ЭТОМ МЕСТЕ delay на равенство чему-то отличному от нуля, смысла писать != 0 нет. но если логика программы или избранного вами алгоритма такова, что ВОЗМОЖНЫ варианты, когда delay может сравниваться с чем-то еще - то стоит задуматься... а не правильнее ли написать delay != DELAY_LIMIT, определив DELAY_LIMIT равным 0, но подразумевая, что там может быть и нечто иное?
а вот -- или ++ я лично никогда не отделяю от операнда пробелом
Ну хорошо, наверняка здесь есть хорошо владеющие СИ, вот прокомментируйте сей код, насколько он кошмарный/некошмарный, само устройство на нем работает как я и задумывал, но может как-то можно код сократить/улучшить без потери функциональности? Если кому понадобится могу скинуть весь проект+схема в протеусе. Кто что скажет?
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
// Функция определяет число дней в месяце, уже с учётом високосных годов static uint8_t DaysInMonth(void) { uint8_t ret = month; if (ret == 2) { ret = year & 0x03; ret = (ret ? 29 : 28); } else { if (ret > 7) ret++; ret |= 30; } return ret; } // Дальше логика автора: if (day > DaysInMonth()) { day = 1; month++; } if (month >= 12) { year++ }
// Функция определяет число дней в месяце, уже с учётом високосных годов static uint8_t DaysInMonth(void) { uint8_t ret = month; if (ret == 2) { ret = year & 0x03; ret = (ret ? 29 : 28); } else { if (ret > 7) ret++; ret |= 30; } return ret; } }
1)
Код:
ret = (ret ? 29 : 28);
29<==>28 помянять бы местами 2) 2100 (2200) году будет неверно работать, но это уже мелочи. 3) чтобы понять, надо напрячься комментарий бы добавить к строке " ret |= 30;" завести массив кол-ва дней в месяцах (во флеш памяти) и индексироваться - просто, понятно с первого взгляда, и займен не намного больше места
то разница с функцией на основе таблицы получается 24 байта для STM32F4. А хотя нет, похоже это из-за того, что я функцию в цикле вызывал, без него 12 байт.
Выносить определение високосности в отдельную функцию (по желанию inline) и всегда (во всех проектах) использовать ее Спойлер
Код:
/* * високосный ли год * year (c 2000-го года): 0=2000, 1=2001, ... * * c 2000 по 2255 годы: 2100 и 2200 не являются високосными */ __INLINE__ bool_t is_leap_year (uint8_t year) { if (year & 0x03) return 0;
#ifdef LEAP_YEAR_EXEPTIONS /* съэкономим несколько байт, если не проверяем исключения (годы: 2100 и 2200)*/ if (year == 100 || year == 200) return 0; #endif
return 1; }
Тогда Ваш код еще понятней станет (не очивидные с первого взляда места я бы откомментировал): Спойлер
Хотим сохранять конфигурацию в EEPROM. Отлично. Зачем? Чтобы при сбросе/включении начать работать с сохраненной конфигурацией. 1) Пользователю не интересно видеть сообщение "TEST EEPROM OK! " Зачем оно? Если при включении самотестирование проходит - молча начинаем работать. Представьте, включаете Вы телевизор, а там:
2) У вас есть конфигурация устройства. Так? Не вижу причин не зафиксировать это средствами языка программирования (объявить соотвктствующую структуру):
Код:
typedef struct _device_config_t { // здесь все параметры конфигурации } device_config_t;
3) mass[] - конфигурация в SRAM eep_mass[] - конфигурация в EEPROM. Так? Непонятно, зачем их сравнивать. mass откуда берется? Читается из EEPROM? Т.е. Вы прочитали EEPROM, работаете-работаете, а затем обнаруживаете, что EEPROM (или конфигурация в SRAM) странным образом изменилась.
При старте устройства желательно бы проверить целостность конфигурации в EEPROM (например, питание устройства может быть отключено в момент записи конфигурации), выбирайте: a) в EEPROM хранить контрольную сумму б) в EEPROM держать несколько копий в) комбинация двух методов г) что-то еще
3) Раз есть конфигурация, то нужны: a) функция сброса параметров конфигурации в значения по умолчанию. Т.е. если обнаружено, что в EEPROM лежит каая-то фигня, то надо привести конфигурацию в заведомо правильное состояние (значения по умолчанию, заводские установки - называйте как хотите)
Код:
void device_default_config (device_config_t* c) { // устанавливаем значения по умолчанию }
/* например, есть функции чтение байта из EEPROM по указанному адресу */ uint8_t eeprom_read_byte (unsigned addr); /* мы хотим контолировать целестность сохраненной конфигурации посредсвом контрольной суммы */ uint16_t cksum_update (uint16_t cksum, uint8_t);
/* возвращает 0, если в EEPROM лежит плохая конфигурация, и значения конфигурационных параметров установлены в начальное состояние */ bool_t device_load_config (device_config_t* c) { uint8_t data; uint16_t cksum = CKSUM_INIT_VALUE; /* начальное значение контрольной суммы */ uint16 addr = DEVICE_CONFIG_ADDR; /* начиная с DEVICE_CONFIG_ADDR лежит конфигурация устройства */ uint8_t *p = (uint8_t *) (c); uint8_t *limit = p + sizeof (*c);
функция device_load_config () будет нормально работать во ВСЕХ ваших проектах, достаточно чтобы была определена device_config_t, функции чтения EEPROM, функции контрольной суммы.
в) функцию сохранения конфигурационных параметров. г) ...
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 32
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения