Вот вы эту простыню зачем тут запостили? Вместо неё лучше бы расшифровали, что за фигня у вас пишется вместо 1, 2 - больше толку было бы. Но скажу вам следующее, возможно, что-то окажется полезным: 1. функций для записи есть несколько: для байта, слова (2 байта), для двойного слова (4 байта) и для блока произвольной длины. выбирайте ту, которая вам больше подходит для данных, и не ломайте голову напрасно 2. функции, содержащие вместо write слово update в своем названии предназначены для продления ресурса записи в EEPROM: прежде чем записать ячейку, эти функции считывают ее и сравнивают с новыми данными - если новые данные не отличаются от уже имеющихся в ячейке, запись не выполняется. так что эти функции работают медленнее, но менее изнашивают EEPROM. повлиять на ваши "чудеса" они не смогут никак. 3. протеус корректно отрабатывает длительность записи в EEPROM (около 4 мс), поэтому при прогоне по шагам программы сразу после выполнения функции записи вы не увидите в дампе EEPROM никакого обновления одного байта, а если писали несколько, то самого последнего записанного. зато спустя 4 мс (по часам симуляции протеуса) увидите
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Есть 3 функции по работе с епромом: SaveEEPROM(uint8_t SaveValue,uint8_t SaveFlagPower,uint8_t NumberZone) LoadingValueEEPROM(uint8_t NumberZone) LoadingFlagEEPROM(uint8_t NumberZone) Эти функции работают с массивами unsigned char ValuePWM[]={0,0,0,0,0,0}; unsigned char FlagPower[]={0,0,0,0,0,0};
Массивы в свою очередь содержат данные для 6ти каналов ШИМ и флаг о состоянии канала.
Добавлено after 6 minutes 23 seconds: причем с 1го по 5тый канал ШИМа значения "2"(SaveEEPROM(1,2,Count+1); Пишется а в 6том канале нет.
Ужас. Посмотрел на ваш код - ужас. У вас switch-ем выбирается, какая переменная пишется/читается - это ж кошмар! Ну поместите все в массив, и пишите элемент массива или сразу весь массив! структуры для этого служат, например... и тогда у вас вся запись превратится в единственный eeprom_update_block, чтение соответственно тоже...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Изначально все и было в массиве )а ,eeprom_update_block рассматривал как вариант , но не понял его синтаксиса.как правильно записать и считать массив+как изменить(считать ) определенный элемент массива из еепром.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
// описываем структуру конфигурации typedef struct{ int param1; char param2; long param3; } configuration;
//определяем массив конфигураций в EEPROM EEMEM configuration e_config[CONFIG_CNT];
// для удобства такой же массив в ОЗУ configuration config[CONFIG_CNT];
// вот так конфигурация из ОЗУ сохраняется в EEPROM eeprom_update_block((void*)config, (void*)e_config, sizeof(config));
// вот так конфигурация считывается в ОЗУ из EEPROM eeprom_read_block((void*)e_config, (void*)config, sizeof(config)); // я тут ранее опечатался - теперь корректно!!!
// вот так вы получаете параметр из 2-й конфигурации для работы int var = config[1].param1;
и всё, никаких switch, никакой мороки, никакого гемора... всё будет работать, как часы. код сократится в 10 раз...
Добавлено after 4 minutes 50 seconds: если вам все-таки приспичит считывать/записывать не весь массив конфигураций, а отдельно взятую конфигурацию из массива, то параметры функций блочной записи/чтения надо всего-навсего сделать такими: ((void*)&config[i], (void*)&e_config[i], sizeof(configuration)), то есть передавать в функцию не адреса и размер массивов целиком, а только адреса нужного элемента и размер структуры этого элемента.
хотя причин так делать я не вижу, разве что экономия нескольких десятков миллисекунд...
Добавлено after 17 minutes 3 seconds: еще в догонку... параметры блочных функций такие (по порядку): -адрес "откуда" -адрес "куда" -количество байт
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
То есть как я понял ,создаем массив структур e_config[] с типом configuration , который в себя включает нужное количество мне параметров. Также дублируем этот маcсив в ОЗУ под именем config[](С этими значениями я уже могу работать непосредственно в теле программы).
каждый параметр функции имеет тип. для блочной же функции все равно, какой тип обрабатывать. а вот адрес массива имеет определенный тип, и если вы передадите его в функцию без приведения к void*, то получите варнинг о несоответствии типов. чтобы убрать варнинги, приходится все адреса приводить к типу void* - он считается совместимым с любым иным указателем, и варнинга не будет.
если вас варнинги не нервируют, можете не приводить.
обратите внимание на приписку о параметрах функций, которую я сделал позже - порядок адресов для чтения и записи - разный! на первом месте адрес массива, откуда берутся данные, на втором - куда помещаются. если вы сделаете так, как процитировано - функция чтения работать не будет
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Еще раз спасибо , сейчас пробую реализовать структуру под мои нужды.
Добавлено after 3 minutes 1 second: Яж правильно понимаю т.к номера элемента массивов начинаются с 0 , то для 6ти конфигураций мне нужно указать. #define CONFIG_CNT 5.
Добавлено after 6 minutes 49 seconds: Хотя походу нет при компиляции: EEPROM Memory Usage : 10 bytes 2,0 % Full
Походу создано на самом деле 5 копий а не 6 судя по тому что в епроме 10 bytes только занято а не 12.
Добавлено after 7 minutes 31 second: и для инициализации ConfigLamp и E_ConfigLamp (стартовыми значениями ) Как я понял придется прогнать вот такой цикл ? for (int i = 0; i< 5; i++) { ConfigLamp[i].FlagPower=0; ConfigLamp[i].ValuePWM=0; }
количество человек считает с 1, поэтому если у вас 6 конфигураций, и в программе надо 6 указывать. а вот НОМЕР конфигурации будет на 1 меньше первый будет 0, а последний - 5.
что касается инициализации, то есть несколько способов. 1. если все нулями - есть 2 способа: 1.1 прямо в описании массива в EEPROM выполнить его инициализацию = {0}; а потом прошить в МК полученный .eep файл 1.2 глобальный массив в ОЗУ будет автоматически заполнен нулями, и поэтому достаточно его записать в EEPROM 2. если не все нулями, то можно поступить почти как в п.1: или инициализировать вручную и прошить, или аналогично заполнить в ОЗУ и сохранить.
для заполнения области памяти одинаковыми байтами рекомендую применять функцию memset из модуля string.h для копирования одной области памяти в другую (например, заполнение массива структур одинаковыми, но ненулевыми, структурами) рекомендую применять функцию memcpy или memmove оттуда же.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
оно же явно не правильное в конце: 000a должно быть = 06 000bдолжно быть = 05
Добавлено after 5 minutes 39 seconds: Тфу сам тупил ))) Надо же for (unsigned char ValueCount = 0; ValueCount <= 5; ValueCount++).. Чет запарился походу я с этим епромом.
вы попадает в ловушку неоднообразия... у вас в коде смешано два стиля: нехороший и хороший. я, конечно, рекомендую придерживаться хорошего стиля, а он однозначно требует исключить "магические числа" из кода. и вместе с ними пропадут ошибки.
в чем ваша беда? в том, что вы думаете, будто ValueCount у вас пробегает по ВСЕМ элементам массива... а он, зараза, не пробегает.
вот так ПРАВИЛЬНО делать цикл по ВСЕМ элементам массива:
Код:
for (unsigned char ValueCount = 0; ValueCount < CONFIG_CNT; ValueCount++)
и, разумеется, если вы где-то еще по коду используете КОЛИЧЕСТВО КОНФИГУРАЦИЙ, вместо числа 6 вы ОБЯЗАНЫ использовать константу CONFIG_CNT, иначе зачем вы вообще её вводили?!
Добавлено after 2 minutes 43 seconds: кстати, пользуйтесь типами строгой размерности. вместо длинного unsigned char применяйте короткий (и однозначный) uint8_t. ну и соответственно для других случаев аналогично in8_t, uint16_t, int16_t и т.д. (где u в начале означает "без знака", а число перед _t - количество бит в переменной).
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Сделал пару функций для теста вроде работают(в протеусе значения меняются) но при перезапуске протеуса все значение в еппром = 00. Грешу на file.BIN созданный мной для еппрома.
Добавлено after 13 minutes 29 seconds: походу у функции чтения др порядок. eeprom_read_block((void*)ConfigLamp, (void*)E_ConfigLamp, sizeof(ConfigLamp)); Куда. Откуда. Размер.
Добавлено after 1 hour 13 minutes 18 seconds: А есть идеи как можно сделать покомпактней функцию UpdateValue(); Спойлер
char mask = 0; if (! (BTN_PIN & BTN_LINE_UP)) mask = BTN_SHRT_UP; if (! (BTN_PIN & BTN_LINE_DN)) mask = BTN_SHRT_DN; if (! (BTN_PIN & BTN_LINE_POWER)) mask = BTN_SHRT_POWER; if (! (BTN_PIN & BTN_LINE_SW)) mask = BTN_SHRT_SW;
if (mask){ //опрос состояния кнопки if (BtnLockCoun < (BTN_LOCK_TIME/10)){ //клавиша нажата BtnLockCoun++; return; //защелка еще не дощитала - возврат } BtnLastState = mask; BtnLockBit =1; //нажатие зафиксировано if (BtnLongCoun >= (BTN_LONG_TIME/10)) return; //возврат, т.к. счетчик длинн нажат досчитал до максимума еще раньше if (++BtnLongCoun >= (BTN_LONG_TIME/10)) BtnFlags |= (BtnLastState<<4); //счетчик досчитал до максимума - устанавливаем биты длинного нажатия } else{ //клавиша отжата if (BtnLockCoun){ BtnLockCoun --; return; //защелка еще не обнулилась - возврат } if (! BtnLockBit) //СТАТИЧЕСКИЙ ВОЗВРАТ return; BtnLockBit =0; //отжатие зафиксировано if (BtnLongCoun < (BTN_LONG_TIME/10)) BtnFlags |= BtnLastState; //установка бита короткого нажатия BtnLongCoun = 0; //сброс счетчика длительности нажатия } } //----------****7SEG****---------- #define SEGA 6 #define SEGB 5 #define SEGC 1 #define SEGD 2 #define SEGE 3 #define SEGF 4 #define SEGG 0
#define ANOD1 4 #define ANOD2 7 #define ANOD3 4 //---------- void segchar (unsigned char seg) { switch (seg) { case 0: PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(1<<SEGG);break; case 1: PORTC=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG);break; case 2: PORTC=(0<<SEGA)|(0<<SEGB)|(1<<SEGC)|(0<<SEGD)|(0<<SEGE)|(1<<SEGF)|(0<<SEGG);break; case 3: PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(1<<SEGF)|(0<<SEGG);break; case 4: PORTC=(1<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG);break; case 5: PORTC=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG);break; case 6: PORTC=(0<<SEGA)|(1<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG);break; case 7: PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG);break; case 8: PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(0<<SEGE)|(0<<SEGF)|(0<<SEGG);break; case 9: PORTC=(0<<SEGA)|(0<<SEGB)|(0<<SEGC)|(0<<SEGD)|(1<<SEGE)|(0<<SEGF)|(0<<SEGG);break; case 99: //OFF Все сегменты PORTC=(1<<SEGA)|(1<<SEGB)|(1<<SEGC)|(1<<SEGD)|(1<<SEGE)|(1<<SEGF)|(1<<SEGG);break; } }
а объясните: зачем вам отдельные массивы ValuePower и FlagPower, если все то же самое у вас хранится в ConfigLamp? двойной расход памяти, лишние действия по переносу данных туда-сюда... зачем все это?
7seg писал(а):
А есть идеи как можно сделать покомпактней функцию UpdateValue();
а что она делает? можете словами описать, потому что анализировать ваш код у меня лично желания нет...
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Функция UpdateValu() обновляет значения OCRХХ ,также проверяет FlagPower который отвечает за состояние канала (включен/выключен). Так же сюда предполагал добавить плавное включение , т.е при переходе из состояние OFF в ОN повышать значение OCRХХ до значения записанного в еппром, антологичные действия при подачи питания на МК ( так сказать плавное включение ).
ну, плавное включение явно делать придется по таймеру... наверное.
а что касается остального, то, как я понимаю, функция смотрит флаг и, если он стоит, заносит в соответствующий регистр соответствующее значение, а если флаг сброшен, то заносит туда 0 - верно?
ну так я посоветую в структуру вышеопределенную добавить адрес регистра, который надо обновлять, и в вашей функции пробегать в цикле по всем структурам массива и обновлять по этому правилу содержимое регистра... элементарно!
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
А насчет массивов ValuePower и FlagPower еще не успел переписать под структуру ConfigLamp которая находиться в ОЗУ. В AtmelStudio вроде можно писать на с++,меня просто отговорили от использования синтаксиса плюсов в мк из за его реализации, если мк все-таки поддерживает парадигму ооп программирования то это все упрощает . можно создать класс и наполнить его методами(но я\ не уверен что МК AVR полноценно поддерживает с++.)
На самом деле с плюсами бы было работать проще и привычней . ) но даже не знаю какой стандарт поддерживает avr-gcc в atmelstudio ведь не так давно вышел очередной стандарт с++17 который пришелся сне с разу по душе в другом моем хобби. А по этой прошивке походу надо с начало адаптировать код к структуре и повыкидывать лишнее.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 47
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения