привет всем , попытался сделать таймер с точностью 1 мкс в режиме СТС , то есть на таймере1 (65535 тактов заполнения таймера , для точности 1 мкс нужно 16 тактов + вкл выключение , но точности менее 5 мкс получить не удалось таким способом , меняя количество тактов для прерывания СТС режима , значение счетчика меняется только при значениях выше 200-500 тактов или даже выше ( проверял на 2600 там меняется ) т. е. что 20 тактов что 5 , все равно получаю такую погрешность , код прикрепляю ниже
#include <Wire.h >
#include <LiquidCrystal_I2C.h >
#include <avr/io.h>
#include <avr/interrupt.h>
LiquidCrystal_I2C lcd(0x27 ,16,2);
volatile unsigned long T, myTimer, time_old ;
volatile boolean flag = 0 ;
int n = 0;
void setup() {
lcd.init();
lcd.backlight(); // подсветка
lcd.clear();
pinMode(3,INPUT_PULLUP);
attachInterrupt(1 , myinterrupt, RISING );// включаем режим аппаратного прерывания
cli(); // выключения прерываний
TCCR1A = 0 ;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 14;
TCCR1B |= (1 << WGM12); // режим СТС
TCCR1B |= (1 << CS10); // без подделителя
TIMSK1 |= (1 << OCIE1A); // настройка прерывания режима СТС
sei();// включение прерываний
}
void loop() {
if (flag) {
float f = 1000000/T;
lcd.clear();
lcd.setCursor(4,0);
lcd.print(T);
delay(100); // выводы на дисплей нужных значений
cli();
flag = 0;
TCCR1B |= (1 << WGM12);
TCCR1B |= (1 << CS10); // включение прерываний после их отключения в самом прерывании ( чтобы таймер не мешал выполнению loop )
TIMSK1 |= (1 << OCIE1A);
sei();
}
}
void myinterrupt(){
if(!flag){
n++; // счетчик фронта , 1 или 2
}
if (n > 3){
n = 0;
}
}
ISR(TIMER_COMPA_vect){
myTimer++
if ( n == 1){
time_old = myTimer; // время первого фронта
n = 2;
}
else if (n == 3){
T= myTimer - time_old ; // время второго фронта
flag = 1 ;
n = 0;
TCCR1B = 0;
}
}
Вы забываете что аппаратные прерывания обрабатываются функциями,вызов которых занимает достаточно много времени.
Пока обрабатывается myinterrupt(),уже наступает прерывание по сравнению ISR(TIMER_COMPA_vect).
Сами флаги прерываний,и,если соответствующим образом настроены выходы OCRx, наступают с точностью до такта.
Вот как раз,видимо, обработка прерываний в функциях именно столько и занимает.
Варианты:
Переработать архитектуру
Взять МК помощней(например stm32)(хотя спорно,т.к. там тоже есть нюансы)
Изменить концепцию с МК на “железную” логику или ПЛИС.
Точность таймера , предполагается за 16 тактов проходит 1 мкс, но на самом деле прерывание срабатывает не в 1 мкс а в 5 мкс , хочу узнать можно ли сделать счетчик времени с такой точности и как
ТС, Дорогой, если тебе нужно измерить величину периода сигнала, то есть время между двумя фронтами, то нужно просто разместить заказ в “Ищу исполнителя”. Как раз недавно такое писал, поэтому за пару тысяч рублей “отдам в хорошие руки”.
Точность порядка микросекунды. Если писать очень аккуратно и входить в прерывание одинаково всегда - то точность два такта- вполне достижима. То есть задержка при входе в прерывание - порядка 50 тактов, но она одинаковая, значит можно считать только разницу, понимаешь?
И да, писать так как ты написал - не стоит. Зачем тебе КомпА вектор? Для каких целей? Чтобы время считать не мучь таймер, пусть крутится, только его счетчик забирай по прерыванию от входа и считай разницу.
Так надо всё таки выдавать точный сигнал или измерять его?
Если выдавать,то я бы за основу взял ассемблерные вставки файла delay.h в стандартном комплекте в avr-gcc. Там точные циклы здержки релизованы.
Владдракула правильно расписал задачу ,
На вход 3 приходит сигнал определенной частоты , нужно измерять период этого сигнала по 1 волне , с точностью до 1 мкс
А таймер нужен чтобы отчитывать время фронтов этого сигнала , надеюсь правильно расписал
На PIC-контроллерах полно схем частотомеров до 50МГц…1ГГц.
Честно говоря никогда не задумывался как это там реализовано - или микроконтроллеры “заточены” под это дели или алгоритмы какие “хитрые”…
С прерываниями где то 2 мкс, меньше не получится. И то нужно изгаляться с обработчиком.
Без прерываний - 1 мкс на асм вполне реально. Dimax расписывал на старом форуме. Только ограничение на длину измеряемого импульса было.
Только речь о длительности импульса, а не о периоде. С этим ещё повозиться нужно.
А частотомеры в ПИКах работают на высоких частотах за счёт высокоскоростного предделителя таймера, значение которого вычисляется слегка по хитрому.