Позвольте с Вами подискутировать. Пробовали использовать эти функции? Они компилируются в неимоверно громоздкий и очень медленный код, который тоже в большинстве случаев никуда не годится. Кроме того, в AVRmega есть аппаратная поддержка чисел с плавающей фиксированной точкой, которая не используется в Си. Реализация математических функций путём разложения в ряд не очень-то и сложна на ассемблере, и при том получается терпимое быстродействие. Да и 32-битная (или 23-х в случае с плавающей точкой) точность, которую Вы получите в Си нужна очень редко. То есть, если Вам не нужна вся математическая библиотека, а нужны одна-две функции, да еще с не очень большой точностью - то вполне оправдано использование ассемблера. Если же нужна вся - чтоже, можно взять ATmega128, и написать компактненькую программу на си, которая в итоге скомпилится в сотню килобайт двоичного кода и даже будет работать (пусть даже быстродействия будет достаточно). Но тут уже неясно, зачем использовать дорогущий 8-битный микроконтроллер, когда 32-битки уже стоят копейки, а для поставленной задачи скорее всего сгодится самый простой из 32-битных микроконтроллеров.Alkul писал(а):И наоборот, если требуется относительно неспешно рассчитывать что-то тригонометрическое, гораздо проще использовать Си, чем писать на ассемблере подпрограмму расчета, допустим, функции арктангенса. Или, к примеру, если требуются вычисления с плавающей точкой.
Еще есть нюанс так же в операциях умножения, деления, и других простых математических операциях. libc не выделяет эти операции в отдельные процедуры, а компилирует голым кодом - т.е. размер итогового бинарника прямо пропорционален количеству таких операций. В tinyAVR это вообще кошмар, т.к. там нет даже аппаратного умножения. Это заставляет писать вот такой код:
Код: Выделить всё
int mul(int a, int b) { return(a*b); }И потом использовать для умножения эту функцию. Оно вроде и не сложно, но не умея читать листинг, человек не разберётся, что именно и где нужно оптимизировать и выделять в отдельные процедуры, если его кто-то не ткнёт носом.
Здесь я полностью соглашусь и добавлю еще что проблема тайминга присутствует не только при генерации сигналов высокой частоты. Пример - наличие двух прерываний: одно срабатывает часто, а другое выполняется долго. Вот, запуск второго прерывания приведёт к дисфункции первого.Alkul писал(а):Как Вы будете решать эту задачу на Си? Разве Вы можете с уверенностью сказать, в какие именно ассемблерные команды и каким образом компилятор превратит printf() в машинный код и какие при этом будут временные тайминги полученных импульсов?
Когда пишешь что-либо на Си, всегда приходится задумываться о быстродействии той или иной операции, либо заглядывать в листинг, и смотреть, что он там накомпилил, иначе отладка программ занимает больше времени, чем написание с нуля на ассемблере.
Впрочем, если человек решил что ему нужен именно Си, то вряд ли получится его переубедить, потому что психология здесь такая: цепляться за любой намёк на преимущества Си, и игнорировать все остальное. Как ни крути, любой человек учится на своих ошибках, не смотря на то что другие делятся с ним опытом.


