Перейти к содержанию
    

Частотомер на Atmega8 (CVAVR)

Делаю (пытаюсь сделать) частотомер по методу предложеному =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);
} }

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы учитываете остаток в регистре таймера на момент окончания измерения, но не учитываете начальное значение таймера.

 

Еще одна ошибка у вас - gate сделайте volatile.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вы учитываете остаток в регистре таймера на момент окончания измерения, но не учитываете начальное значение таймера.

а как же

N0=(((unsigned long int)(Perepol_Timer1_real))<<16)+count_T1;

вроде учитываю сount_T1...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У вас ошибка: второе прерывание TOV1 никогда не даст инкремента, поскольку GATE=0. Число N1 естественно будет меньше на 2^16.

 

Далее, счётчик T0 у вас 8-битный, а переменная count_T0 у вас int, ну и добавляете вы ее, как int, а надо только 8 бит. Для вашего компилятора может и пройдёт, но лучше по-честному добавлять 8-битное число.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У вас ошибка: второе прерывание 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 так.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Структура вашей программы в некотором смысле эклектична.

 

1) Вроде бы работаете по прерываниям, но и ждёте флаг прерывания ICF1 в фоне, и явно это будет другое прерывание, поскольку по завершению прерывания флаг ICF1 сбрасывается в самом прерывании. Зачем тогда его ждёте?

 

2) В начале цикла измерения вы разрешаете прерывания по захвату, но не учитываете, что физически захват как молотил со скоростью входной частоты, так и молотит. Следовательно, после разрешения прерывания TOIE1=1 надо бы сбросить флаг ICF1, также и в конце измерения.

 

Кстати, каков диапазон частот вы хотите измерять, какой проц и тактовая?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Структура вашей программы в некотором смысле эклектична.

Кстати, каков диапазон частот вы хотите измерять, какой проц и тактовая?

Да, программа такова, ибо сначала я пытался измерять методом ворот, но удачи не достиг :) Вот код моего варианта:

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 мГц.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для вашего случая погрешность измерения приблизительно будет +-0.0002 Гц без учёта нестабильности кварца. Вы не плодите варианты, а сконцентрируйтесь на первом, он вполне работоспособен. Как вы струну возбуждаете?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Как вы струну возбуждаете?

Для этого используется автогенератор. На выходе его 300 мВ 2 -10 кГц прямоугольные импульсы. Но вообще эти старые железки хочется переделать и встроить в свое устройство.

 

Кстати говоря, вы своим вопросом породили во мне другой вопрос: можно ли использовать в Вашем алгоритме компаратор встроенный в мегу8 для захвата и будет ли его достаточно для детектирования столь низкого по амплитуде сигнала?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

можно ли использовать в Вашем алгоритме компаратор встроенный в мегу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 >, возникает ошибка.

Изменено пользователем rezident
Редактирование тэгов цитаты исходника.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

В принципе, думаю можно, хотя оффсет у компаратора достаточно большой, посмотрите на рис. 167-168 док. 2486.

Но офсет ведь не влияет? Мы же начинаем измерение фронтом и заканчиваем, и теоретически, задержка прихода фронта не должна влиять. Естественно если она одна и та же для начала и окончания.

 

Спасибо за пример, единственно, надо будет разобраться с регистрами всяких настроек таймеров, прерываний и т.п. В CVAVR таких удобных обращений нет :)

 

p.s. Правильны ли эти дефайны:

#define TOIE0 0x01
#define TOIE1 0x04
#define ICF1 0x20

Судя по всему нет, ибо МК перезагружается на первой же строчке:

TIMSK=(1<<TOIE1)|(1<<TOIE0);

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

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. При первом вводе сообщения такой замены не происходит. Похоже это баг системы, пожалуйста, разберитесь и по возможности исправьте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

#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:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

1) Для начала неплохо. Каков был номинал входной частоты?

 

2) Поставьте putchar('b'); до сброса флага захвата TIFR=(1<<ICF1); Вы должны понимать, что сбрасываете предыдущее состояние, которое возникло неизвестно когда, и ожидаете свежего захвата, после которого немедленно запоминаете свежие значения TCNT0 и ICR1, пока они не поменялись снова.

 

3) Из тех же соображений уберите вывод putchar('c'); сразу после захвата, это достаточно длительная функция.

 

4) Неплохо бы для отладки выводить в цикле не только частоту, но и значения N1, N2, M1, M2.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Входная частота 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;
} }

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...