ps1x 0 9 июня, 2010 Опубликовано 9 июня, 2010 · Жалоба Делаю (пытаюсь сделать) частотомер по методу предложеному =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); } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Сергей Борщ 119 10 июня, 2010 Опубликовано 10 июня, 2010 · Жалоба Вы учитываете остаток в регистре таймера на момент окончания измерения, но не учитываете начальное значение таймера. Еще одна ошибка у вас - gate сделайте volatile. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ps1x 0 10 июня, 2010 Опубликовано 10 июня, 2010 · Жалоба Вы учитываете остаток в регистре таймера на момент окончания измерения, но не учитываете начальное значение таймера. а как же N0=(((unsigned long int)(Perepol_Timer1_real))<<16)+count_T1; вроде учитываю сount_T1... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 10 июня, 2010 Опубликовано 10 июня, 2010 · Жалоба У вас ошибка: второе прерывание TOV1 никогда не даст инкремента, поскольку GATE=0. Число N1 естественно будет меньше на 2^16. Далее, счётчик T0 у вас 8-битный, а переменная count_T0 у вас int, ну и добавляете вы ее, как int, а надо только 8 бит. Для вашего компилятора может и пройдёт, но лучше по-честному добавлять 8-битное число. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ps1x 0 11 июня, 2010 Опубликовано 11 июня, 2010 · Жалоба У вас ошибка: второе прерывание TOV1 никогда не даст инкремента, поскольку GATE=0. Число N1 естественно будет меньше на 2^16. Таким образом пишем gate=0; после while ((TIFR&0x20)==0x20){}? Далее, счётчик T0 у вас 8-битный, а переменная count_T0 у вас int, ну и добавляете вы ее, как int, а надо только 8 бит. Для вашего компилятора может и пройдёт, но лучше по-честному добавлять 8-битное число. а здесь пишем count_T0=(int)TCNT0; с приведением типа. (хотя компилятор сам это делает, не делает а пишет варнинги если написать char*2, например, то он ругнется на переполнение чара.) В общем результат тот же. :( И число N1 то меньше на 65536 то ровно столько сколько надо. От чего это зависит не понимаю. 3 измерения так - 3 так. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 11 июня, 2010 Опубликовано 11 июня, 2010 · Жалоба Структура вашей программы в некотором смысле эклектична. 1) Вроде бы работаете по прерываниям, но и ждёте флаг прерывания ICF1 в фоне, и явно это будет другое прерывание, поскольку по завершению прерывания флаг ICF1 сбрасывается в самом прерывании. Зачем тогда его ждёте? 2) В начале цикла измерения вы разрешаете прерывания по захвату, но не учитываете, что физически захват как молотил со скоростью входной частоты, так и молотит. Следовательно, после разрешения прерывания TOIE1=1 надо бы сбросить флаг ICF1, также и в конце измерения. Кстати, каков диапазон частот вы хотите измерять, какой проц и тактовая? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ps1x 0 12 июня, 2010 Опубликовано 12 июня, 2010 · Жалоба Структура вашей программы в некотором смысле эклектична. Кстати, каков диапазон частот вы хотите измерять, какой проц и тактовая? Да, программа такова, ибо сначала я пытался измерять методом ворот, но удачи не достиг :) Вот код моего варианта: float result; char buff[16], tim, numizm=2, state=0; // Timer 1 overflow interrupt service routine interrupt [TIM1_OVF] void timer1_ovf_isr(void) { tim++; // увеличиваем счетчик переполнений. } // Timer 1 input capture interrupt service routine interrupt [TIM1_CAPT] void timer1_capt_isr(void) { if (state==0){ // первый фронт сигнала tim=0; // обнуляем переменные и таймер TCNT1=0; } state++; // прибавляем счетчик if (state == numizm){ // если счетчик и кол-во измерений равны, то вычисляем частоту result = 12000000 / ((float)tim*65535+ICR1); // вычисляем "частоту" result *= (int)numizm; // и умножаем на кол-во измерений, получая действительную частоту numizm = 255; //выставляем число измерений if (numizm < result){ // если оно меньше полученной частоты то ставим ее равной частоте ( т.о. измерение будет длиться меньше секунды) numizm = result; } sprintf(buff,"F = %0.3f Гц",result); // выводим на экран и в UART puts(buff); putchar(13); lcd_clear(); lcd_puts(buff); state = 0; // Обнуляем состояние } } На мой взгляд совершенно логичный, но не работающий. Потом мне объяснили что таким способом, разрешающая способность будет не велика. Поэтому я решил пойти по пути Вашего метода. Ну и взял 2 варианта кода и их объединил :) Ну а частоты которые мне нужно измерять - 2 кГц -- 10 кГц. Насколько я понимаю, Вашим методом можно достичь очень хорошей точности, что для струнного датчика (линейный размер -> частота) было бы очень неплохо :) МК Atmega8 частота не принципиальна, но вот сейчас под рукой кварц на 12 мГц. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 12 июня, 2010 Опубликовано 12 июня, 2010 · Жалоба Для вашего случая погрешность измерения приблизительно будет +-0.0002 Гц без учёта нестабильности кварца. Вы не плодите варианты, а сконцентрируйтесь на первом, он вполне работоспособен. Как вы струну возбуждаете? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ps1x 0 12 июня, 2010 Опубликовано 12 июня, 2010 · Жалоба Как вы струну возбуждаете? Для этого используется автогенератор. На выходе его 300 мВ 2 -10 кГц прямоугольные импульсы. Но вообще эти старые железки хочется переделать и встроить в свое устройство. Кстати говоря, вы своим вопросом породили во мне другой вопрос: можно ли использовать в Вашем алгоритме компаратор встроенный в мегу8 для захвата и будет ли его достаточно для детектирования столь низкого по амплитуде сигнала? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 13 июня, 2010 Опубликовано 13 июня, 2010 (изменено) · Жалоба можно ли использовать в Вашем алгоритме компаратор встроенный в мегу8 для захвата и будет ли его достаточно для детектирования столь низкого по амплитуде сигнала? В принципе, думаю можно, хотя оффсет у компаратора достаточно большой, посмотрите на рис. 167-168 док. 2486. Думаю, что для ваших целей подойдёт более простой код для измерения частоты, это модификация вашего варианта, я только немного упорядочил и заменил названия "непроизносимых" переменных. Есть правда один нюанс, но об этом позже. Компилятор WinAVR-20100110 static float volatile Fx; uint32_t volatile N,N1,N2,M,M1,M2; uint16_t volatile mtick1,mtick2,mover=0; uint16_t volatile ntick1,ntick2,nover=0; ISR (TIMER0_OVF_vect) //переполнение счётчика0 входных тиков { mover++; //учтём в mover } ISR (TIMER1_OVF_vect) //переполнение таймера1 системных тиков { nover++; //учтём в nover } int main(void) { TIMSK=(1<<TOIE1)|(1<<TOIE0); //разрешим TOV1 и TOV0 asm volatile("sei\n\t"::); //разрешим прерывания while(1) //цикл непрерывного измерения частоты { TIFR=(1<<ICF1); //сбросим флаг захвата while((TIFR&0x20)==0x20); //ждём начала измерения ntick1=ICR1; //запомним ICR1 и TCNT0 mtick1=TCNT0; //в начале измерения ntick2=nover; mtick2=mover&0x00FF; N1=((uint32_t)(ntick2)<<16)+(uint32_t) ntick1; //системные тики M1=((uint32_t)(mtick2)<<8) +(uint32_t) mtick1; //входные тики delay_ms(1000); //задержка на 1 с TIFR=(1<<ICF1); //сбросим флаг захвата while((TIFR&0x20)==0x20); //ждём конца измерения ntick1=ICR1; //запомним ICR1 и TCNT0 mtick1=TCNT0; //в конце измерения ntick2=nover; mtick2=mover&0x00FF; N2=((uint32_t)(ntick2)<<16)+(uint32_t) ntick1; //системные тики M2=((uint32_t)(mtick2)<<8) +(uint32_t) mtick1; //входные тики N=N2-N1; //системные тики за время измерения M=M2-M1; //входные тики за время измерения Fx=12000000.0*(float)M/(float)N; //вычисление частоты входного сигнала // <<здесь должен быть код вывода на индикатор>> } } Обращаю внимание СИСАДМИНА: при редактировании тег [ / codebox ] самопроизвольно меняется на тег < / div >, возникает ошибка. Изменено 14 июня, 2010 пользователем rezident Редактирование тэгов цитаты исходника. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ps1x 0 14 июня, 2010 Опубликовано 14 июня, 2010 · Жалоба В принципе, думаю можно, хотя оффсет у компаратора достаточно большой, посмотрите на рис. 167-168 док. 2486. Но офсет ведь не влияет? Мы же начинаем измерение фронтом и заканчиваем, и теоретически, задержка прихода фронта не должна влиять. Естественно если она одна и та же для начала и окончания. Спасибо за пример, единственно, надо будет разобраться с регистрами всяких настроек таймеров, прерываний и т.п. В CVAVR таких удобных обращений нет :) p.s. Правильны ли эти дефайны: #define TOIE0 0x01 #define TOIE1 0x04 #define ICF1 0x20 Судя по всему нет, ибо МК перезагружается на первой же строчке: TIMSK=(1<<TOIE1)|(1<<TOIE0); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 15 июня, 2010 Опубликовано 15 июня, 2010 · Жалоба 1) Оффсет влияет на начало фронта, многое зависит от ваших требований к изделию, пробуйте, потом расскажете. Если оффсет не изменяется за время измерения, то задержки обоих фронтов будут одинаковые. 2) Дифайны неправильные, надо так #define TOIE0 0 #define TOIE1 2 #define ICF1 5 Но самому делать ничего не надо, всё сделано до нас, определения находятся в одном из io*.h, для атмеги8 в частности в файле WinAVR-20100110\avr\include\avr\iom8.h. Обращаю внимание СИСАДМИНА: при редактировании тег [ / codebox ] самопроизвольно меняется на тег < / div >, возникает ошибка Уважаемый rezident, спасибо за исправление, я тоже вначале так делал, но при этом искажается код программы, кроме того, вы разрушили моё красивое форматирование комментов, мне так не нравится. Обратите внимание, в исправленном вами коде вместо : : ) появилась заставка рожицы :). Это уже не дело, а ведь могут быть искажения и посерьёзнее, особенно там, где присутствуют угловые скобки < или >. Тогда уж не надо было вводить в практику и тег [ code ]. ЕЩЁ РАЗ ОБРАЩАЮ ВНИМАНИЕ: при редактировании сообщения тег [ / codebox ] самопроизвольно меняется на тег < / div >, приходится вручную забивать div и допечатывать codebox. При первом вводе сообщения такой замены не происходит. Похоже это баг системы, пожалуйста, разберитесь и по возможности исправьте. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ps1x 0 15 июня, 2010 Опубликовано 15 июня, 2010 · Жалоба #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); } } Это код который я гружу в контроллер. 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 А это то что на выходе в терминале. :smile3046: Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
=GM= 0 15 июня, 2010 Опубликовано 15 июня, 2010 · Жалоба 1) Для начала неплохо. Каков был номинал входной частоты? 2) Поставьте putchar('b'); до сброса флага захвата TIFR=(1<<ICF1); Вы должны понимать, что сбрасываете предыдущее состояние, которое возникло неизвестно когда, и ожидаете свежего захвата, после которого немедленно запоминаете свежие значения TCNT0 и ICR1, пока они не поменялись снова. 3) Из тех же соображений уберите вывод putchar('c'); сразу после захвата, это достаточно длительная функция. 4) Неплохо бы для отладки выводить в цикле не только частоту, но и значения N1, N2, M1, M2. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ps1x 0 15 июня, 2010 Опубликовано 15 июня, 2010 · Жалоба Входная частота 1019.02173 Гц. Расчетная. По осцилографу тоже очень похоже (С117 с метками). 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 то измерения такие: 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 А вот и сам код: 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; } } Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться