0 / 0 / 0
Регистрация: 05.02.2010
Сообщений: 167
|
|
1 | |
Timer 1. Прерывание по таймеру = +- 1шаг. Как избавиться?21.02.2010, 02:39. Показов 8829. Ответов 8
Метки нет (Все метки)
Есть такая проблемка. При возникновении прерывания запись в порт возникает с разницей в +- 1-н машинный такт. Как сделать, чтоб небыло такого разброса? Или хотябы в одну сторону постоянно было.
частота проца - 4 MHz время мигания светодиода - 1 секунда 999936.00 us 999936.25 999936.00 999935.75 999936.00 999936.25 Получается как раз не одна секунда. Проект в AVR Studyo прилагается))) Формула для расчета времени срабатывания (тактов) TCNT1=0x10000L-(xtal/1024L/fmove); fmove может быть разной. [60.17 Кб]
0
|
21.02.2010, 02:39 | |
Ответы с готовыми решениями:
8
Прерывание по таймеру Прерывание по таймеру Прерывание по таймеру Прерывание программы по таймеру STM32L прерывание по таймеру |
0 / 0 / 0
Регистрация: 05.02.2010
Сообщений: 167
|
|
21.02.2010, 02:49 | 2 |
И еще как поменять частоту на которой симулируется в AVR Studyo? Там стоит 4 мегагерца, и надо свой проект на ету частоту стачить...???????
0
|
Shodow
|
|
21.02.2010, 03:14 | 3 |
Поменять частоту в AVR Studyo можно с помощью меню Debug->AVR Simulator Options.
Время различно так как в случае возникновения прерывания во время выполнения длинной команды (2-3 такта) контролер сначала закончит выполнение команды, а затем перейдёт к вектору прерывания. |
0 / 0 / 0
Регистрация: 26.01.2010
Сообщений: 273
|
|
21.02.2010, 10:59 | 4 |
Короче нужно использовать прерывание по совпадиению. Так будет проще и нагляднее. Тогда в счетчик каждый цикл ничего писать не нужно будет.
Сайчас в счетчик каждый раз записывается заначение, и ошибка, с которой пришло прерывание, суммируется. Кстати +/- тут невозможно. Возможно только в "плюс" 0-1-2 лишних такта. Если критичны эти 1-2 такта (НЕ НАКАПЛИВАЕМОЙ ОШИБКИ) то можно подравнятьвот такой конструкцией: Код
TIM0_OVF: nop ; сохраняем контекст программы nop ; nop ; in temp,tcnt0 subi temp,(7+n) ; сдесь под n понимается число тактов, ; необходимое для сохранения контекста brmi otygn1 otygn1: dec temp3 brmi otygn2 otygn2: nop ; эта операция будет выполняться через nop ; точное колличество циклов nop ; reti
0
|
0 / 0 / 0
Регистрация: 05.02.2010
Сообщений: 167
|
|
21.02.2010, 20:23 | 5 |
Спасибо Shodow. Наконец-то теперь вкурил как менять частоту кварца. )))
Спасибо и SOWushko. С попами можно конечно загасить лишние такты, но невсегда. При одном кварце и одном числе по которому идет прерывание по совпадинию - будет точно выдержанно время. А если мы поменяем число - до которого надо считать, то опять будут ходить последние цифры))) +0, 1, 2 такта. Я вот дума точно не будет никогда, если будем менять до скольки считать . (Посимулировал в AVRStudyo схемку часов по совпаденю http://habrahabr.ru/btogs/gadgets/38443/). Спасибки)) Мне надо ето для управлением драйвером шагового двигателя. Точнее нужно дергать ножкой МК. Наверное последние знаки не будут влиять на работу))
0
|
0 / 0 / 0
Регистрация: 26.01.2010
Сообщений: 273
|
|
21.02.2010, 23:04 | 6 |
Сообщение от rot20
Вы видимо имели в виду команду "nop"? и видимо глянув на код решили что я предлагаю гасить "лишнее время" простоем процессора? =))) Так вот, обьясняю еще раз. Очень подробно. Вход в прерывание происходит при трех обязательных условиях: 1) Прерывание разрешено 2) Произошло событие (в нашем случае это события таймера-счетчика "переполнение", а если интервылы не меняются - лучше "совпадение") 3) процессор не выполняет длинную операцию. И если с первыми двумя особых проблем нет, то третье - это проблема. (Тут нужно сказать, что в случае зажигания светодиодов - это не проблема, а в случае когда важно соблюдать точность в десятые доли микросекунды - это важно.) Почему происходит эта задержка. Да потому что у АВР есть длинные команды, которые выполняются не за 1, а за 2-3 такта. Так вот если событие ("преполнение" или др.) произошло после первого такта длинной комманды, то задержка будет 1-2 такта, для 2-3 тактовых операций соответственно. В вашем варианте программы, вы входите в обработчик прерывания и меняете значение счетчика. Если вход в прерывание всегда будет во время выполнения коротких операций - то все хорошо. Интервалы ровные. НО! Если прерывание приходит во время длинной операции мы входим в обработчик позже. Не учитывая этого вы опять меняете значение счетчика. Итого каждый раз, когда мы входим в прерывание во время длинной операции время прихода следующего прерывания - смещается. На миллионе таких вот ошибок мы получим смещение на миллион-другой тактов. Если мы используем прерывание по совпадению, то выполнение обработчика может запаздать на 1-2 такта. Но дрейфа этого не будет! Тот листинг который привел я выравнивает задержки, и делает абсолютно точными (с точностью до такта) интервалы межде началом выполнения кода с меткой "otygn2" после него можно изменять значение счетчика на требуемое и использовать событие "переполнение". Но делать так при одинаковых интервалах - глупо. Команды nop ножно заменить кодом, предварительно прочитав комментарий написаный после этих самых нопов =)) Желаю удачи, и никогда не делать черезчур поспешных выводов.
0
|
0 / 0 / 0
Регистрация: 05.02.2010
Сообщений: 167
|
|
23.02.2010, 00:43 | 7 |
Спасибки))) За разъяснения))!! НЕ буду делать поспешных выводов)
Я так понял от TIM0_OVF: до reti. ето наше прерывание А in temp,tcnt0 -ето запись числа из счетчика в temp. потом вычитаем етой коммандой subi temp,(7+n) - из темт число 7+n, Если результат отрицательный, то переходим по метке brmi otygn1. Метка otygn1: dec temp3 - вычитаем из temp3 единичку. ЧТО за темп3? Чему он равен? НАверное нулю?! И опять если результат отрицательный, то переходим на brmi otygn2. А где заносить новое число, до которого надо считать таймеру? Наверное после метки otygn2? Счетчик считать будет постоянно до одной величины тактов, но в целой программе - можно менять, и придется менять етот счетчик. Люблю людей с чувством юмора!!!! Если так, то вот еще посмейся немножко до кучи)))))) Играли в бильярд трое или четверо парней, и девчонка. Ну вот когда били из лузы шар. ДЕвушка сказала, что ето выстрел из дырки)))) Смеялись тоже долго))))))))))))))
0
|
0 / 0 / 0
Регистрация: 26.01.2010
Сообщений: 273
|
|
23.02.2010, 21:45 | 8 |
Temp3 - это опечатка. Конструкция эта "выравнивает" время которое потребовалось на то чтобы зайти в счетчик. После того как спроисходит событие которое вызвало прерывание счетчик сбрасывается. То есть вариант когда у нас прерывание по совпадению, но счетчик не сбрасывается, нужно это учесть при сравнении temp с числом. Если вход в обработчик не "запаздывает", то конструкция выполняется за 7 тактов, если запаздывает на 1 - то за 6 тактов, и соответственно на 2 - за 7 тактов.
0
|
0 / 0 / 1
Регистрация: 22.01.2010
Сообщений: 4,000
|
|
26.02.2010, 22:07 | 9 |
Есть один извратский метод. Подходит для поимки очень коротких выдержек.
точка ожидания условия: NOP ; дальше полигон из NOP NOP NOP NOP NOP NOP ... Т.е. добиваемся того, чтобы у нас прерывание произошло исключительно на этом полигоне. Да это сожрет дофига флеша, но зато время выполнения будет четко гарантированной длины. Т.к. не будет ни одной левой команды в момент выполнения. Выход из прерывания делается тоже хитро - мы меняем адрес возврата на конец полигона (чтобы по нему не скакать) и делаем RETI Еще можно помозговать и завернуть два условия. Одно срабатывает если есть событие, другое если нет. Т.е. как ни крути у нас в цикле ожидания будет один переход, что выровняет длину цикла ожидания и тоже даст четкое время срабатывания.
0
|
26.02.2010, 22:07 | |
26.02.2010, 22:07 | |
Помогаю со студенческими работами здесь
9
stm32f429 прерывание по таймеру Прерывание по таймеру на C++ в консоли Не отключается прерывание по таймеру Не работает прерывание по таймеру в STM32f411RE Прерывание по таймеру раз в пол-секунды Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |