Качественное и безопасное устройство, работающее от аккумулятора, должно учитывать его физические и химические свойства, профили заряда и разряда, их изменение во времени и под влиянием различных условий, таких как температура и ток нагрузки. Мы расскажем о литий-ионных аккумуляторных батареях EVE и нескольких решениях от различных китайских компаний, рекомендуемых для разработок приложений с использованием этих АКБ. Представленные в статье китайские аналоги помогут заменить продукцию западных брендов с оптимизацией цены без потери качества.
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Всем привет. В этой теме уже была похожая проблема, но не такая как у меня.. Вообщем создаю меню. Создал структуру, засунул ее в прогмем, потом создал массив структур и туда же положил. Следом создаю указатель на структуру и хочу ему присваивать разные структуры (из массива) которые соответствуют текущему пункту меню. Но во время присвоения получаю какой то левый адрес. Почему так происходит? И еще, если я присваиваю не через макросы прогмема то адрес получаю правильный, но дальше программа отказывается работать...
Карма: 90
Рейтинг сообщений: 1289
Зарегистрирован: Чт мар 18, 2010 23:09:57 Сообщений: 4510 Откуда: Планета Земля
Рейтинг сообщения:0 Медали: 1
Я с AVR не работал никогда, но, сдаётся мне, что добавление PROGMEM в typedef, ничего не даёт. Уберите этот квалификатор оттуда и вставляйте его туда, где непосредственно нужно разместить объект во флеши (массив MenuItems и в указателе parent).
Если вы работаете с современным тулчейном, прочитайте, наконец, о новых возможностях компилятора и пользуйтесь ими! Я сейчас о квалификаторе __flash и __memx Эти квалификаторы позволяют абсолютно прозрачно работать с памятью программ через типизованные указатели, как с ОЗУ. Я в другой теме не раз об этом писал.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
typedef const struct Menu_Item { const struct Menu_Item *Next; /**< Pointer to the next menu item of this menu item */ const struct Menu_Item *Previous; /**< Pointer to the previous menu item of this menu item */ const struct Menu_Item *Parent; /**< Pointer to the parent menu item of this menu item */ const struct Menu_Item *Child; /**< Pointer to the child menu item of this menu item */ void (*SelectCallback)(void); /**< Pointer to the optional menu-specific select callback of this menu item */ void (*EnterCallback)(void); /**< Pointer to the optional menu-specific enter callback of this menu item */ const char Text[]; /**< Menu item text to pass to the menu display callback function */ } Menu_Item_t;
и в конфиге настраивается в какой памяти #define MENU_ITEM_STORAGE PROGMEM
ARV, наверное из за того что дя PROGMEM есть куча примеров. а для __flash не особо. oleg110592, да основная идея взята от туда, но дело в том что я многое там не понимаю, и по этому решил написать так как мне будет понятно.. и вот такой результат. пробовал уже и другой тип данных в место указателя на структуру делать. тогда вообще нули получаю. Может я как то неправильно беру адрес структуры?
даже если я изменяю в квадратных скобках структуру первую или вторую все равно получаю один и тот же адрес
кажется разобрался тут нужно считывать адрес во флеш где хранятся данные znak = pgm_read_byte(&parent->key_state); Но теперь вопрос, почему же вот таким способом я получаю правильный адрес? parent = ((MenuItem*)&MenuItems[1]); Ведь я считываю из памяти программ без каких либо макросов..
_________________ Одержать сто побед в ста битвах — это не вершина воинского искусства. Повергнуть врага без сражения — вот вершина.
я здесь на форуме выкладывал свой проект с активным использованием __flash, и как раз для меню FlexMenu но, если вы с указателями на ты, всю суть можно объяснить несколькими строками:
Код:
// вот так строка помещается в память программ const __flash char str[] = "string";
// вот так создается тип-структра, которую затем будем помещать в памяти программ typedef const __flash struct{ int data; const __flash char *fstr; // а это указатель на строку во flash } flash_data;
// вот массив в памяти программ, наполненный теми структурами: const __flash flash_data array[] = { {.data=1, .fstr = str}, {/* и так далее*/} };
// вот так выводится строка из памяти программ printf("%S\n", str); // как видите, никаких pgm_read_xxxx
// вот собственная функция перебора символов подобной строки int flash_strlen(const __flash char *s){ int result = 0; while(*s++) result++; return result; }
i = flash_strlen(str);
как видите, достаточно описать тип с префиксом const __flash, и данные окажутся в памяти программ, а доступ к ним можно осуществлять так, как будто они в озу, т.е. по имени переменной или через разыменование указателя соответствующего типа.
всё просто
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
аа. я понял. тогда реально отпадает потребность во всех этих извращениях с тем что и от куда читать. но все же, я такой человек который хочет докопаться до истины, почему я могу получить правильный адрес без использования спец макросов. Единственное что наталкивает на мысль что на этапе компиляции туда подставляются нужные значения..
_________________ Одержать сто побед в ста битвах — это не вершина воинского искусства. Повергнуть врага без сражения — вот вершина.
uint8_t doSomething(uint8_t input) { PORTB = PORTB | 1 << led; // Take PB5 high _delay_ms(1000); // Wait for a second PORTB = PORTB & ~(1 << led); // Take PB5 low _delay_ms(1000); // Wait for a second return STATE1; }
void setup() { DDRB = DDRB | 1 << led; // Define PB5 as an output }
void loop() { // Get the Function pStateFunc = (StateFunc) pgm_read_ptr(&menu_state[1].pFunc);
// Execute the Function and save the returned state nextstate = pStateFunc(input); }
Зарегистрирован: Пн ноя 04, 2019 09:58:29 Сообщений: 102 Откуда: г. Нижний Тагил Свердл. обл.
Рейтинг сообщения:0
Добрый вечер. Переписал библиотеку для дисплейчика SSD1306 (128х64) с Arduino на нормальный C++(14). для МК ATmega328P. hardware SPI. Работает нормально. Прошел весь тест. Поменяв pinReset, pinDC протесстировал и на ATmega 2560. Работает на любой меге если позволяет размер памяти. Далее планирую переписать и для цветных дисплейчиков. Заказал - уже в пути (4 шт. разных). Вкурил в абстрактные классы, наследование, виртуальные методы, поверхностно в темплеты. hardware SPI для Ардуины также переписан и затемплетен - файл SPI(AVR_T).h. Все файлики в архиве. (пирожок только что из печки - прошу откушать)
Добавлено after 13 minutes 29 seconds: Питание дисплея по сигнальным проводам, так что отсутствует необходимость подключения внешнего иcточника 3,3 V.
Это быстрый поток. Но еще хочу добавить медленный поток, который за 28 секунд планируется около десятка записей. Для этого я ввёл байт whereami, который показывает в каком программном модуле я нахожусь. Но если в этом байте записан 0, то это типа признака медленного потока и при интепретации данные передаются другие (и пока что меньше чем в быстром потоке):
Код:
typedef struct slow_data { int coordX; int coordY; uint segmentLength; int nodeNum; }
Как объявить это дело, чтобы размер записи всегда был одинаковым и байт whereami тоже находился в одном и том же месте. Конечно я могу просто дефайнами переобозвать, что #define coordX SetSpeedLeft итд. Но, ведь, наверняка, есть более красивый способ записи? Слышал про union, но не могу сообразить как его сюда приделать, чтобы поле whereami никуда не уехало.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 21
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения