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

shkal

Свой
  • Постов

    279
  • Зарегистрирован

  • Посещение

Сообщения, опубликованные shkal


  1. Имеем вычисление по простейшей формуле F=A*B/C.

    A, B, C имеют тип long int, F - long double.

    Строка F=(((long double)(А))*B )/С; при А=65535, В=2500000, С=5000002 даёт результат, совпадающий с виндовым калькулятором только до 9 знака.

    Где я теряю точность?

    Компилятор Микрочип С30, мк PIC24H.

  2. Ну вот вы и не демонстрируйте :)

    У меня еще в 1993 году была бумажная дока на МКЭ 332-333 и там цифры были примерно такие, как я и написал.

    Видимо, ребята тоже забыли поставить черточки, а вашей "консультации" так и не получили. :)

     

    Вопрос по чуйствительности закрыт.

     

    Да не закрыт. Даташит покажите хоть один.

     

    МКЭ-333

    МКЭ 332

     

    А чем красный не угодил? Падением напряжения на нём?

     

    Да, нужно полпитания

  3. Это у вас однобокая информация. Есть и 60 мВ/Па и 600 мВ/Па и 1200 мВ/Па.

     

    http://www.radiomaster.net/load/07-7/index.html

     

    Автор не указал тип. Поэтому возникли замечания. Можно и добавить усиления, но Ку не более 20.

     

    Не стоит так откровенно демонстрировать своё ламерство. В табличке, на которую вы ссылаетесь, люди забыли чёрточки между цифрами поставить :) :)

     

    тыц

     

    Andrey_1 , кстати, в измерительных микрофонах по $100 типа Behringer ECM8000 или Nady CM 100 как раз и стоят капсули panasonic WM-61 за $2

     

     

  4. Электретные микрофоны имеют чувствительность примерно 1000 мВ/Па.

    http://www.chipdip.ru/video.aspx?vid=ID000275528

     

    Это ошибка примерно в 20 раз. Обычно 50-60 мв/Па

    микрофоны

    Соответственно и уровень на выходе - единицы-десятки милливольт. Поэтому и повторитель после него никому не нужен, нужен усилитель.

  5. Так тоже нельзя ;)

    Вот так можно. Стабилитрон на 2.5 В

     

    Вы хотя-бы первую главу про ОУ из "Искусства схемотехники" прочитайте, нельзя так, право же.

    post-37149-1312366182_thumb.png

  6. 1) первый ОУ так нельзя включать.

    2) При закорачивании входа его Ку стремиться к бесконечности, что вы и наблюдаете.

    3) TL072 - не подходит для микрофонного преда, поскольку довольно шумное. Из недорогих - возьмите RC4580

    4) Питание от USB очень грязное.

    5) 7805 от 5В входа работать не будет.

  7. Добрый день всем. Существуют ли дсп с параллельными интерфейсами, позволяющими напрямую подключить ацп 14 бит 170-250 msps? Какова потоковая скорость передачи интерфейс-память для ддр? Прикидочно общая задача - оцифровка 4М отсчётов, запись в память, обработка не в реальном времени, выдача результатов на DVI

     

  8. Если я правильно понял, у вас захват двух последовательных фронтов входного сигнала, т.е. измеряется время одного периода. В этом случае нужна информация о приблизительной входной частоте, иначе как определить нужный коэфициент деления? В алгоритме , описанном GM, изменение коэфициента деления происходит как-бы автоматически при изменении входной частоты таким образом, чтобы время измерения оставалось постоянным. Кроме того, этот алгоритм не имеет нижней граничной частоты - он просто ждет второго фронта, если он не появился за время гейта. Еще вот какой вопрос-очищается ли у ПИК24 ФИФО захвата при выключении модуля захвата?

  9. Отказался в итоге от захвата таймера, считающего входную частоту. Захватываю только таймер, считающий опору, а в прерывании от IC1 просто читаю входной таймер первой командой. При высокой входной частоте этот таймер, конечно, успевает сосчитать несколько фронтов за время входа в прерывание, но, поскольку это время однинаково в начале и конце цикла измерения, то ошибка не возникает. Ессно, при такой схеме требуется , что приоритет прерывания IC1 был наивысшим.

    Там есть один тонкий момент, связаный с возможностью совпадения прерывания от IC1 и прерывания от переполнения таймеров, но это вроде решаемо, тут где-то была ветка на эту тему.

  10. Так изучай-не изучай, повлиять на работу ея я всё равно не могу, отключить - тоже. С таймером всё более-менее понятно и оговорено в даташите - время от входного фронта до изменения состояния 0.75-1.75 цикла.

    0-1 цикл - задержка синхронизации, то есть обычный Д-триггер, 0.75 цикла - сам таймер. А вот с input capture тайминги не оговариваюся. есть старый аппнот 96 года по семейству pic17, appnote где на стр.8 нарисованы тайминги работы, так как я их себе представлял (но не так, как на самом деле в pic24)

  11. Написал простейшую тестовую программу (инициализацию опускаю). IC1 захватывает TMR3.

     

    
    int main()
    {
    while (1) {};
    }
    
    void __attribute__((__interrupt__)) _IC1Interrupt(void)
    {
    unsigned int a,b;
    
    
    b=TMR3;
    a=IC1BUF;
    if (a==b ) 
    {
    	ok1++;
    }
    else
    {
    	error1++;
    }
    counter++;
    IFS0bits.IC1IF=0; //reset interrupt flag
    }

     

     

    независимо от входной частоты этот код дает 75% счётчика ок и 25% счётчика error от общего числа циклов. Я в ах.... прострации :wacko:

  12. При любых. Даже очень низких, хоть 1 Гц.

    Тут, похоже, дело не в алгоритме. У меня есть такое впечатление, что, когда один и тот же фронт приходит и на IC1, и на таймер, который она захватывает, то

    иногда сначала срабатывает таймер, а потом IC, а иногда наоборот, и зависит это от фазы входного фронта по отношению к фронту тактовой.

  13. Зачем опорную частоту надо заводить на пин и считать, когда от нее можно просто затактировать сам процессор?

    Измеряемую частоту заведите на счетчик, и одно прерывание по Т1 - истечение периода усреднения.

     

    Опора на внешний пин не заводится, Т3 считает внутренний клок.

    Вы ссылку на алгоритм посмотрели, которую я дал? Там извращенность подхода тщательно обсуждается.

  14. Добрый день всем. Я попал в некоторый затык и не могу выбраться из него без посторонней помощи.

    Итак, пишется реализация частотомера по алгоритму, приведённому здесь

    Входные импульсы считаются таймером Т2, опорные - Т3. Входы IC1 IC2 T2CK - физически один пин, мэппинг с помощью PPS. IC1 захватывает Т2, IC2 захватывает T3.

    Функция F_init() инициализирует переферию.

    Функция F_start() запускает цикл измерения частоты.

    По первому прерывнию от IC1 сохраняются пары значений F_osc_start, F_in_start и счётчики переполнения таймеров over2_start, over3_start.

    Далее модули IC1 IC2 выключаются и запускается на время gate_time таймер Т5. По его прерыванию модули IC1 IC2 опять включаются, и после очередного фронта входного сигнала в прерывании IC1

    сохраняются пары значений F_osc_end, F_in_end и счётчиков переполнения таймеров over2_end, over3_end. Устанавливается флаг new_data.

    В main'е крутиться простейшая state machine, после установки флага new_data значение частот вычисляется функцией F_calc() и отображается на ЛСД.

     

    main() {
    
    F_init();
    while(1)
    {
    
    
    switch (main_state)
    	{
    	case 0: 
    
    			F_start(200);	
    			main_state=1;
    			break;
    
    	case 1: 	
    
    			if (new_data)
    			{
    				Freq=F_calc();
    				LCDWriteCmd(0x01); // clear display
    				delay_ms(2);
    				if (Freq == 0)
    					{
    						LCDputstr ("NO SIGNAL");
    					}				
    				else 
    					{
    						sprintf(F_display, "%15f", Freq);
    						LCDputstr(F_display);
    
    					}
    				new_data=0;
    				main_state=0; 
    			}
    
    			break;
    
    	}
    }

     

     

    void F_init(void)
    {
    // init timer2 for external clock
    
    T2CONbits.TON = 0; // Disable Timer
    T2CONbits.TCS = 1; // Select external clock
    T2CONbits.TGATE = 0; // Disable Gated Timer mode
    T2CONbits.TCKPS = 0b00; // 1:1 prescaler
    T2CONbits.T32 = 0; // 16bit mode
    TMR2 = 0x00; // Clear timer register
    PR2=0xffff;
    IPC1bits.T2IP = 6; // INT priority=6
    IFS0bits.T2IF = 0; // Clear Timer1 Interrupt Flag
    IEC0bits.T2IE = 1; // Enable Timer1 interrupt
    
    
    // init timer 3
    
    T3CONbits.TON = 0; // Disable Timer
    T3CONbits.TCS = 0; // Select internal clock
    T3CONbits.TCKPS = 0b00; // 1:1 prescaler
    T3CONbits.TGATE = 0; // Disable Gated Timer mode
    TMR3 = 0x00; // Clear timer register
    PR3=0xffff;
    IPC2bits.T3IP = 6; //INT priorty=6
    IFS0bits.T3IF = 0; // Clear Timer1 Interrupt Flag
    IEC0bits.T3IE = 1; // Enable Timer1 interrupt	
    
    
    // init timer 5 for 0.2c 
    
    T5CONbits.TON = 0; // Disable Timer
    T5CONbits.TCS = 0; // Select internal clock
    T5CONbits.TCKPS = 0b11; // 1:256 prescaler
    T5CONbits.TGATE = 0; // Disable Gated Timer mode
    TMR5 = 0x00; // Clear timer register
    PR5=2879;
    IPC7bits.T5IP = 4; //INT priorty=4
    IFS1bits.T5IF = 0; // Clear Timer1 Interrupt Flag
    IEC1bits.T5IE = 1; // Enable Timer1 interrupt	
    
    
    // init input capture 1 on Timer 2
    
    IC1CONbits.ICM= 0b000; // Disable Input Capture 1 module
    IC1CONbits.ICTMR= 1; // Select Timer2 as the IC2 Time base
    IC1CONbits.ICI= 0b00; // Interrupt on every capture event
    IPC0bits.IC1IP = 6; // Setup IC1 interrupt priority level
    IFS0bits.IC1IF = 0; // Clear IC1 Interrupt Status Flag
    IEC0bits.IC1IE = 1; // Enable IC1 interrupt
    
    
    // init input capture 1 on Timer 3
    
    IC2CONbits.ICM= 0b000; // Disable Input Capture 2 module
    IC2CONbits.ICTMR= 0; // Select Timer3 as the IC2 Time base
    IC2CONbits.ICI= 0b00; // Interrupt on every capture event - INT from IC2 DISABLED!!!
    //	IPC0bits.IC1IP = 6; // Setup IC1 interrupt priority level
    //	IFS0bits.IC1IF = 0; // Clear IC1 Interrupt Status Flag
    //	IEC0bits.IC1IE = 1; // Enable IC1 interrupt
    
    gate_flag=0;
    
    
    
    
    }
    
    
    void F_start (unsigned int gate_time)
    
    {
    unsigned int scale;
    
    
    
    T5CONbits.TON = 0;
    scale = gate_time*(3125/(TOSC*8)) ;
    TMR5 = 0x00; 			// Clear timer register
    PR5=scale;
    new_data=0;
    T2_over=0;				//Clear TMR2 overflow
    T3_over=0;				//Clear TMR3 overflow
    TMR2 = 0x00;  			//Clear timer 2
    TMR3 = 0x00;  			//Clear timer 3
    T2CONbits.TON = 1; 		//Start Timer 2
    T3CONbits.TON = 1;		//Start Timer 3
    IC1CONbits.ICM= 0b011; 	// Enable IC1, every rising edge
    IC2CONbits.ICM= 0b011; 	// Enable IC2, every rising edge
    
    }
    
    void __attribute__((__interrupt__)) _T2Interrupt( void )
    {
    	T2_over++ ;
    		IFS0bits.T2IF = 0;				/* reset timer interrupt flag	*/
    }
    
    
    void __attribute__((__interrupt__)) _T3Interrupt( void )
    {
    	T3_over++ ;
    		IFS0bits.T3IF = 0;				/* reset timer interrupt flag	*/
    }
    
    
    void __attribute__((__interrupt__)) _T5Interrupt( void )
    {
    
    	T5CONbits.TON = 0; 
    	IC1CONbits.ICM= 0b011; //Enable IC1 , on every rising edge
    	IC2CONbits.ICM= 0b011; //Enable IC2 , on every rising edge
    	IFS1bits.T5IF = 0;				/* reset timer interrupt flag	*/
    }
    
    // Capture Interrupt Service Routine
    
    void __attribute__((__interrupt__)) _IC1Interrupt(void)
    {
    unsigned int tmp;
    
    
    
    
    if (!gate_flag) 
    {
    	F_osc_start=IC2BUF;
    	IC2CONbits.ICM= 0b000; //Turn OFF IC2
    	F_in_start=IC1BUF;
    	IC1CONbits.ICM= 0b000; //Turn OFF IC1 module
    	over2_start=T2_over;
    	over3_start=T3_over;
    	while (IC1CONbits.ICBNE)
    	{
    		tmp=IC1BUF;
    	}
    	while (IC2CONbits.ICBNE)
    	{
    		tmp=IC2BUF;
    	}	
    	gate_flag=1;
    	T5CONbits.TON = 1; //start timer5
    }
    else
    {
    	F_osc_end=IC2BUF;
    	IC2CONbits.ICM= 0b000; //Turn OFF IC2
    	F_in_end=IC1BUF;
    	IC1CONbits.ICM= 0b000; //Turn OFF IC1 module
    	over2_end=T2_over;
    	over3_end=T3_over;
    	T2CONbits.TON = 0; 		//Stop Timer 2
    	T3CONbits.TON = 0;		//Stop Timer 3
    	while (IC1CONbits.ICBNE)
    	{
    		tmp=IC1BUF;
    	}
    	while (IC2CONbits.ICBNE)
    	{
    		tmp=IC2BUF;
    	}	
    	gate_flag=0;	
    	new_data=1;
    }
    
    IFS0bits.IC1IF=0; //reset interrupt flag
    }
    
    float F_calc(void)
    
    {
    float F;
    float M;	//input pulse count
    float N;	//clock pulse count
    unsigned long A1,A2 ;
    
    
    
    
    A1=((unsigned long)(over2_end-over2_start))<<16;
    A2=((unsigned long)(over3_end-over3_start))<<16;
    M=A1+(F_in_end-F_in_start);
    N=A2+(F_osc_end-F_osc_start);
    if (M == 0) F=0;
    else F=(OSCIL*M)/N;
    return F;
    }

     

     

    Проблема заключается в том, что данный код примерно в 80% циклов выдаёт правильное значение частоты, а в 20% - таймер Т2 пропускает 1 входной импульс, причем это происходит совершенно хаотично, никакой закономерности я уловить не смог.

    Уже довольно долго бьюсь с отладкой, но всё мимо. Будут ли какие-нибудь идеи о причинах такого поведения?

  15. Опору измерять значительно проще, т.к. постоянное напряжение, да и полно ЦАПов со встроенными опорами. Для измерения 10-20КГц с такой точность нужно что-то типа Agilent 34410a

  16. Микроконтроллер с выходом I2S и звуковой ЦАП. Контроллер формирует отсчёты синуса в цифре и отдаёт ЦАПу. Точность напряжения равна точности ЦАПа. 16 бит хватит с большим запасом. Возможно ещё выходной буфер, редкий ЦАП с выходом по напряжению работает на 200 Ом.

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