|
Частотомер на Atmega8 (CVAVR) |
|
|
|
Jun 9 2010, 17:23
|
Местный
  
Группа: Свой
Сообщений: 300
Регистрация: 15-03-06
Из: Москва
Пользователь №: 15 284

|
Делаю (пытаюсь сделать) частотомер по методу предложеному =GM= тут: http://electronix.ru/forum/index.php?showtopic=29796. Но вот что то не получается. Верней получается но не совсем. Во первых если я меняю задержку между началом и концом измерения то получаю существенно разные варианты. Но в то же время, если задержка ровно 1 сек (delay_ms(1000)  то результат выводится либо равный расчетному либо чуть больше. Причем как будто бы не хватает одного переполнения таймера 1 т.е. Perepol_Timer1++; и число N1 получается на 65536 меньше. Из за чего результат чуть больше. Но куда оно может пропасть? код вообще то взят в основном отсюда http://pro-radio.ru/controllers/5978/(с комментариями) но там не работает регистрация поэтому спрашиваю тут. Код char gate; static float Fx; unsigned long int N, N0, M, M0, N1, M1; unsigned int Perepol_Timer0=0, Perepol_Timer1=0, count_T1, count_T0,Perepol_Timer1_real;
//Прерывание по переполнению Timer/Counter 0 interrupt [TIM0_OVF] void timer0_ovf_isr(void){ Perepol_Timer0++;//Увеличение переменной на 1 }
//Прерывание по переполнению Timer/Counter 1 interrupt [TIM1_OVF] void timer1_ovf_isr(void){ if (gate){ Perepol_Timer1++;//Увеличение переменной на 1 } }
//Прерывание по захвату Timer/Counter 1 interrupt [TIM1_CAPT] void timer1_capt_isr(void){ count_T1=ICR1;//Значение регистра ICR1 переписывается в переменную count_T0=TCNT0;//Значение регистра TCNT0 переписывается в переменную TIMSK&=0xDF;//Запрет прерывания по захвату if (TIFR&0b00000100==1){ Perepol_Timer1++; TIFR&=0b00000100; } }
while (1){//Бесконечный цикл #asm("cli") gate=0; Perepol_Timer1=0;//Обнуление переменной Perepol_Timer0=0;//Обнуление переменной #asm("sei")//Разрешения прерываний TIMSK|=0x20;//Разрешили захват gate=1; while ((TIFR&0x20)==0x20){}//Ожидание прерывания по захвату Perepol_Timer1_real = Perepol_Timer1; N0=(((unsigned long int)(Perepol_Timer1_real))<<16)+count_T1; //Расчет общего количества тиков системной частоты M0=(((unsigned long int)(Perepol_Timer0))<<8)+count_T0;//Расчет общего количества тиков входной частоты //sprintf(lcd_buffer, "PT1=%u;CT1=%u;PT0=%u;CT0=%u;\r", Perepol_Timer1_real, count_T1, Perepol_Timer0, count_T0); //puts(lcd_buffer); delay_ms(1000);//Задержка на 1 с TIMSK|=0x20;//Разрешили захват gate=0; while ((TIFR&0x20)==0x20){}//Ожидание прерывания по захвату Perepol_Timer1_real = Perepol_Timer1; N1=(((unsigned long int)(Perepol_Timer1_real))<<16)+count_T1; //Расчет общего количества тиков системной частоты M1=(((unsigned long int)(Perepol_Timer0))<<8)+count_T0;//Расчет общего количества тиков входной частоты sprintf(lcd_buffer, "PT1=%u;CT1=%u;PT0=%u;CT0=%u;\r", Perepol_Timer1_real, count_T1, Perepol_Timer0, count_T0); puts(lcd_buffer); N=(N1-N0);//Расчет количества тиков системной частоты за время измерения M=(M1-M0);//Расчет количества тиков входной частоты за время измерения
Fx=12000000.0*(float)M/(float)N;//Вычисление частоты входного сигнала putchar('c'); sprintf(lcd_buffer, "F=%0.6fHz", Fx); lcd_clear(); lcd_puts(lcd_buffer); puts(lcd_buffer); putchar(13); } }
|
|
|
|
|
 |
Ответов
|
Jun 15 2010, 09:38
|
Местный
  
Группа: Свой
Сообщений: 300
Регистрация: 15-03-06
Из: Москва
Пользователь №: 15 284

|
CODE #include <mega8.h> //Подключение #include <stdio.h> // внешнх #include <stdlib.h> #include <delay.h> // библиотек #include <16x2.h>//
#define TOIE0 0 #define TOIE1 2 #define ICF1 5
//Объвление переменных static float volatile Fx; unsigned long volatile N,N1,N2,M,M1,M2; unsigned int volatile mtick1,mtick2,mover=0; unsigned int volatile ntick1,ntick2,nover=0;
//Прерывание по переполнению Timer/Counter 0 interrupt [TIM0_OVF] void timer0_ovf_isr(void){ mover++; }
//Прерывание по переполнению Timer/Counter 1 interrupt [TIM1_OVF] void timer1_ovf_isr(void){ nover++; }
//Тело основной программы void main(void){
unsigned char lcd_buffer[46];//Обявление локальной строковой переменной
PORTC=0x00; DDRC=0xFF;
//Инициализация Timer/Counter 0 TCCR0=0x07;
//Инициализация Timer/Counter 1
TCCR1B=0x01;
UCSRA=0x00; UCSRB=0x08; UCSRC=0x86; UBRRH=0x00; UBRRL=0x4D; putsf("reset\r"); lcd_init();//Инициализация LCD HD44780
#asm("sei")
TIMSK=(1<<TOIE1)|(1<<TOIE0); //разрешим TOV1 и TOV0 putchar('a');
while (1){//Бесконечный цикл
TIFR=(1<<ICF1); //сбросим флаг захвата putchar('b'); while((TIFR&0x20)==0x20); //ждём начала измерения putchar('c'); ntick1=ICR1; //запомним ICR1 и TCNT0 mtick1=TCNT0; //в начале измерения ntick2=nover; mtick2=mover&0x00FF; N1=((long)(ntick2)<<16)+(long) ntick1; //системные тики M1=((long)(mtick2)<<8) +(long) mtick1; //входные тики putchar('d'); delay_ms(1000); //задержка на 1 с TIFR=(1<<ICF1); //сбросим флаг захвата while((TIFR&0x20)==0x20); //ждём конца измерения ntick1=ICR1; //запомним ICR1 и TCNT0 mtick1=TCNT0; //в конце измерения ntick2=nover; mtick2=mover&0x00FF; N2=((long)(ntick2)<<16)+(long) ntick1; //системные тики M2=((long)(mtick2)<<8) +(long) mtick1; //входные тики N=N2-N1; //системные тики за время измерения M=M2-M1; //входные тики за время измерения Fx=12000000.0*(float)M/(float)N; //вычисление частоты входного сигнала putchar('c'); sprintf(lcd_buffer, "F=%0.6fHz", Fx); lcd_clear(); lcd_puts(lcd_buffer); puts(lcd_buffer); putchar(13); } } Это код который я гружу в контроллер. CODE bcdcF=1016.036315Hz
bcdcF=1017.031433Hz
bcdcF=1016.036315Hz
bcdcF=1021.588439Hz
bcdcF=1021.588439Hz
bcdcF=1021.588439Hz
bcdcF=1021.588439Hz
bcdcF=1016.036315Hz
bcdcF=1017.031433Hz
bcdcF=1016.036315Hz
bcdcF=1021.588439Hz
bcdcF=1021.588439Hz
bcdcF=1021.588439Hz
bcdcF=1021.588439Hz
bcdcF=1016.036315Hz
bcdcF=1017.031433Hz
bcdcF=1016.036315Hz
bcdcF=1016.036315Hz
bcdcF=1021.588439Hz
bcdcF=1021.588439Hz
bcdcF=1021.588439Hz
bcdcF=1016.036315Hz
bcdcF=1017.031433Hz
bcdcF=1016.036315Hz
bcdcF=1016.036315Hz
bcdcF=1021.588439Hz
bcdcF=1022.588989Hz
bcdcF=1021.588439Hz
bcdcF=1016.036315Hz
bcdcF=1016.036315Hz
bcdcF=1016.036315Hz
bcdcF=1016.036315Hz
А это то что на выходе в терминале.
|
|
|
|
|
Jun 15 2010, 10:34
|

Ambidexter
    
Группа: Свой
Сообщений: 1 589
Регистрация: 22-06-06
Из: Oxford, UK
Пользователь №: 18 282

|
1) Для начала неплохо. Каков был номинал входной частоты?
2) Поставьте putchar('b'); до сброса флага захвата TIFR=(1<<ICF1); Вы должны понимать, что сбрасываете предыдущее состояние, которое возникло неизвестно когда, и ожидаете свежего захвата, после которого немедленно запоминаете свежие значения TCNT0 и ICR1, пока они не поменялись снова.
3) Из тех же соображений уберите вывод putchar('c'); сразу после захвата, это достаточно длительная функция.
4) Неплохо бы для отладки выводить в цикле не только частоту, но и значения N1, N2, M1, M2.
--------------------
Делай сразу хорошо, плохо само получится
|
|
|
|
|
Jun 15 2010, 11:36
|
Местный
  
Группа: Свой
Сообщений: 300
Регистрация: 15-03-06
Из: Москва
Пользователь №: 15 284

|
Входная частота 1019.02173 Гц. Расчетная. По осцилографу тоже очень похоже (С117 с метками). CODE reset N1=0 M1=97 N2=0 M2=1130 cF=1016.924499Hz
N1=0 M1=1168 N2=0 M2=2204 cF=1014.423889Hz
N1=0 M1=2242 N2=0 M2=3277 cF=1018.893310Hz
N1=0 M1=3315 N2=0 M2=4350 cF=1018.893310Hz
N1=0 M1=4388 N2=0 M2=5423 cF=1018.893310Hz
N1=0 M1=5461 N2=0 M2=6496 cF=1018.893310Hz
N1=0 M1=6534 N2=0 M2=7569 cF=1018.893310Hz
N1=0 M1=7607 N2=0 M2=8642 cF=1018.893310Hz
N1=0 M1=8680 N2=0 M2=9715 cF=1013.444702Hz
N1=0 M1=9753 N2=0 M2=10788 cF=1018.893310Hz
N1=0 M1=10827 N2=0 M2=11863 cF=1014.423889Hz
N1=0 M1=11902 N2=0 M2=12939 cF=1020.862243Hz
N1=0 M1=12978 N2=0 M2=14014 cF=1019.877746Hz
N1=0 M1=14053 N2=0 M2=15089 cF=1019.877746Hz
N1=0 M1=15128 N2=0 M2=16164 cF=1014.423889Hz
N1=0 M1=16203 N2=0 M2=17240 cF=1020.862243Hz
Такое ощущение, что нужно обнулять nover и mover. Но что то еще не так. Смущает так же, что N1 и N2 = 0. Если обнулять nover и mover то измерения такие: CODE reset N1=0 M1=98 N2=0 M2=1131 F=1016.924499Hz
N1=0 M1=144 N2=0 M2=1178 F=1017.908935Hz
N1=0 M1=191 N2=0 M2=1225 F=1017.908935Hz
N1=0 M1=238 N2=0 M2=1272 F=1017.908935Hz
N1=0 M1=29 N2=0 M2=1062 F=1022.421386Hz
N1=0 M1=75 N2=0 M2=1108 F=1016.924499Hz
N1=0 M1=121 N2=0 M2=1155 F=1017.908935Hz
N1=0 M1=168 N2=0 M2=1202 F=1017.908935Hz
N1=0 M1=215 N2=0 M2=1249 F=1017.908935Hz
N1=0 M1=6 N2=0 M2=1038 F=1021.431579Hz
N1=0 M1=51 N2=0 M2=1084 F=1016.924499Hz
N1=0 M1=97 N2=0 M2=1130 F=1016.924499Hz
N1=0 M1=143 N2=0 M2=1177 F=1023.411132Hz
N1=0 M1=190 N2=0 M2=1224 F=1017.908935Hz
N1=0 M1=237 N2=0 M2=1272 F=1024.400878Hz
N1=0 M1=29 N2=0 M2=1062 F=1016.924499Hz
N1=0 M1=75 N2=0 M2=1108 F=1016.924499Hz
N1=0 M1=121 N2=0 M2=1155 F=1017.908935Hz
N1=0 M1=168 N2=0 M2=1202 F=1017.908935Hz
N1=0 M1=215 N2=0 M2=1249 F=1017.908935Hz
N1=0 M1=6 N2=0 M2=1038 F=1015.940002Hz
N1=0 M1=51 N2=0 M2=1084 F=1016.924499Hz
N1=0 M1=97 N2=0 M2=1130 F=1022.421386Hz
N1=0 M1=143 N2=0 M2=1177 F=1017.908935Hz
N1=0 M1=190 N2=0 M2=1224 F=1017.908935Hz
А вот и сам код: CODE while (1){//Бесконечный цикл
TIFR=(1<<ICF1); //сбросим флаг захвата while((TIFR&0x20)==0x20); //ждём начала измерения ntick1=ICR1; //запомним ICR1 и TCNT0 mtick1=TCNT0; //в начале измерения ntick2=nover; mtick2=mover&0x00FF; N1=((long)(ntick2)<<16)+(long) ntick1; //системные тики M1=((long)(mtick2)<<8) +(long) mtick1; //входные тики sprintf(lcd_buffer, "N1=%i M1=%i\r", N1,M1); puts(lcd_buffer); delay_ms(1000); //задержка на 1 с TIFR=(1<<ICF1); //сбросим флаг захвата while((TIFR&0x20)==0x20); //ждём конца измерения ntick1=ICR1; //запомним ICR1 и TCNT0 mtick1=TCNT0; //в конце измерения ntick2=nover; mtick2=mover&0x00FF; N2=((long)(ntick2)<<16)+(long) ntick1; //системные тики M2=((long)(mtick2)<<8) +(long) mtick1; //входные тики sprintf(lcd_buffer, "N2=%i M2=%i\r", N2,M2); puts(lcd_buffer); N=N2-N1; //системные тики за время измерения M=M2-M1; //входные тики за время измерения Fx=12000000.0*(float)M/(float)N; //вычисление частоты входного сигнала
sprintf(lcd_buffer, "F=%0.6fHz", Fx); lcd_clear(); lcd_puts(lcd_buffer); puts(lcd_buffer); putchar(13); nover=0; mover=0; } }
|
|
|
|
Сообщений в этой теме
ps1x Частотомер на Atmega8 (CVAVR) Jun 9 2010, 17:23 Сергей Борщ Вы учитываете остаток в регистре таймера на момент... Jun 10 2010, 06:02 ps1x Цитата(Сергей Борщ @ Jun 10 2010, 10:02) ... Jun 10 2010, 09:01 =GM= У вас ошибка: второе прерывание TOV1 никогда не да... Jun 10 2010, 21:36 ps1x Цитата(=GM= @ Jun 11 2010, 01:36) У вас о... Jun 11 2010, 08:54  =GM= Структура вашей программы в некотором смысле эклек... Jun 11 2010, 21:28   ps1x Цитата(=GM= @ Jun 12 2010, 01:28) Структу... Jun 12 2010, 11:43    =GM= Для вашего случая погрешность измерения приблизите... Jun 12 2010, 12:51     ps1x Цитата(=GM= @ Jun 12 2010, 16:51) Как вы ... Jun 12 2010, 21:51      =GM= Цитата(ps1x @ Jun 12 2010, 20:51) можно л... Jun 13 2010, 22:22       ps1x Цитата(=GM= @ Jun 14 2010, 02:22) В принц... Jun 14 2010, 18:46        =GM= 1) Оффсет влияет на начало фронта, многое зависит ... Jun 15 2010, 09:11   =GM= Разница М2-М1 всё время где-то 1033-1034, это прие... Jun 15 2010, 12:03 ps1x Кодreset
aN1=65536 M1=98 ntick1=0 ntick2=1
N2=125... Jun 15 2010, 12:50 =GM= Теперь мне не нравится, что ntick1 всё время равен... Jun 15 2010, 14:05  ps1x Цитата(=GM= @ Jun 15 2010, 18:05) Признав... Jun 15 2010, 14:58   =GM= Цитата(ps1x @ Jun 15 2010, 13:58) Входной... Jun 15 2010, 15:35 ps1x А DDR соответствующих ножек влияет? Подтяжка? Сейч... Jun 15 2010, 16:02 =GM= Да, надо соединить Т0 и ICP с генератором меандра.... Jun 15 2010, 16:23 ps1x Появилась стабильность Значения 1018.8184 - 1018.... Jun 15 2010, 19:22 =GM= Ну, я рад за вас. Выбросы происходят из-за того са... Jun 15 2010, 19:36 ps1x Автогенератор в институте, и схемы от него нет, да... Jun 15 2010, 20:21 =GM= Цитата(ps1x @ Jun 15 2010, 19:21) Может б... Jun 16 2010, 10:10  ps1x Цитата(=GM= @ Jun 16 2010, 14:10) 4) Пров... Jun 16 2010, 13:31   =GM= Не понял, по-подробнее можно? Jun 16 2010, 14:33    ps1x Ваш пост из того топика. Jun 16 2010, 14:51     =GM= Ну что, ps1x, есть подвижки? В принципе, я нашёл р... Jun 21 2010, 15:31      ps1x Цитата(=GM= @ Jun 21 2010, 19:31) Ну что,... Jun 23 2010, 18:37       =GM= Попробуйте следующий код, для ваших целей должен п... Jun 24 2010, 21:56        ps1x Работает прекрасно +/- 0.0001 мкС
Большущее спаси... Jun 25 2010, 10:27         =GM= На здоровье.
Но 0,0001 мкс - это 0,1 нс, вы не ош... Jun 25 2010, 11:19          demiurg_spb Цитата(=GM= @ Jun 25 2010, 15:19) На здор... Jun 25 2010, 12:00           =GM= Цитата(demiurg_spb @ Jun 25 2010, 11:00) ... Jun 25 2010, 13:06            demiurg_spb Цитата(=GM= @ Jun 25 2010, 17:06) Я уж ис... Jun 27 2010, 19:19             =GM= 1) В чём конкретно вы видите лёгкое неудобство от ... Jun 28 2010, 11:34              demiurg_spb Цитата(=GM= @ Jun 28 2010, 15:34) 1) В чё... Jun 28 2010, 17:34               =GM= Цитата(demiurg_spb @ Jun 28 2010, 16:34) ... Jun 28 2010, 21:56          ps1x Цитата(=GM= @ Jun 25 2010, 15:19) Но 0,00... Jun 26 2010, 09:13 ps1x Пожалуй, подниму тему из глубин форума. Встала зад... Nov 3 2010, 11:50 akl В mega8 есть аналоговый компаратор, имеющий доступ... Nov 3 2010, 16:19 ps1x Цитата(akl @ Nov 3 2010, 20:19) В mega8 е... Nov 3 2010, 18:15 akl Цитата(ps1x @ Nov 3 2010, 15:50) Судя по ... Nov 3 2010, 18:39 =GM= Если измерять частоты надо одновременно, то вот ва... Nov 3 2010, 20:40 ps1x Но ведь вроде T0 и T1 асинхронные, и считают незав... Nov 3 2010, 20:50 =GM= Ну, вот вам ещё вариант: берёте МК с тремя таймера... Nov 3 2010, 22:55 horoc =GM= Заинтересовался Вашим способом, давно хотел с... Nov 7 2010, 13:54 =GM= Ну, трудно обьяснить, попробую. Цикл do ... whil... Nov 7 2010, 18:52 horoc Я поэкспериментировал немного, сделал вот так.
К... Nov 7 2010, 19:16 horoc Вот еще на танцевал с бубном
=GM= благодарю... Nov 7 2010, 21:06 Pikt Приветствую. Я плохо разбираюсь пока что в микроко... Jun 19 2011, 11:32 =GM= Пойдёт.
Выходной сигнал - двоичное число в операт... Jun 20 2011, 13:05
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|