Свежие обсуждения
Микроконтроллеры

Частотомер на AVR

1 3 7

Сдела таблицу в Excele из 20-ти измерений со всеми значениями. Так что отклонения измеряной величины начинаются раньше чем через 18-ть измерений, просто VMlab их показывает вот в таком фомате 1.0е+06(в действительности может быть, например, 1000253Гц ), что и вводило меня в заблужление.

148380.xls

 

Опять у вас теряется 256 импульсов. В п.п.8, 9, 10 и 11 значение М должно быть меньше на 256, тогда измеренная частота будет точно равна 1000000 Гц. В п.18 значение М должно быть больше на 256. Ещё в нескольких пунктах у вас ошибка достигает 2 Гц, это плохо, т.к. максимальная теоретическая ошибка для секундного интервала измерения и входной частоты 1000000 Гц равна +-0,125 Гц. Все ваши измерения по моему методу должны лежать в пределах от 999999.975 до 1000000.125 Гц

Чудес не бывает. Явно где-то теряется или добавляется перенос, как-то связанный с обработкой прерывания от переполнения таймера0. Давайте смотреть си-программу и код, полученный компайлером. Заодно и схему подключения измеряемой частоты к МК.

 

Вот СИ код с последними изменениями:

 

А также asm полученный компайлером:

148460.asm

 

Блин чегото не преципился

148463.c

 

Вот что с ходу не так:

1) Схема захвата у вас срабатывает на спад, это единственно верно. А вот счётчик0 у вас срабатывает тоже на спад, что не совсем правильно, надо от фронта, чтобы счётчик0 и захват срабатывали от одного перепада, а не от разных.

2) Во время обработки прерывания по захвату может произойти переполнение счётчика0, таким образом вы можете потерять одно переполнение (перенос), а с ним и 256 импульсов входной частоты, что мы и наблюдаем, возможно, здесь и была зарыта собака (. Примите меры, скажем, проверьте нет ли ждущего прерывания по переполнению счётчика0 и скорректируйте результат.

Кстати вот, когда вы возвращаетесь из прерывания по захвату, а это может быть достаточно длинное время, вы используете Perepol_Timer0, а оно уже изменилось, так что лучше его не использовать. Лучше сделать как-то так. Заведите ячейку overflow0 и в прерывании перепишите туда из Perepol_Timer0. Если в прерывании по захвату было отложенное прерывание по переполнению счётчика0, то надо скорректировать overflow0 (добавить 256). И использовать затем overflow0 при вычислении М и М0. На самом деле, всё не так просто, поскольку переполнение может случиться в любой момент. Я делал так: читал TCNT0, потом проверял не было ли переноса и если был, то читал второй раз. Если не было переноса, первый результат был верный, если случился перенос, то - второй.

Пока всё, посмотрю ещё.

 

Я сильно не вникал, но возможно, проблема в том, что приоритет прерывания по захвату выше, чем приоритет таймерного прерывания.
Вот здесь я спрашивал про эту проблему на электрониксе, там есть ссылка на обсуждение и моё окончательное решение на Си.

 

По-моему, здесь по прерываниям в чистом виде не подойдёт. У Y@rikа тактовая частота МК равна 8 МГц, а входная частота - 1 МГц. Всего 8 машинных циклов между прерываниями захвата, а там один вход в прерывание занимает 4 (на сохранение СК)+2 (на переход из вектора) +1-2-3 (на завершение текущей команды) = 7-9 МЦ. Только он собрался что-то сделать, а тут уже новое прерывание возникло. А в пределе входная частота должна быть 4 МГц, т.е. 2 МЦ между прерываниями захвата, ну какое прерывание успеет обработаться, тем более на си?

 

Да нет, я не имел в виду, что надо делать именно так. Там задача совсем другая. Я имел в виду, что возможно проблема в том же.
Хотя там обращение к счётчику прерываний таймера1 происходит уже в основном цикле, но...

Вот смотрите:

delay_ms(1000);//Задержка на 1 с
PORTC.0=1;//TIMSK|=0x20;//Разрешили захват
while ((TIFR&0x20)==0x20){}//Ожидание прерывания по захвату

Потом сразу расчёт. Прерывание по захвату, как я понимаю, продолжает лупить? Поэтому прерывание по таймеру может и вовсе не вызываться.
Надо после этих строк снова запретить захват, потом пару nop-ов (чтобы ожидающее таймерное прерывание отработало), а уже потом - считать.

Кстати, и в первый раз (первая засечка) тоже не вижу запрета прерываний от захвата. При такой частоте на входе можно запросто пропустить прерывание от таймера.

 

AHTOXA: Потом сразу расчёт. Прерывание по захвату, как я понимаю, продолжает лупить?
Нет в обработчике прерывния по захвату, вход захвата отключается от источника сигнала, подачей низкого уровня на один из входов элемента 2И-НЕ( PORTC.0=0;).
::::::::::::::::::::::::::::::::: _____::::::::::::::::::::::::::::::::::::::
:::::::::::::::::::::Fx------|:&::::::::|::::::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::|::::::::::::|o------Вход захвата.
::::::Упр.(PB0)------|_____|:::::::::::::::::::::::::::::::::::::
:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::