Как стать автором
Обновить

Комментарии 19

Я никогда не слышал ничего об AVR, но первый запрос в Гугле avr assembler sleep выдаёт что есть такая интсрукция как SLEEP. Можете сравнить её с вашим подходом?
(это я к тому, что перед реализацией всегда стоит посмотреть есть ли что-то готовое; пустые циклы негативно влияют на энергопотребление, если есть аппаратная возможность задержки, то лучше пользоваться ей)
Этот sleep просто переводит контроллер в энергосберегающий режим, без отсчетов времени.
Ясно. Значит мой комментарий неуместен.
но с ассемблером ковыряюсь недели 2, и пока не понял, как вынести все это в отдельный модуль, и сделать функцию в нем соответствующую.
Так как вы уже сохраняете все используемые регистры в макросе (push/pop), то можете просто вынести его тело в подпрограмму, передав время в качестве параметра или через стек, или через регистры.

Вообще, по опыту, полезность этой подпрограммы спорная. Если проект пишется на ассемблере, то явно под конкретный МК и под конкретную частоту. Все эти задержки высчитываются один раз на этапе написания, что экономит программную память, а так же работает намного точнее.
Вот, для примера, можете посмотреть реализацию 1-wire, где используются точные задержки: тыц (где-то 1300я строка baro_clock.asm)
Это проект часов с термометром, барометром и пультом ДУ (обучаемым) на Atmega48, работает год у меня без сбоев. Код подробно раскоментирован.
Что-то с кодировкой, так предполагаю вы не AVR Studio писали?
Я так понял на 16 MHz оно у вас работает?
микросекунды не делал подсчет (в принципе реализуемо), а вот миллисекунды считает при любой частоте не менее 1,3 MHz
Кодировка UTF-8, писалось в текстовом редакторе, компилировалось gavrasm под линуксом.
Я так понял на 16 MHz оно у вас работает?

20МГц.
Макросы занимают во флеше 34,78,198 байт. Суть в том что в 7 местах в коде ставилось по 15-20 NOP, что выглядело, по мне, не очень кошерно (думаю это от избалованности ЯП высоко уровня). При частоте <1,3 MHz не покатит точно, но я писал это в целях получения опыта и естественно на конкретный мк (но в принципе подходит на многие avr), так что если кому понадобится могут допилить под своё)
Но все-таки надо будет сделать в виде подпрограммы, только затраты на вызов посчитать.
Можете не считать, затраты на вызов 4 такта :)
Немного отступая от темы… Никто не замечал что этот самый _delay_ms врёт? притом легко может обмануть где-то процентов на 30. Или это у меня что-то не так.
А разверните эту функцию. Она объявлена где то в .h файлах идущих в поставке вместе со средой программирования от производителя контроллера. Там пустой цикл на нужное количество тактов. Соответственно время задержки будет не точное если есть, например, обработка прерываний.
Точно! Прерывания, что-то про них я и не подумал, спасибо. Значит все-таки на таймере делать задержки гораздо лучше. Хотя зависит конечно от задачи. (Виртуально вас плюсую :) )
Мне понравилось такое решение:
delay:           
  ldi delay2,$01  
  ldi delay1,$77  
  ldi delay0,$00  ; $017700 - даст задержку в 50мс при 9.6МГц
  loop:
    subi delay0,1 
    sbci delay1,0 
    sbci delay2,0
    brcc loop

из книжки «Практическое программирование микроконтроллеров Atmel AVR на языке ассемблера» Ю. Ревич с. 93-94
Самое чудесное у Вас случится когда такая «чудо функция» окажется внутри обработчика прерываний.
Так что для точных таймингов и забивания головы какие функции можно или нельзя использовать только аппаратный таймер. Благо что в AVR их завались и повесить на него программное прерывание для подсчёта не проблема.
Да не завались, в лучшем случае их три-четыре, а если используется ШИМ, режимы захвата или что-то ещё, то таймеров ой как не хватает.
Но всё же я бы не стал измерять время такой «универсальной» функцией, а реализовал бы алгоритм для конкретной задачи.
Все три заняты, в том то и вся проблемы. Там на плате вообще весь мк обвешан))
Я ж не на часы программу пишу)
Добрый день!

Ни в коей мере не претендую на профессионализм (контроллеры для меня хобби), однако мне совершенно непонятно, зачем писать для AVR на ассемблере? Если не хватает памяти, купите AVRку помощнее. Неужели все настолько упирается в цену кристаллов и совершенно не учитывается стоимость разработки и поддержки? А по теме, для задержек лучше использовать все же аппаратный таймер + спинлок, даже на ассемблере. Опять же, если не хватает таймеров, поставьте кристалл где таймеров 5 штук, либо используйте 1 таймер для разных задач (например 2 таймера для ШИМ, а третий для всего связанного со временем).
В том месте где я работаю всё уперлось в деньги) код на ассемблере по каким-то невиданным причинам (можно было обойтись вставками в Си) писали еще год назад, теперь настало моё время его поддерживать)
3 имеющихся таймера постоянно переинициализируются (2 режима, один для приема другой для передачи), так судя по всему еще и третий режим будет для индикации)
Основная цель заменить имеющиеся вот такие конструкции:

NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP
NOP

на
DELAY_CL 20
Ну и просто интересно было реализовать подобное)
Есть программы, формирующие Assemblerный код под нужную задержку и частоту контроллера.
Есть web приложение AVRDelayCalculator которое формирует Assemblerный код под нужную задержку и частоту контроллера. Интерфейс можно переключить на Русский язык. Адрес страницы.
В поисковике можно найти по названию, название в строке поиска нужно ввести в кавычках.
Будут вопросы, пишите алгоритм проверен годами. Сначала был реализован в виде программы, но потом реализовал как web приложение. Метод рассчёта коэффициентов табличный, поэтому проблем со временем вычисления коэффициентов нет.

image
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации