Вообще-то, жизненный цикл программы это самое "потом" предполагает всегда. Знаете, как часто могут перетряхиваться самые простые структуры данных в программе?
Раздел темы "Разные вопросы по МК", форум любительский, тема "Вопросы по С/С++" - вряд-ли это место для лекций о филологии, управлению проектами, общих принципах написания надёжного кода, автоматизации тестирования и т.п. [О, Коте Всемогущий, не сочти это за самовольное модерирование.] 99% аудитории хочет видеть конкретные ответы на интересующие их вопросы, да и только. И хорошие привычки им прививать нужно дозированно, не перенагружая их входные цепи информацией. Такой вот мой вам оффтопичный намёк.
Т.е. на моей актуальной платформе RX63N + 32 MB etx. SDRAM ваша аксиома о всегдашности использования упаковки структур принесёт что-то кроме замусоривания кода - это выдумка? И про word-aligned memory access вы тоже не слышали. [Канделябр, заходи...]
_________________ Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR!
99% аудитории хочет видеть конкретные ответы на интересующие их вопросы, да и только.
Телепатией не обладаю. Уж извините.
Добавлено after 14 minutes 29 seconds:
Цитата:
Двух слов .data и .text - sapienti sat, чтобы понять о чём речь. У вас пробел в знаниях.
Всегда удивляла подобная самоуверенность, переходящая в наглость. Вы правда думаете, что будете писать что вздумается и при этом ожидать, что вас поймут? Да откуда бы?! Секция .data - содержит статические инициализированные данные. А про секцию .bss вы как-то забыли. И про кучу тоже не вспомнили. Забыли вы и про то, что переменные могут создаваться и на стеке (и рекурсию на МК никто не запрещал - есть и такие задачи). Да даже может потребоваться передать структуру по значению в функцию - и то на 1 КБ ОЗУ памяти может не хватить. Поэтому я написал, как оно и должно быть написано - мало памяти. А вы по сути написали, что если вы заняли всю память под .data, то... Но речь не идёт о том, чтобы занять всю память одной секцией. Речь идёт о том, что при работе программы памяти может не хватить (в том числе в процессе выполнения) (а так оно и бывает чаще всего). Поэтому написали вы совсем не то же самое, что и я.
Цитата:
Т.е. на моей актуальной платформе RX63N + 32 MB etx. SDRAM ваша аксиома о всегдашности использования упаковки структур принесёт что-то кроме замусоривания кода - это выдумка?
Вообще, вы странные люди. Я вам давно объяснил, о чём написал. Но вы продолжаете упорно сами придумывать случаи, где вам выравнивание структур мешает.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
Спасибо, возможно это так, но я пробовал компилировать и без дефайна для поика порядкового номера нажатой кнопки, и оно все равно не работало. Я тут уже и так и эдак крутил, и даже вроде "оптимизировал" до варианта без массива, сложение 4-х байт в один произвожу прямо в цикле. Получилось даже компактнее, и главное работает (тут переменные немного переименовал, для большей понятности для себя)
Код:
for (keys_byte = 0; keys_byte < 4; keys_byte++) // Будем читать 4 байта состояний кнопок { spi_put(0); spi_wait(); keys_code |= (TM1638_convert_byte(spi_get()))<<keys_byte; // Каждый следующий байт накладывается на предыдущий со сдвигом влево на величину порядкового номер принятого байта (начиная с 0 !!!) }
П.С. Описываемая проблема относилась к варианту при использовании дефайна USE_USI_FOR_TM1638.
TM1638_STB_LOW(); TM1638_write_byte(TM1638_CMD_READ_KEYS); // _delay_us(2); // Минимально необходимая по даташиту задержка 2 мкс - можно убрать, все равно есть задержка после поднятия CLK в процедуре записи байта
#ifdef USE_USI_FOR_TM1638 half_spi_init_receive(); // Init SPI driver as RECEIVED master.
#else TM1638_DIO_INPUT(); // Установим ногу на вход !!! #endif
#ifdef USE_USI_FOR_TM1638 for (keys_byte = 0; keys_byte < 4; keys_byte++) // Будем читать 4 байта состояний кнопок { spi_put(0); spi_wait(); keys_code |= (TM1638_convert_byte(spi_get()))<<keys_byte; // Каждый следующий байт накладывается на предыдущий со сдвигом влево на величину порядкового номер принятого байта (начиная с 0 !!!) }
#else uint8_t key_code = 0;
for (keys_byte = 0; keys_byte < 4; keys_byte++) // Будем читать 4 байта состояний кнопок { for (key_number = 0; key_number < 8; key_number++) // Перебор всех кнопок этого байта { TM1638_CLK_LOW(); _delay_us(TM1638_DELAY_US); TM1638_CLK_HIGH();
if (TM1638_DIO_READ()) // Если есть нажатая кнопка { key_code |= (1<<key_number); // Устанавливаем бит нужной кнопки keys_code |= key_code<<keys_byte; // и накладываем этот байт на предыдущий со сдвигом влево на величину порядковго номера принятого байта (начиная с 0 !!!) }
_delay_us(TM1638_DELAY_US); } } #endif
TM1638_STB_HIGH();
#ifdef USE_USI_FOR_TM1638 half_spi_reinit_transmit(); // Init SPI driver as TRANSMIT master.
#else TM1638_DIO_OUTPUT(); // Вернем ногу на выход !!! #endif
_delay_us(TM1638_DELAY_US);
TM1638_send_comm(TM1638_CMD_SET_DATA | TM1638_SET_DATA_F_ADDR); // Установка режима работы - Запись в индикатор, Фиксированный адрес
_delay_us(TM1638_DELAY_US);
#ifdef RETURN_KEY_NUMBER if (keys_code) // Если нажата кнопка - вычисляем ее номер (Внимание, будет передана только 1, самая младшая кнопка !!!) { for (key_number = 0; key_number < 8; key_number++, keys_code >>=1) { if (keys_code & 0x01) // Если 0 бит установлен, найдена нажатая кнопка (Внимание, первой будет найдена кнопка из младшего бита) { return key_number+1; // Возвращаем порядковый номер первой найденой нажатой кнопки } } } #endif
return keys_code; // Возвращаем состояние всех кнопок }
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
Причина пропадания вызова может быть шуткой оптимизатора. Мне сначала показалось, что вы там не сдвигаете keys_code и поэтому оптимизатор выбросил вычисление, которое в конце-концов не понадобится. Поэтому внимательно проверьте, что для вычисления вашего return keys_code это действительно нужно. кстаи, причина может быть внутри функции TM1638_convert_byte(
Мне как-то IAR тоже так был "соптимизировавши". Благодаря ему я и нашел ошибку. Причем, при компиляции с пониженным уровнем оптимизации всё работало
_________________ А люди посмотрят и скажут: "Собаки летят. Вот и осень."
..\Src\Font.c(51): error: #513: a value of type "const t_point *" cannot be assigned to an entity of type "t_point *"
1. Идём на https://translate.google.com/#en/ru; 2. Переводим текст ошибки с аспергерского на русский: error: # 513: значение типа "const t_point *" не может быть присвоено сущности типа "t_point *"; 3. Осознаем, что тому кто "слева" неприемлемо значение предлагаемое тем кто "справа"; 4. Есть два варианта - либо меняем тип "левого" на const t_point*, либо то, что отдают справа насильно считаем типом t_point* (т.е фактически read-only данные считаем возможным модифицировать);
Впрочем это вам уже объяснили и без меня - остается лишь добавить что const - это указание компилятору считать данные неизменяемыми и он, обладая этим знанием, может оптимизировать работу с ними, сэкономив, к примеру оперативную память, обращаясь напрямую к данным из флеш. Но за такими деталями - это вам к специалистам по используемой вами платформе.
Т.е. если вы не планируете менять данные "шрифта" во время выполнения программы - оставляйте их const, если-же нужно менять - придётся определить некий максимум для размера данных символа - и оперировать в его пределах. Ну и поудалять модификаторы const. Примерно так:
Код:
#define MAX_CHAR_DATA 32
// [омномномном]
// при таком способе инициализации данные массива добиваются нулями до размера 32 (MAX_CHAR_DATA) t_point ch56[MAX_CHAR_DATA] = { 0x10, 0x30, 0x41, 0x42, 0x33, 0x44, 0x45, 0x36, 0x16, 0x05, 0x04, 0x13, 0x02, 0x01, 0x10, BRK, 0x13, 0x33, EOL } ;
Зарегистрирован: Пт мар 02, 2018 16:31:19 Сообщений: 7
Рейтинг сообщения:0
Всем спасибо за участие! Теперь все компилируется и рисуется =) Заодно дописал функцию сглаженной линии... Вот только шрифт имеет смысл рисовать сглаженным, если он скейлится... Для тех, кому интересно, прикладываю пример на фото.
Добавлено after 7 minutes 21 second: Забыл добавить: символы еще не все добавил. В верхней части слева - сглаженный, справа обычный. В нижней первая строка скейленый шрифт без сглаживания, во второй строке - те же скейленные символы со сглаживанием.
Как сделать установку несколько IP адресов, по феншую? т.е как инициализировать массив из 4 байт и больше. уже кучу вариантов, придумал и все не нравятся, хотел объявить структуру с дефектными настройками и от туда копировать до N поля, но тут не нравиться что может глюк с выравниванием структуры. Сделал в лоб, но тут не нравиться что надо массив объявлять.
Сделал себе структуру модулей так есть глобальный #include "Aplication.h" который подключается ко ВСЕМ модулям в нем решил включать #include которые могут вызываться в многих модулях к примеру светодиоды(для отладки) и тд. Все хорошо работало, но засунув в очередной раз модуль в Aplication.h получил кучу ошибок("dataEntryType" is undefined ) совершено в другом модуле, причем dataEntryType находится в другом модуле и он подключен. т.е это выглядит так: Есть два модуля в модуле snmp.h объявлена структура dataEntryType и получаю ошибки на то что в модуле snmp_custom неизвестна dataEntryType, хоть вот выше строчкой структура должна подключиться
PS: сейчас с модулями snmp.h snmp_custom.h все переделал убрал внутри все ихнии инклуды, и перекинул их все в "Aplication.h все равно все ещё ругается, пока каша в голове отчего все это может быть. сдается мне что модуль как -то рекурсивно вызывается, в одном он подключился а в другом уже нет.
во всех модулях стоит, естественно с разными define
Есть два модуля в модуле snmp.h объявлена структура dataEntryType и получаю ошибки на то что в модуле snmp_custom неизвестна dataEntryType, хоть вот выше строчкой структура должна подключиться
Чтобы основательно разобраться с темой - нужно смотреть что там препроцессор наворотил - поищите кaк для вашего компилятора просмотреть выхлоп препроцессора - т.е. файл, получившийся после разворачивания всех #include директив до передачи его компилятору. В ембедерных ИДЕ это как правило опция в проекте - либо "do not remove intermediate files" либо "preprocess only" - файл нужно искать в папке с объектниками иногда с расширением .pre иногда прямо вместо объектника, иногда .i В майкрософтосвских средах - ключи командной строки /E /P - появится файл с расширением .i
Если по быстрому - иногда спасет т.н. forward declaration - но только в том случае, если компилятору не нужны подробности:
Код:
#ifndef __H__ #define __H__
struct dataEntryType; // forward declaration int cleanThemAll(struct dataEntryType*); // указатель на тип - подробности внутренностей объекта не нужны
#endif /* __H__ */
И в таком случае файл с [полным] объявлением структуры нужно включать только в том .с файле где определяются переменные этого типа.
_________________ Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR!
Благодарю обязательно поищу файл, а так вроде разобрался компилятор IAR выдавал ошибку при компиляции snmp.с который вызывал snmp.h и в самом начале еще до объявлении структуры вызывался файл "Aplication.h" который открывал snmp_custom.h и видать из за того что вызов был из snmp.h файла, второй раз он уже его не мог открыть по этому компилятор успешно пропускал его в snmp_custom.h и ругался.
pokk, логику диррективы "#include" понимаете? Она очень простая: #include "file" заменяется содержимым указанного файла. Все. Какая каша? Если ругается на строку, что тип не определен, значит этот тип не определен. Все, другого быть не может. А) файл с определением типа инклудается позже (компилятор вперед ничего не просматривает) Б) вообще банальная ошибка, типа определили dataEntryType, а используете dateEntryType В) тип действительно не определен, например, не заинклуден нужный файл.
PS. По вашему описанию вообще проблематично чтото сказать. Вложите исходник и все инклуды, которые инкудятся, скажите в какой строке и как ругается компилятор, думаю, Вам через пять минут скажут где "косяк".
// вот две функции void output_level_1_GWS(void); void output_level_1_HWS(void);
// объявляю тип структуры с полями на указатель функции typedef struct { void (*Ptr1GWS)(void); // пункт меню на первом уровне void (*Ptr1HWS)(void); // пункт меню на первом уровне }LEVEL1; // тип структуры 1 уровня
//инициализирую ее функциями выше LEVEL1 MENU_LEVEL1={output_level_1_GWS,output_level_1_HWS};
// создаю указатель на целое беззнаковое uint8_t *PtrPunkt;
в него планирую поместить адрес 2 поля структуры LEVEL1 MENU_LEVEL1.Такой вот записью PtrPunkt=&(LEVEL1 MENU_LEVEL1->Ptr1HWS); 1)нужен ли здесь указатель на указатель? :dont_know:
2)затем используя PtrPunkt нужно вызвать функцию output_level_1_HWS();Правильно ли будет написав так *PtrPunkt;
3)объявления переменных, функции и т.п делаю в хедере, а инициализацию нужно делать в исходнике модуля как и реализацию функции, или в хедере?
// вот две функции void output_level_1_GWS(void); void output_level_1_HWS(void);
// sz: делаем каноничненько - алиасим тип указателя на функцию typedef void (*TvvPtr)(void);
// объявляю тип структуры с полями на указатель функции typedef struct { TvvPtr Ptr1GWS; // пункт меню на первом уровне TvvPtr Ptr1HWS; // пункт меню на первом уровне } LEVEL1; // тип структуры 1 уровня
// создаю указатель на целое беззнаковое uint8_t *PtrPunkt; // sz: когда устанете бороться с компилятором - напишите так: TvvPtr PtrPunkt;
PtrPunkt=&(LEVEL1 MENU_LEVEL1->Ptr1HWS); // sz: не выйдет в мышь впихнуть кота - любой заметит: - "Фактура не та!" А приведение типов - Зло™. Синтакс - ужасен - достаточно PtrPunkt=MENU_LEVEL1->Ptr1HWS;
// sz: да и за полностью прописные имена типов/переменных и прочих не #define-ов - тру-Сишники из вас кактус сделают. :-) Ибо заповедано: -"Прописными - только #define-ы!"
2)затем используя PtrPunkt нужно вызвать функцию output_level_1_HWS();Правильно ли будет написав так *PtrPunkt; // sz: а если-бы функция имела аргументы? И таблицу приоритетов посмотрите - кто кого перетянет. ;-)
3)объявления переменных, функции и т.п делаю в хедере, а инициализацию нужно делать в исходнике модуля как и реализацию функции, или в хедере? // sz: "хидер" - это интерфейс модуля - там объявления, А определения - только в самом модуле. Будь определение в хидере - в каждом включающем этот хидер модуле будет копия переменной - линкер может и заколдобиться.
_________________ Одновременным нажатием LIGHT и POWER, РП Sangean ATS-909X (ver 1.29) превращается в ATS-909XR!
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 21
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения