APJ, у вашей задачи есть типовое решение. Почти как сказал andriano, но не совсем. Запускающая функция читает первое значение, и программирует через это время прерывание. В прерывании читается следущее значение и программируется под него таймер, и так пока весь массив не будет обработан.
dimax, пока будет вызвано "следующее прерывание", пока функция считает и проанализирует очередные данные и т.п. - пройдет время.
Я не знаю, сколько тактов уходит в AVR на вызов прерывания (в stm32 гордятся, что у них всего 12 тактов), положим, порядка 1 мкс, еще пару уйдет на дальнейшее (для сравнения - digitalWrite() выполняется 7 мкс), т.е. к периоду в 60 мкс добавится еще несколько. IMHO точность задания интервалов будет ниже, чем в предложенном мной способе. Хотя, загрузка процессора прерываниями (т.е. доля времени, проводимая в них), конечно, меньше.
andriano, да там всё быстро. В массив обычно кладут заранее вычисленные такты таймера, а не микросекунды, ногами можно вообще не управлять, использовать аппаратный туглинг.
Я бы, может, и оценил мысль, если бы знал, что такое туглинг (гугл на запрос предлагает "туннелирование"). Однако "там все быстро" отнюдь не опровергает моего тезиса, что на каждом прерывании добавляется 2-3 лишних микросекунды. Для кото-то это "быстро", а для кото-то это 4-5%. А в массив, естественно, кладется то, что удобнее для данногослучая. Напрример, в описанном мною случае кладутся не такты таймера, а количество прерываний, которое надо пропускать.
andriano, Это я некорректно произношу toggling (Toggle on compare match mode) , у кого-то услышал это каверканье, и привязалось, знаю, надо переучиваться по-правильному :-)
А дисководную музыку помню, да) Там конечно лишние микросекунды погоды не делают.
andriano, Об чём вы? Ну возьмём например "ля" 440Гц, или >2000uS. Пару микросекунд тут не решат. Конечно чем выше частота, тем... но так дисководы и не умеют как скрипочка пиликать)
dimax, вообще-то нота "ля", не одна - их целых 8 в разных октавах. И для двух из восьми (а третья - где-то на пределе) эта пара микросекунд уже приведет к заметной на слух шальши.
И вообще, мне кажется, уместнее оперировать конкретными числовыми оценками, а не категориями "там все быстро" и "ничего не решает".
Тем не менее, советую AКJ заглянуть по приведенной мной ссылке - как раз для его задачи там содержится не только подходящее, но даже масштабируемое решение.
Я не знаю, сколько тактов уходит в AVR на вызов прерывания
Если с ардуины -то вход выход в прерывание порядка в сумме 60-80 команд. Грубо говоря 100-120 тактов. Возможно в последних версиях быстрей. Если на голом си то в разы менше.
Но тут еще надо помнить что таймер может выставить флаг прерывания во время работы обработчика другого прерывания, uart например, и пока тот не кончится - обработчик таймера не стартанет. Или еще где прерывание запретят на какое время. Вобщем 60мксек - неудобный интервал, с какой стороны не подступись.
Кстати, а чего таймером 60мксек делать? Там требуется 120, 300, 400 - вот их сразу и формировать, чтоб лишний раз не дергатся. А научившись настраиватся на 60 не так уж трудно и на переменную длительность сделать, только настраивать таймер так, чтоб не терялось время от завершения предыдущего интервала до момента настройки.
Buzoff, кстати забыл сказать - некоторые модели stm32 имеют аппаратный автодетект скорости uart :) Правда в "народной" серии F103 к сожалению нету.
а не вкурсе, какой там алгоритм определения? может есть какие-то моменты, которые помогут с большей вероятностью определять правильную скорость с помощу атмеги.
Buzoff, не в курсе. Наверняка есть какие-то документы на этот счёт на сайте st, поищите. В любом случае нужно измерять длительность старт-бита. На меге измерить единицы микросекунд в принципе трудно, а без применения ассемблера так вообще вряд ли возможно, почитайте про мои тесты в ветке про микрос.
способ с таймером может реагировать на смену значения на порту, с LOW на HIGH и наоборот одновременно (по аналогии с прерыванием CHANGE)?
Может, но с нюансом - либо одно, либо другое. Логика выбирается битом ICES (Input Capture Edge Select). Но это не проблема, в своём примере я как раз ловлю и так и эдак именяя этот бит, обратите внимание на комменты в функции rising(falling) icp detect.
я правильно понимаю, что функция uint16_t asm_func() будет делать подсчет, только в момент обращения к ней, и на некоторое время будет останавливать основной код (пока будет ожидать импусы)?
и для того чтоб она делала подсчет по факту наличия импульса, нужно использовать внешнее прерывание?
тогда если я буду обращатся к функции по внешнему прерыванию, то скорее всего первый импульс она пропустит и будет ждать следующий, а при следующем импульче внешнее прерывание снова обратися к функции, и таким образом не давая делать подсчет или делать подсчет не каждое прерывание изза флагов.
как вариант думал, по первому внешнему прерыванию запустить цикл на некоторое время и крутить данную функцию, собирая данные в массив.
или может есть какая-то возможность подсчитывать такты между каждым внешним прерыванием, как это делается с МИКРОС, сранивая новое и старое значение
тогда если я буду обращатся к функции по внешнему прерыванию, то скорее всего первый импульс она пропустит и будет ждать следующий
Балинн.. вы плохо прочли. Если вы хотите измерять микросекунды -забудьте про прерывания. Я же писал, что 700nS уходит только что б зайти в голое прерывание. Пока дойдёт дело до измерения стартовый бит уже проскочит. Вообще тема изначально тупиковая, на AVR такое бессмысленно мутить. Справиться с задачей сможет таймер в stm32, он без всяких прерываний может измерять импульс. А если брать стм32 -то сразу ту модель, которая с автодетктом. Задача сама собой отпадёт.
Хотя может и не всё так плохо, заглянул в апноут от стм, там есть вариант софтового измерения. Предлагают измерять целый пакет, и потом вычислять скорость. Есть пример, но не ардуино френдли :)
тогда если я буду обращатся к функции по внешнему прерыванию, то скорее всего первый импульс она пропустит и будет ждать следующий
Балинн.. вы плохо прочли. Если вы хотите измерять микросекунды -забудьте про прерывания. Я же писал, что 700nS уходит только что б зайти в голое прерывание. Пока дойдёт дело до измерения стартовый бит уже проскочит. Вообще тема изначально тупиковая, на AVR такое бессмысленно мутить. Справиться с задачей сможет таймер в stm32, он без всяких прерываний может измерять импульс. А если брать стм32 -то сразу ту модель, которая с автодетктом. Задача сама собой отпадёт.
я это все понимаю, но мне не нужно измерять импульсы в пару микросек.
самый короткий импуль, который мне нужно засечь - 8мкс (115200бод), но не с погрешностью +/- 4, как у микрос.
ладно, пока поэксперементирую с вашив кодом, посмотрю, что вообще получается.
Buzoff, кстати а как вы измеряли то, по какой методике? Там ведь полно граблей. Вот например если послать ноль по сериалу, то все биты слипнутся в лог.ноле, и будет один большой импульс. Получается нужно какое-то время на ожидание всей посылки..
Buzoff, кстати а как вы измеряли то, по какой методике? Там ведь полно граблей. Вот например если послать ноль по сериалу, то все биты слипнутся в лог.ноле, и будет один большой импульс. Получается нужно какое-то время на ожидание всей посылки..
ну когда использовал прерывание, я записывал все полученые интервалы в массив на протяжении 100мс (время обусловлено спецификой устройства на котором пытаюсь определять скорость), а потом анализирую полученый массив. устройства шлют пакеты байт, на практике пока не анализировал, но я надеюсь что там будут присутствуют такие очередности бит как 010 и 101. аналогично хочу поробовать и с таймером, в определенный момент запустить цикл на теже 100мс и крутить вашу функцию. полученные показания тоже хотелось бы собирать в массив, и потом анализировать.
почитал как работает автоопределение корости на smt, так там алгоритм примитивнее чем у меня, куча условий, которые ужно соблюсти, иначе ничего не определится. для моего случая это не подойдет.
Ок, буду пробовать. Пока ничего дельного не выходит
APJ, у вашей задачи есть типовое решение. Почти как сказал andriano, но не совсем. Запускающая функция читает первое значение, и программирует через это время прерывание. В прерывании читается следущее значение и программируется под него таймер, и так пока весь массив не будет обработан.
dimax, пока будет вызвано "следующее прерывание", пока функция считает и проанализирует очередные данные и т.п. - пройдет время.
Я не знаю, сколько тактов уходит в AVR на вызов прерывания (в stm32 гордятся, что у них всего 12 тактов), положим, порядка 1 мкс, еще пару уйдет на дальнейшее (для сравнения - digitalWrite() выполняется 7 мкс), т.е. к периоду в 60 мкс добавится еще несколько. IMHO точность задания интервалов будет ниже, чем в предложенном мной способе. Хотя, загрузка процессора прерываниями (т.е. доля времени, проводимая в них), конечно, меньше.
andriano, да там всё быстро. В массив обычно кладут заранее вычисленные такты таймера, а не микросекунды, ногами можно вообще не управлять, использовать аппаратный туглинг.
Я бы, может, и оценил мысль, если бы знал, что такое туглинг (гугл на запрос предлагает "туннелирование"). Однако "там все быстро" отнюдь не опровергает моего тезиса, что на каждом прерывании добавляется 2-3 лишних микросекунды. Для кото-то это "быстро", а для кото-то это 4-5%. А в массив, естественно, кладется то, что удобнее для данногослучая. Напрример, в описанном мною случае кладутся не такты таймера, а количество прерываний, которое надо пропускать.
Кстати, вспомнил, я, оказывается, делал как раз так, как написал. Только период опроса чуть поменьше, и управление не 1, а 7 устройствами. http://arduino.ru/forum/proekty/floppy-hdd-music
andriano, Это я некорректно произношу toggling (Toggle on compare match mode) , у кого-то услышал это каверканье, и привязалось, знаю, надо переучиваться по-правильному :-)
А дисководную музыку помню, да) Там конечно лишние микросекунды погоды не делают.
А дисководную музыку помню, да) Там конечно лишние микросекунды погоды не делают.
Ни фига себе не делают!
6% - полутон.
andriano, Об чём вы? Ну возьмём например "ля" 440Гц, или >2000uS. Пару микросекунд тут не решат. Конечно чем выше частота, тем... но так дисководы и не умеют как скрипочка пиликать)
dimax, вообще-то нота "ля", не одна - их целых 8 в разных октавах. И для двух из восьми (а третья - где-то на пределе) эта пара микросекунд уже приведет к заметной на слух шальши.
И вообще, мне кажется, уместнее оперировать конкретными числовыми оценками, а не категориями "там все быстро" и "ничего не решает".
andriano, про ноты речь шла применительно к вашим дисководным звукам.
намек понял
Тем не менее, советую AКJ заглянуть по приведенной мной ссылке - как раз для его задачи там содержится не только подходящее, но даже масштабируемое решение.
[quote=andriano]
Уже заглянул. Пока что ничего не понял.
Я не знаю, сколько тактов уходит в AVR на вызов прерывания
Если с ардуины -то вход выход в прерывание порядка в сумме 60-80 команд. Грубо говоря 100-120 тактов. Возможно в последних версиях быстрей. Если на голом си то в разы менше.
Но тут еще надо помнить что таймер может выставить флаг прерывания во время работы обработчика другого прерывания, uart например, и пока тот не кончится - обработчик таймера не стартанет. Или еще где прерывание запретят на какое время. Вобщем 60мксек - неудобный интервал, с какой стороны не подступись.
Кстати, а чего таймером 60мксек делать? Там требуется 120, 300, 400 - вот их сразу и формировать, чтоб лишний раз не дергатся. А научившись настраиватся на 60 не так уж трудно и на переменную длительность сделать, только настраивать таймер так, чтоб не терялось время от завершения предыдущего интервала до момента настройки.
Вобщем 60мксек - неудобный интервал, с какой стороны не подступись.
Кстати, а чего таймером 60мксек делать? Там требуется 120, 300, 400 - вот их сразу и формировать, чтоб лишний раз не дергатся.
Там не было 400, было 480. 60 - наибольший общий делитель.
Buzoff, кстати забыл сказать - некоторые модели stm32 имеют аппаратный автодетект скорости uart :) Правда в "народной" серии F103 к сожалению нету.
а не вкурсе, какой там алгоритм определения? может есть какие-то моменты, которые помогут с большей вероятностью определять правильную скорость с помощу атмеги.
Buzoff, не в курсе. Наверняка есть какие-то документы на этот счёт на сайте st, поищите. В любом случае нужно измерять длительность старт-бита. На меге измерить единицы микросекунд в принципе трудно, а без применения ассемблера так вообще вряд ли возможно, почитайте про мои тесты в ветке про микрос.
способ с таймером может реагировать на смену значения на порту, с LOW на HIGH и наоборот одновременно (по аналогии с прерыванием CHANGE)?
Может, но с нюансом - либо одно, либо другое. Логика выбирается битом ICES (Input Capture Edge Select). Но это не проблема, в своём примере я как раз ловлю и так и эдак именяя этот бит, обратите внимание на комменты в функции rising(falling) icp detect.
я правильно понимаю, что функция uint16_t asm_func() будет делать подсчет, только в момент обращения к ней, и на некоторое время будет останавливать основной код (пока будет ожидать импусы)?
и для того чтоб она делала подсчет по факту наличия импульса, нужно использовать внешнее прерывание?
Buzoff, Да, верно понимаете.
Buzoff, Да, верно понимаете.
тогда если я буду обращатся к функции по внешнему прерыванию, то скорее всего первый импульс она пропустит и будет ждать следующий, а при следующем импульче внешнее прерывание снова обратися к функции, и таким образом не давая делать подсчет или делать подсчет не каждое прерывание изза флагов.
как вариант думал, по первому внешнему прерыванию запустить цикл на некоторое время и крутить данную функцию, собирая данные в массив.
или может есть какая-то возможность подсчитывать такты между каждым внешним прерыванием, как это делается с МИКРОС, сранивая новое и старое значение
тогда если я буду обращатся к функции по внешнему прерыванию, то скорее всего первый импульс она пропустит и будет ждать следующий
Балинн.. вы плохо прочли. Если вы хотите измерять микросекунды -забудьте про прерывания. Я же писал, что 700nS уходит только что б зайти в голое прерывание. Пока дойдёт дело до измерения стартовый бит уже проскочит. Вообще тема изначально тупиковая, на AVR такое бессмысленно мутить. Справиться с задачей сможет таймер в stm32, он без всяких прерываний может измерять импульс. А если брать стм32 -то сразу ту модель, которая с автодетктом. Задача сама собой отпадёт.
Хотя может и не всё так плохо, заглянул в апноут от стм, там есть вариант софтового измерения. Предлагают измерять целый пакет, и потом вычислять скорость. Есть пример, но не ардуино френдли :)
тогда если я буду обращатся к функции по внешнему прерыванию, то скорее всего первый импульс она пропустит и будет ждать следующий
Балинн.. вы плохо прочли. Если вы хотите измерять микросекунды -забудьте про прерывания. Я же писал, что 700nS уходит только что б зайти в голое прерывание. Пока дойдёт дело до измерения стартовый бит уже проскочит. Вообще тема изначально тупиковая, на AVR такое бессмысленно мутить. Справиться с задачей сможет таймер в stm32, он без всяких прерываний может измерять импульс. А если брать стм32 -то сразу ту модель, которая с автодетктом. Задача сама собой отпадёт.
я это все понимаю, но мне не нужно измерять импульсы в пару микросек.
самый короткий импуль, который мне нужно засечь - 8мкс (115200бод), но не с погрешностью +/- 4, как у микрос.
ладно, пока поэксперементирую с вашив кодом, посмотрю, что вообще получается.
Buzoff, кстати а как вы измеряли то, по какой методике? Там ведь полно граблей. Вот например если послать ноль по сериалу, то все биты слипнутся в лог.ноле, и будет один большой импульс. Получается нужно какое-то время на ожидание всей посылки..
Buzoff, кстати а как вы измеряли то, по какой методике? Там ведь полно граблей. Вот например если послать ноль по сериалу, то все биты слипнутся в лог.ноле, и будет один большой импульс. Получается нужно какое-то время на ожидание всей посылки..
ну когда использовал прерывание, я записывал все полученые интервалы в массив на протяжении 100мс (время обусловлено спецификой устройства на котором пытаюсь определять скорость), а потом анализирую полученый массив. устройства шлют пакеты байт, на практике пока не анализировал, но я надеюсь что там будут присутствуют такие очередности бит как 010 и 101. аналогично хочу поробовать и с таймером, в определенный момент запустить цикл на теже 100мс и крутить вашу функцию. полученные показания тоже хотелось бы собирать в массив, и потом анализировать.
почитал как работает автоопределение корости на smt, так там алгоритм примитивнее чем у меня, куча условий, которые ужно соблюсти, иначе ничего не определится. для моего случая это не подойдет.