Обсуждаем контроллеры компании Atmel.
Ответить

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт сен 30, 2022 07:24:46

Продвинутые микроконтроллеры имеют аппаратные ловушки (флаги ошибок) при таких операциях. На чистом Си без предварительных проверок такое невозможно, компилятор не отслеживает математику переменных. Если 0 - константа, то предупреждение выдаст. Иначе - нет.

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт сен 30, 2022 09:57:36

MLX90640, ну тема про AVR-ный Си.
На АВРках нет аппаратных ловушек.
Просто столкнулась, что надо немного математики покрутить с широким диапазоном параметров..... Придется руками проверять всё.....
Эхххх.. где мои любимые begin.... exception when ... then .... end;

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт сен 30, 2022 11:53:01

Количество кода, нужного на проверку делителя на ноль - ничуть не больше, чем добавить те же try/catch, если бы они и были. Но с точки зрения ресурсов, обходится гораздо дешевле.
Код:
x = (a+b+c)/(d+e);

# vs

div=d+e;
x = div ? (a+b+c)/div : 0;

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт сен 30, 2022 12:29:19

WiseLord, деление на ноль - фиг с ним.
У меня будет квадратный корень, тригонометрия, включая тангенс и, возможно, будет еще экспонента, но тут еще не знаю.
И не хотелось бы проверять отдельно отрицательное для корня, +/-90° для тангенса, что б аргумент экспоненты был меньше 88.5 и т.д.
математика будет в одном блоке и хотелось получить либо результат, либо ошибку. Где она возникла - будет не особо важно....

Re: Нескольно простых вопросов о программировании AVR на Си.

Чт окт 06, 2022 20:56:34

подскажите как можно узнать длину массива хранящегося в progmem? У меня есть массив указателей(тоже в progmem) который хранит в себе указатели на массивы, но они разной длины, и вот их нужно передать в функцию вывода, но так же нужно знать размер.. И это не строка, по нуль символу парсить не получится(
костыль я уже придумал. в нулевом элементе каждого массива хранить его размер. но может есть что по изящнее?\

Re: Нескольно простых вопросов о программировании AVR на Си.

Чт окт 06, 2022 21:08:09

в си нельзя в общем случае по указателю определить размер области, на которую он указывает.
ваш костыль - не костыль, в вполне обычная практика.

Re: Нескольно простых вопросов о программировании AVR на Си.

Чт окт 06, 2022 21:10:40

ARV, там же массивы прибиты гвоздями в progmem и скорее всего не меняются в run-time. Это ж не выделение памяти в куче.


Roman Solovey, нууу... У вас массив массивов. С учетом того, что они в прогмеме - они, скорее всего, не меняются (вариант, когда вы из программы перешиваете память МК - не рассматриваем).
Есть смысл тогда размеры этих массивов задефайнить через sizeof на этапе написания программы.


Код:
const int arr1[50] PROGMEM = {1,2,3....};
const int arr2[25] PROGMEM = {1,2,3....};
const int arr3[666] PROGMEM = {1,2,3....};
const int arr4[1984] PROGMEM = {1,2,3....};

#define ARR1_SIZE    sizeof(arr1)
#define ARR2_SIZE    sizeof(arr2)
#define ARR3_SIZE    sizeof(arr3)
#define ARR4_SIZE    sizeof(arr4)


И использовать эти дефайны в программе...

Ну или покажите код, как вы определяете эти массивы и расскажите, для чего нужен их размер?

Re: Нескольно простых вопросов о программировании AVR на Си.

Чт окт 06, 2022 21:56:14

спасибо за подсказки)
с дефайнами морочнее будет. мне шрифт нужно к дисплею прикрутить, а это много символов)

Re: Нескольно простых вопросов о программировании AVR на Си.

Чт окт 06, 2022 22:03:33

Roman Solovey, если размер каждого символа одинаков - то множить код символа на размер. Если ширина разная - то оптимально в первом байте символа держать размер этого символа. Так все делают.
Плюс дополнительно, если отвести еще один байт на код символа - можно собирать в шрифт только нужные символы.

Re: Нескольно простых вопросов о программировании AVR на Си.

Чт окт 06, 2022 22:19:15

Плюс дополнительно, если отвести еще один байт на код символа - можно собирать в шрифт только нужные символы.

Немного не понял. это типа в программе которая генерит шрифты нужно выделить?

Re: Нескольно простых вопросов о программировании AVR на Си.

Чт окт 06, 2022 22:51:49

Roman Solovey, есть 2 подхода.
1. в шрифте сохранены все символы, цифры , англицкий алфавит, кириллический алфавит. Это порядка 160 символов.
И все эти символы хранятся в прогмем и занимают место.
А нам надо написать "ПРИВЕТ!" - из 160 символов нужно всего 7. И 153 символа просто занимают память.
2. В шрифте сохранены только нужные символы. Цена этого - + 1 байт к каждому символу - в этом бате хранится код.
И для надписи "ПРИВЕТ!" достаточно сохранить 7 символов всего.
но если вдруг придется написать, "ПРИВЕТ, ВАСЯ!" - то нужно будет выгружать заново не 7, а 12 символов.

Re: Нескольно простых вопросов о программировании AVR на Си.

Пт окт 07, 2022 09:31:37

ARV, там же массивы прибиты гвоздями в progmem и скорее всего не меняются в run-time. Это ж не выделение памяти в куче.
ну и что? в массиве указатели на массивы, а какой размер того массива, на что показывает указатель - узнать нельзя. тот факт, что на самом деле размеры известны программисту, не делает их доступными программно.


Есть смысл тогда размеры этих массивов задефайнить через sizeof на этапе написания программы.
что и требовалось доказать

Добавлено after 4 minutes 38 seconds:
шрифты делаются примерно так:
Код:
typedef struct {
   uint8_t width;
   uint8_t height;
   uint8_t bytes[]; // массив неизвестного размера всегда последний
}symbol_t;

по полям width и height вычисляется количество элементов массива bytes.

затем вы делаете массивы символов, заносите указатели в массив "алфавита" и т.д.

для пущей экономии можно сделать "алфавит" не полным, но тогда при выводе символа надо предусмотреть проверку вхождения символа в алфавит.

Добавлено after 7 minutes 56 seconds:
кстати, для более-менее свежих версий компилятора avr-gcc крайне рекомендую использовать префикс __flash для описания констант, размещаемых в памти программ, т.е. отказаться от PROGMEM, а заодно и от функций pgm_read_xxx. я об этом неоднократно писал уже - код становится более переносимым, лучше читается и в целом работать проще.

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб окт 08, 2022 11:47:07

А кто подскажет, в голом Си (на МК) реально отловить деление на ноль, не проверяя делитель перед делением?
try... catch вроде ж только для плюсов....


try/catch в С++ не отлавливает деление на ноль и вообще не имеет никакого отношения к этому.

отловить деление на ноль, не проверяя делитель перед делением?


Никак. Ни в С, ни в С++.
Последний раз редактировалось KorbenDallas Сб окт 08, 2022 23:17:36, всего редактировалось 1 раз.

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб окт 08, 2022 15:25:42

- Вась, а Вась, чем С++ от С отличается?
- 1
- ну правда, Вась?
:)))

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб окт 08, 2022 19:08:57

ARV, не 1, а True :)

Re: Нескольно простых вопросов о программировании AVR на Си.

Сб окт 08, 2022 20:01:02

Roman Solovey, для шрифтов массив данных символа делается либо одинакового для всех символов размера, либо размер массива данных каждого символа косвенно хранится в таблице описаний символов. Некоторые утилиты создания шрифтов (например Dot Factory) умеют создавать такие таблицы.

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн окт 10, 2022 13:14:13

Roman Solovey, я тоже применяю дефайн, но немного иначе
1) допустим, есть функция, работающая с массивом F(Arr), внутри которой надо знать его размер...
2) создаю для функции обёртку вида: #define _F(Arr) F(Arr, sizeof(Arr))
3) в дальнейшем вызываю её... (внутрь функции размер приходит 2м аргументом)
ПС) недостаток метода - для массивов из элементов инт надо размер делить на 2: #define _F(Arr) F(Arr, sizeof(Arr)/2)

Добавлено after 5 minutes 44 seconds:
Пример:
Код:
/*поиск в int[] */#define  findint(_Arr,_value) (searchInArrayInt  (_Arr, (sizeof(_Arr)/2)-1, _value))
/*поиск в char[]*/#define findchar(_Arr,_value) (searchInArrayChar (_Arr, (sizeof(_Arr)-1),   _value))
размер вычисляется во время компиляции и в прошивку попадает только готовое к употреблению число
(-1 я вынес из функции, так оказалось немного удобнее и немного уменьшило прошивку в моем случае)

ПС: посмотрел по сторонам и нашел, как от этого недостатка избавиться:
sizeof(Array)/sizeof(Array[0]);
или
sizeof(Array)/sizeof(*Array);
дадут именно количество элементов массива, а не его размер в байтах

Добавлено after 17 minutes 7 seconds:
Just_Fluffy, в чем разница между sizeof(arr1) и #define ARR1_SIZE ? и то и то дефайн... (только один системный, а второй пользовательский, причем ни какими преимуществами не обладающий...)

Добавлено after 52 minutes 49 seconds:
Оно не будет работать с динамическими массивами, но тут про них речь и не идёт

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн окт 10, 2022 14:00:05

Ivanoff-iv, так никакой разницы и нет. Только я предлагала просто держать рядом с массивами дефайны их размеров через sizeof, а вы предпочли инкапсулировать размер в вызов функции....
Вроде и красивее, но иногда проще обращаться к элементу массива напрямую, а не через функцию.
Но суть одна - инструментов определить размер массива нету. Для динамических надо самому помнить, сколько мы отгрызли памяти под массив. Для статических - в design-time где то сохранять размер. Через тот же sizeof, к примеру. И это нормальная практика.

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн окт 10, 2022 15:00:53

так sizeof и дефайн на него ничего не хранят (по крайней мере там, где написаны), а лишь указывают на константу в памяти компилятора и говорить о том, что одна лежит к массиву ближе другой... :dont_know:
по мне так sizeof применять удобнее, т.к. она имеет параметр, через который её вызов можно автоматизировать... свою подменку тоже можно автоматизировать, но это сложнее

Добавлено after 8 minutes 38 seconds:
иногда проще обращаться к элементу массива напрямую, а не через функцию.
не спрю, напрямую ,конечно проще, но если надо както автоматизировать это обращение, например обратиться несколько раз одинаковыми методами да к разным массивам... то проще 1раз написать функцию... беда в том, что внутрь функции массив не передается, передается лишь указатель на него и sizeof становится бессилен.
Можно всю функцию написать в виде дефайна (т.е. по сути просто много раз продублировав код), каюсь я и так делал :) , оптимизатор, кстати, такой код ооочень хорошо ужимает :hunger: оверхеда практически не остается... (иногда прошивка даже компактнее получается... :shock: )
а можно (как я привел в примере) просто получить размер заранее и как параметр передать функции.

Добавлено after 7 minutes 52 seconds:
ПС: наличие функции не мешает обращаться напрямую... просто вне функции работают и sizeof и дефайн на него (а значит дефайн безполезен), а внутри функции если sizeof просто перестает работать, то дефайн продолжает отображать то, на что его направили.... это полностью убивает универсальность функции (зачем мне размер ARR1 если я работаю с ARR2 ? )

Добавлено after 27 minutes 29 seconds:
Ivanoff-iv, так никакой разницы и нет. Только я предлагала просто держать рядом с массивами дефайны их размеров через sizeof, а вы предпочли инкапсулировать размер в вызов функции....
ничего я не инкапсулировал... :oops: :))) это просто небольшая часть возможностей дефайна по облегчению написания кода, я даже имени ни одного из массивов не упомянул - всё подставляется и считается автоматически!

А дефайн без параметра или хотя-бы математической операции (чтобы что-то при сборке посчитать), без пользователького значения внутри (которому этот дефайн придает имя) ИМХО штука совсем безполезная... даже код понятнее такой дефайн не делает... :cry: зачем он?
у меня sizeof() всегда рядом с массивом лежит (хоть и только в мыслях).... :)))

Добавлено after 7 minutes 1 second:
ПС вот так смысл появится:
Код:
#define ARR1_SIZE    (sizeof(arr1)/sizeof(arr1[0]))
так в дефайне будет именно количество элементов массива, а не занимаемый им размер памяти.

А вот так ещё интересней:
Код:
#define quantity(ARR_NAME)    (sizeof(ARR_NAME)/sizeof(ARR_NAME[0]))
так этот дефайн к любому (статическому) массиву применить можно

Re: Нескольно простых вопросов о программировании AVR на Си.

Пн окт 10, 2022 15:07:11

только все это бесполезно, если адрес массива неизвестной длины берется не по имени массива, а по указателю
Ответить