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

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

Ср мар 15, 2023 20:14:32

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

Т.е. каждый раз сравнивают (проверяют), что разность больше чем вычитаемое, тогда продолжают вычитать. Накапливают переменную. и так далее с каждым разрядом?

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

Чт мар 16, 2023 00:13:13

Понимаю, что надо использовать деление на 10 и остаток от деления на 10. Много чего уже посмотрел, но все равно плохо доходит.
Так ведь Eddy_Em в Сообщении от Вт ноя 22, 2022 11:07:19 на предыдущей странице уже всё расписал!
Суть в том, что я не знаю, сколько разрядов у числа изначально. Может быть три, а может пять.
А какая разница, сколько их? Изначально буфер на 5 символов надо заполнить пробелами или каким другим пустым кодом, если кодировка не ASCII. Цифры же формируются с конца (обратите внимание на --bufptr у Eddy_Em), и этот цикл заканчивается не по счётчику, а по нулевому остатку от исходного числа. При этом сколько символов сформировалось, столько и ладно. Программа даже не заморачивается подсчётом этих символов!
Опишите суть, или ткните, где это максимально понятно расписано.
AVR Application Note 204: BCD Arithmetics. Начинается этот аппноут как раз с программы, а точнее с алгоритма Binary 16 to BCD Conversion. А хорошее разъяснение всей этой математики есть в 3-м томе 4-томника "Микроконтроллеры" от Алекса Фрунзе. Не столь популярное, но тоже небесполезное описание всё той же самой математики есть и в жёлтой книжке "Программы для микропроцессоров" Гуртовцева и Гудыменко. И всё это есть в сети.

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

Чт мар 16, 2023 05:13:55

...Теперь я хочу разбивать число неопределенного количества разрядов на цифры... Суть в том, что я не знаю, сколько разрядов у числа изначально...

Не обязательно делить или вычитать. Можно провести десятичную коррекцию, начиная с младших разрядов.
viewtopic.php?p=1417529#p1417529

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

Чт мар 16, 2023 08:30:23

В древности писал статью на тему вывода чисел: http://arv.radioliga.com/content/view/106/49/

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

Чт мар 16, 2023 09:15:32

СКАЗОЧНИК писал(а):Т.е. каждый раз сравнивают (проверяют), что разность больше чем вычитаемое, тогда продолжают вычитать. Накапливают переменную. и так далее с каждым разрядом?
да, каждый раз нужно сначала делать проверку на возможность вычесть, потом вычитают.
а иногда делают наоборот - сначала вычитают, потом проверяют остаток на знак. если положительный, продолжают вычитать. если отрицательный, прибавляют и переходят к следующему разряду.

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

Чт мар 16, 2023 10:18:01

Starichok51, спасибо, интересно. Код небольшой (против /10 и %10).
Код:
int16_t data = 9876;
---
  while ((data - 1000) > 0) {
    data -= 1000;
    a++;
  }

  while ((data - 100) > 0) {
    data -= 100;
    b++;
  }

  while ((data - 10) > 0) {
    data -= 10;
    c++;
  }

  d = data;
---
результат:
9876
9 8 7 6

---
Да, но медленнее :P.
Код выше по сравнению с кодом ниже: 20 µs / 4 µs (ATmega328, 16 MHz).
Код:
  a = data / 1000;
  b = (data / 100) % 10;
  c = (data / 10) % 10;
  d = data % 10;

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

Чт мар 16, 2023 10:44:27

veso74, что-то мне не верится, что деление и потом взятие %10 работает быстрее вычитания.
я не умею писать для МК на Си, чтобы самому это проверить.

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

Чт мар 16, 2023 10:56:02

Все по умолчанию, оптимизация на макс. Ардуино IDE, со своим языком и функциями (печать в Serial из отчетности время пропущен).

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

Чт мар 16, 2023 13:34:09

veso74, что-то мне не верится, что деление и потом взятие %10 работает быстрее вычитания.
я не умею писать для МК на Си, чтобы самому это проверить.

Поверьте, быстрее.
Компиляторы сейчас умные, и при включенной (по умолчанию) оптимизации сами реализуют деление на 10 как умножение со сдвигом, что и кода меньше занимает, и по времени гораздо быстрее, чем отнимать и считать циклы.

К примеру, вместо целочисленного деления uint8_t числа на 10 компилятор сам может сообразить, что это то же самое, что умножить это число на 205 и результат сдвинуть на 11 разрядов вправо.

Почему 205? Потому что X / 10 = X * 204.8 / 2048 ~= X * 205 / 2048 = (X * 205) << 11. Что для любых чисел само по себе приблизительно, но для однобайтовых X погрешность нулевая.

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

Чт мар 16, 2023 13:57:00

+1000500. Считаю, и не только я, что в наше время, в первую очередь, нужно обращать внимание на наглядность исходного текста, а не заниматься "оптимизацией". Все эти оптимизации ушли вместе с ассемблером.

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

Чт мар 16, 2023 14:43:10

WiseLord, а если число большое и нужно поделить на 10 тысяч или на 10 миллионов?

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

Чт мар 16, 2023 14:52:31

viewtopic.php?p=4386697#p4386697
Тестирование некорректное. Если data - константа, компилятор имеет полное право вместо
Код:
data = 9876;
a = data / 1000;
b = (data / 100) % 10;
c = (data / 10) % 10;
d = data % 10;

записать a = 9; b = 8; c = 7; d = 6;
И МК вообще ничего не будет вычислять.
Кроме того, в коде с циклами три ошибки. Но это так, мелочи.

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

Чт мар 16, 2023 14:57:21

WiseLord, а если число большое и нужно поделить на 10 тысяч или на 10 миллионов?
Принцип остаётся тот же - заменить деление на умножение и сдвиг.
Если контроллер умеет аппаратно умножить два 8бит числа с 16бит результатом, то и умножение чисел с большей разрядностью легко сводится к умножению октет и суммироованию, что всё равно обходится дешевле циклов вычитаний.

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

Чт мар 16, 2023 15:08:19

МК вычисляет :) И еще хочет :ПП
Код:
uint64_t data = 11126789012;
---
  data++;
  PORTB = data / 123456789;

36..40 µs

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

Чт мар 16, 2023 15:22:27

Добавлю: встроенная функция avr-gcc позволяет иметь остаток от деления одновременно с получением частного. Т.е. не сначала деление, а потом взятие остатка от деления, а за один вызов. Думаю, оптимизатор распознает эту ситуацию и делает с минимальными затратами.

Если честно, то вообще не понимаю, к чему в данной ситуации погоня за тактами... Индикация - процесс настолько низкоприоритетный и медленный, что экономить на нем просто глупо...

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

Чт мар 16, 2023 15:23:50

mont-oriol, да, компилятор считает один раз. С расчетом в цикле изменилось: 24 µs к 72 µs. Нравится, есть где использовать.

А лично в 99% случаев неважно как написано - от этого ничего не зависит (скорость?), и если память будет на пределе (если, конечно не любимый ATtiny13A). Вопрос ради вопроса.
Вложения
2.jpg
(68.36 KiB) Скачиваний: 26
1.jpg
(61.4 KiB) Скачиваний: 24

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

Чт мар 16, 2023 21:00:12

В древности писал статью на тему вывода чисел: http://arv.radioliga.com/content/view/106/49/

Очень понравилась Ваша реализация. ) Переделал чуток под себя, конечно.
Идеально выводит числа на 6 разрядов индикатора, прям как я хотел.

Спасибо. :beer:

Добавлено after 2 minutes:
З.Ы. да и пришлось про свитч-кейс еще почитать, что он умеет не только с целыми числами работать, но и с символами.

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

Пт мар 17, 2023 19:37:57

ARV
И если критична производительность и/или объем кода - то стоит задуматься, а нужен ли тут float ?

Вспомнила, делался какой то показометр на линейке диодов, там логарифмическое что то просили считать. Пришлось туда втулить.

А если некритичны производительность и/или объем кода – то тоже стоит задуматься, а нужен ли тут float?

Как я понял из последней фразы, из-за логарифма вы «втулили» float.
Так в целочисленной арифметике тоже есть логарифм.
Например, в, условно говоря, хорошем ассемблере есть вызов функции логарифма. Одна строчка - и есть готовый логарифм.
По объёму и скорости выполнения программа наверняка будет лучше.
Скорее всего, подойдёт самый простой вариант, где аргумент – 2 байта. У него точность вроде как полпроцента, вполне достаточно для рядовых целей.
Диапазон, правда, небольшой, но, скорее всего, несложно расширить с помощью простой школьной арифметики.

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

Пт мар 17, 2023 20:33:27

AQ29, Вам шашечки или ехать?
Суть была в чем - пихать флоаты налево и направо - не стоит. В большинстве (обратите внимание - не всегда) случаев от флоатов можно отказаться. Но иногда с ними проще.
У меня проектов на мелких МК с флоатами - ну вот только один и вспомнился. В остальных случаях получилось уйти к целочисленной математике. Ну там, где вообще надо было к ней уходить.
Касательно флоата и логарифма.
Это заказной проект был. Не особо дорогой. И тратить свое время на какие то изыски - не выгодно было.
Я отдавала себе отчет, что флоаты на авр - не самое лучшее решение...
Но в данном случае ресурсов хватало и таймингов тоже. Зачем мне искать/придумывать ассемблерный вариант или целочисленный алгоритм?
Что бы процессор в idle крутился не 40, а 60% времени? Или что бы свободного флеша у меня оставалось не 30, а 50% ?
Куда мне девать эти такты и килобайты? Солить на зиму?
Поэтому проще и быстрее взять флоатный логарифм (заодно не трахаться с пересчетом дробных коэффициентов, участвующих в расчетах, в целочисленные) и получить на выходе нужное мне число. Которое потом округлится в целочисленную переменную и засветится на шкале.
Управление двумя линейками диодов было сделано из таймерного прерывания, чтение полученных извне данных - там же. Заодно в том же таймерном прерывании еще и АЦП опрашивался и перезапускался. И его данные в массив для усреднения складывались...
Всё остальное процессорное время - в моем распоряжении..... И его для той задачи - много. Там можно считать что угодно, хоть float-ом, хоть double-ом... Подождать флаг прихода данных или обновления АЦП -пересчитать данные и обновить инфу для диодов..
Программа в восьмую мегу поместилась, около 30% флеша свободно осталось, в ТЗ по таймингам - умещалось с запасом.
А, и еще не надо спорить с заказчиком. Им надо было, что б все было точно-точно... Дали ТЗ с формулами - получили результат. Я получила денешшшшку. И все довольны.
Зачем мне тратить свое время в таком случае на придумывание?...

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

Пт мар 17, 2023 23:15:46

в данном случае ресурсов хватало и таймингов тоже. Зачем мне искать/придумывать ассемблерный вариант или целочисленный алгоритм? Что бы процессор в idle крутился не 40, а 60% времени? Или что бы свободного флеша у меня оставалось не 30, а 50% ? Куда мне девать эти такты и килобайты? Солить на зиму?
Вот, кстати, согласен на все 146%.
Управление двумя линейками диодов было сделано из таймерного прерывания, чтение полученных извне данных - там же. Заодно в том же таймерном прерывании еще и АЦП опрашивался и перезапускался. И его данные в массив для усреднения складывались...
Аналогичную задачу я решал (и решил) на 13-й тиньке, но (оффтопик!) на ассемблере, поскольку из прикидок на ардуине мне показалось, что на С, да ещё с логарифмом в плавающей запятой я в мелкую тиньку не уложусь: размер кода для 48-й атмеги даже без плавающей запятой был 1864 байта. На асме, конечно, уложился. Объём прошивки стал 760 байт, быстродействие упёрлось в АЦП, а не в процессор, и возник тот же самый вопрос: куда девать лишние такты и лишние байты (25% памяти)???
Зачем мне тратить свое время в таком случае на придумывание?...
Абсолютно справедливая постановка вопроса, ибо никогда не надо забывать про критерий разумной достаточности. :-)
Ответить