kovigor 6 May 26 Posted May 26 · Report post Три дня искал. Может, кому-то сэкономлю время: https://batchloaf.wordpress.com/2012/11/17/simple-dspic33fj32mc202-example/ Компилируется и работает. Там, правда, для другого МК (у меня dsPIC33FJ128GP706), так что пришлось немного подправить ... Quote Share this post Link to post Share on other sites More sharing options...
kovigor 6 May 26 Posted May 26 · Report post А вот пример с настройкой осциллятора: ( Взят вот отсюда: https://forum.mikroe.com/viewtopic.php?t=25296 ) // Primary Oscillator Mode: Disabled void main{ // Configure Oscillator to operate the device at 40MIPS // Fosc= Fin*M/(N1*N2), Fcy=Fosc/2 // Fosc= 7.37M*43/(2*2)=79.22Mhz for ~40MIPS input clock PLLFBD=41; // M=43 CLKDIVbits.PLLPOST=0; // N1=2 CLKDIVbits.PLLPRE=0; // N2=2 OSCTUN=0; // Tune FRC oscillator, if FRC is used // Disable Watch Dog Timer RCONbits.SWDTEN=0; // Clock switch to incorporate PLL __builtin_write_OSCCONH(0x01); // Initiate Clock Switch to // FRC with PLL (NOSC=0b001) __builtin_write_OSCCONL(0x01); // Start clock switching while (OSCCONbits.COSC != 0b001); // Wait for Clock switch to occur // Wait for PLL to lock while(OSCCONbits.LOCK!=1) {}; } Quote Share this post Link to post Share on other sites More sharing options...
kovigor 6 May 29 Posted May 29 · Report post Вот пример с использованием таймера. Проверил, работает: https://catcatcat.d-lan.dp.ua/obuchenie/izuchaem-pic24-kompilyator-xc16/issleduem-formirovaniya-zaderzhki/ Сам код (вдруг ссылка не откроется): int main(int argc, char** argv) { OSCCON = 0x3301; //Primary Oscillator with PLL; //Clock switching is enabled, system clock source may be modified by clock switching; //Peripheral Pin Select is not locked. Writes to Peripheral Pin Select registers are allowed; //Disable Secondary Oscillator; //????????? oscillator switch to selection specified by the NOSC<2:0> bits; CLKDIV = 0x0000; //FCY divided by 1; //Processor clock and peripheral clock ratio forced to 1:1; //Output divided by 2, i.e. "N2" = 1; //Input divided by 2, i.e. "N1" = 2; PLLFBD = 0x0002; //PLLDIV<8..0> = 2, i.e. "M" multiplier = 4; //7.37 MHz OSCTUN = 0x0000; //Fast RC Oscillator Tuning bits (? ????? ?????? ?? ????????????) /// //--------------------------------------------------------------------------- // ????????? ??????? TMP1 T1CON = 0b1000000000000000; // |||||||||||||||+-- ?????????????? // ||||||||||||||+--- TCS: ???????? ???????? ????????? FOSC/2 // |||||||||||||+---- TSYNC: ????????? ????????????, ??? ??? ???????? ??????? ????????? ????????? // ||||||||||||+----- ?????????????? // ||||||||||++------ TCKPS1:TCKPS0: ????????? ???????????? 00 = 1:1 // |||||||||+-------- TGATE: 0- ????? ????????? ???????????? ???????? ???????? ???????? // |||++++++--------- ?????????????? // ||+--------------- TSIDL: 0- ?????????? ?????? ? ?????? ???????? (???) // |+---------------- ?????????????? // +----------------- TON: 1 -?????? ??????? PR1=0xFFFF; // ?????? ????? // /// // Configure RB15 as digital output TRISB = 0b0111111111111111; // Flash LED on RB15 while (1) { _LATB15 = 1 - _LATB15; // toggle RB15 //???????? ? ?????????????? ??????? TMR1 = 0; while(TMR1 < 6000); //__delay_ms(500); } return 0; } Quote Share this post Link to post Share on other sites More sharing options...
kovigor 6 June 2 Posted June 2 · Report post Методичка какого-то зарубежного ВУЗа, там пример с АЦП и еще много интересного. Правда, пример пришлось немного подправить, а то не компилировался: https://cs-people.bu.edu/rmancuso/courses/cs454_654-sp20/material/labmanual.pdf Quote Share this post Link to post Share on other sites More sharing options...
kovigor 6 June 3 Posted June 3 · Report post А вот - простейший цифровой фильтр скользящего среднего, без всяких оптимизаций. Сам написал (только не смейтесь). Может, кому-то пригодится: /* * Пример простейшего КИХ - фильтра скользящего среднего */ #include <stdio.h> #include <stdlib.h> #include <p33FJ128GP706.h> //Входные отсчеты unsigned int in_samples[4]; //Коэффициенты //static const float coefficients[4] = { 1/4, 1/4, 1/4, 1/4 }; // Internal FRC oscillator w/ PLL (Fcy=23031250Hz,Tcy=43.419ns) //xx = _FOSCSEL(); _FOSCSEL(0x0083); //????????????? ?? ???????? ?????? ? ?????????????? PLL _FOSC(0x0041); //Clock switching is enabled, FSCM is disabled; //Allow multiple reconfigurations; //OSC2 is the clock output and the instruction cycle (FCY) clock is output on OSC2 pin; //XT Crystal Oscillator mode; // Watchdog timer off _FWDT(FWDTEN_OFF); /* * */ // Функция для КИХ фильтрации unsigned int kih_filter(unsigned int input_signal) { unsigned int output_signal = 0; //Добавляем новый отсчет входного сигнала в массив in_samples[3] = in_samples[2]; in_samples[2] = in_samples[1]; in_samples[1] = in_samples[0]; in_samples[0] = input_signal; //Вычисляем выходной отсчет for (int i = 0; i < 4; i++) { output_signal += (in_samples[i] >> 2)/** coefficients[i]*/; } return output_signal; } int main(int argc, char** argv) { OSCCON = 0x3301; //Primary Oscillator with PLL; //Clock switching is enabled, system clock source may be modified by clock switching; //Peripheral Pin Select is not locked. Writes to Peripheral Pin Select registers are allowed; //Disable Secondary Oscillator; //????????? oscillator switch to selection specified by the NOSC<2:0> bits; CLKDIV = 0x0000; //FCY divided by 1; //Processor clock and peripheral clock ratio forced to 1:1; //Output divided by 2, i.e. "N2" = 1; //Input divided by 2, i.e. "N1" = 2; PLLFBD = 0x000e; //PLLDIV<8..0> = 14, i.e. "M" multiplier = 16; //7.37 MHz OSCTUN = 0x0000; //Fast RC Oscillator Tuning bits (? ????? ?????? ?? ????????????) /// //--------------------------------------------------------------------------- // ????????? ??????? TMP1 T1CON = 0b1000000000000000; //TON = 1, // |||||||||||||||+-- ?????????????? // ||||||||||||||+--- TCS: Internal clock (FOSC/2) // |||||||||||||+---- TSYNC: Do not synchronize external clock input // ||||||||||||+----- ?????????????? // ||||||||||++------ TCKPS1:TCKPS0: prescale value 00 = 1:1 // |||||||||+-------- TGATE: 0 -> Gated time accumulation disabled // |||++++++--------- ?????????????? // ||+--------------- TSIDL: 0 -> Continue timer operation in Idle mode // |+---------------- ?????????????? // +----------------- TON: 1 -> Starts the timer PR1=0xFFFF; // ?????? ????? // /// //?????? ??????????? ???????? ? ?????? PLL, Fosc / 2 // Configure RRB14, 15 as digital outputs // Configure RB9 as digital input TRISB = 0x3fff; // Configure RG15 as digital input TRISG = 0xffff; // Configure PORT D as digital outputs TRISD = 0x0000; //The PORTB pins have alternate functions as analog inputs. //You need to configure the ADPCFG register for digital pins (bits set to 1) //as the reset value is all zeros (analog pins). ADPCFG = 0xfdfc; //Using PORTB.9 as analog input pin (ADC input)) //Using PORTB.0, 1 as analog input pins (Vref+, Vref-)) //The code below configures and enables ADC1, AN9 (PIN = PINB.9) to 12 bit, integer, //automatic conversion mode, with no scanning. //disable ADC AD1CON1bits.ADON = 0; // Configure RB9 as digital input TRISB = 0x3fff; AD1PCFGLbits.PCFG9 = 0; //set AD1 AN9 input pin as analog //Configure AD1CON1 AD1CON1bits.AD12B = 1; //set 12b Operation Mode (this bit is UNDOCUMENTED !!!)) AD1CON1bits.FORM = 0; //set integer output AD1CON1bits.SSRC = 0x7; //set automatic conversion //Configure AD1CON2 AD1CON2 = 0; //not using scanning sampling //Configure AD1CON3 AD1CON3bits.ADRC = 0; //internal clock source AD1CON3bits.SAMC = 0x1F; //sample-to-conversion clock = 31Tad AD1CON3bits.ADCS = 0x2; //Tad = 3Tcy (Time cycles) //Leave AD1CON4 at its default value //enable ADC AD1CON1bits.ADON = 1; // Flash LED on RB15 while (1) { //_LATB15 = 1; //LED blinking _LATB14 = 1; // RB14 -> 1 //The code below will sample ADC1 AN9 with the above configuration: AD1CHS0bits.CH0SA = 9; //set ADC to Sample AN9 pin AD1CON1bits.SAMP = 1; //start to sample while(!AD1CON1bits.DONE); //wait for conversion to finish AD1CON1bits.DONE = 0; //MUST HAVE! clear conversion done bit LATD = kih_filter(ADC1BUF0); //Transferring sample to 12-bit R-2R DAC _LATB14 = 0; // RB14 -> 0 //_LATB15 = 0; //LED blinking } return 0; } Quote Share this post Link to post Share on other sites More sharing options...
Obam 46 June 6 Posted June 6 (edited) · Report post А вот - простейший цифровой фильтр скользящего среднего, без всяких оптимизаций. Сам написал (только не смейтесь). Может, кому-то пригодится: Какие уж тут смехи... А теперь то же самое, но без цепочки пересохранений в массиве-буфере (а прикиньте если бы 256 отсчётов) и цикла суммирования ;-) Edited June 6 by Obam Quote Share this post Link to post Share on other sites More sharing options...
kovigor 6 June 6 Posted June 6 · Report post Сейчас ... Вот, сегодня написал (в работе я опирался на SLAA280b от TI, реализация с кольцевым буфером взята оттуда): /* * FIR filter, see SLAA280b from TI */ #include <stdio.h> #include <stdlib.h> #include <p33FJ128GP706.h> //Отсчеты импульсной характеристики, все отсчеты умножены на 128, //чтобы не работать с дробными числами. Это только часть характеристики, вся она выглядит вот так: // {-1, 0, 32, 66, 32, 0, -1} (см. SLAA280b от TI) static const signed int coefficients[4] = {-1, 0, 32, 66}; //????????? ??????? // Internal FRC oscillator w/ PLL (Fcy=23031250Hz,Tcy=43.419ns) //xx = _FOSCSEL(); _FOSCSEL(0x0083); _FOSC(0x0041); //Clock switching is enabled, FSCM is disabled; //Allow multiple reconfigurations; //OSC2 is the clock output and the instruction cycle (FCY) clock is output on OSC2 pin; //XT Crystal Oscillator mode; // Watchdog timer off _FWDT(FWDTEN_OFF); /* * */ //Функция фильтрации unsigned int kih_filter(unsigned int sample) { static int buflp[8]; // Reserve 8 loactions for circular buffering static int offsetlp = 0; long z; unsigned char i; buflp[offsetlp] = sample; z = ((long)coefficients[3] * buflp[(offsetlp - 3) & 0x07]); for (i = 0; i < 3; i++) z += ((long)coefficients[i] * (buflp[(offsetlp - i) & 0x07] + buflp[(offsetlp - 6 + i) & 0x07])); offsetlp = (offsetlp + 1) & 0x07; return z >> 7; // Return filter output} } int main(int argc, char** argv) { OSCCON = 0x3301; //Primary Oscillator with PLL; //Clock switching is enabled, system clock source may be modified by clock switching; //Peripheral Pin Select is not locked. Writes to Peripheral Pin Select registers are allowed; //Disable Secondary Oscillator; //oscillator switch to selection specified by the NOSC<2:0> bits; CLKDIV = 0x0000; //FCY divided by 1; //Processor clock and peripheral clock ratio forced to 1:1; //Output divided by 2, i.e. "N2" = 1; //Input divided by 2, i.e. "N1" = 2; PLLFBD = 0x000e; //PLLDIV<8..0> = 14, i.e. "M" multiplier = 16; //7.37 MHz OSCTUN = 0x0000; //Fast RC Oscillator Tuning bits /// //--------------------------------------------------------------------------- T1CON = 0b1000000000000000; //TON = 1, // |||||||||||||||+-- ?????????????? // ||||||||||||||+--- TCS: Internal clock (FOSC/2) // |||||||||||||+---- TSYNC: Do not synchronize external clock input // ||||||||||||+----- ?????????????? // ||||||||||++------ TCKPS1:TCKPS0: prescale value 00 = 1:1 // |||||||||+-------- TGATE: 0 -> Gated time accumulation disabled // |||++++++--------- ?????????????? // ||+--------------- TSIDL: 0 -> Continue timer operation in Idle mode // |+---------------- ?????????????? // +----------------- TON: 1 -> Starts the timer PR1=0xFFFF; // /// // Configure RRB14, 15 as digital outputs // Configure RB9 as digital input TRISB = 0x3fff; // Configure RG15 as digital input TRISG = 0xffff; // Configure PORT D as digital outputs (but 10, 11 will be tuned as inputs //because of 10 (not 12) - bits ADC) TRISD = 0x0c00; //The PORTB pins have alternate functions as analog inputs. //You need to configure the ADPCFG register for digital pins (bits set to 1) //as the reset value is all zeros (analog pins). ADPCFG = 0xfdfc; //Using PORTB.9 as analog input pin (ADC input)) //Using PORTB.0, 1 as analog input pins (Vref+, Vref-)) //The code below configures and enables ADC1, AN9 (PIN = PINB.9) to 12 bit, integer, //automatic conversion mode, with no scanning. //disable ADC AD1CON1bits.ADON = 0; // Configure RB9 as digital input TRISB = 0x3fff; AD1PCFGLbits.PCFG9 = 0; //set AD1 AN9 input pin as analog //Configure AD1CON1 AD1CON1bits.AD12B = 0; //set 10b Operation Mode (this bit is UNDOCUMENTED !!!)) AD1CON1bits.FORM = 0; //set integer output AD1CON1bits.SSRC = 0x7; //set automatic conversion //Configure AD1CON2 AD1CON2 = 0; //not using scanning sampling //Configure AD1CON3 AD1CON3bits.ADRC = 0; //internal clock source AD1CON3bits.SAMC = 0x1F; //sample-to-conversion clock = 31Tad AD1CON3bits.ADCS = 0x2; //Tad = 3Tcy (Time cycles) //Leave AD1CON4 at its default value //enable ADC AD1CON1bits.ADON = 1; // Flash LED on RB15 while (1) { //_LATB15 = 1; //LED blinking _LATB14 = 1; // RB14 -> 1 //The code below will sample ADC1 AN9 with the above configuration: AD1CHS0bits.CH0SA = 9; //set ADC to Sample AN9 pin AD1CON1bits.SAMP = 1; //start to sample while(!AD1CON1bits.DONE); //wait for conversion to finish AD1CON1bits.DONE = 0; //MUST HAVE! clear conversion done bit LATD = kih_filter(ADC1BUF0); //Transferring filtered sample to 10-bit R-2R DAC _LATB14 = 0; // RB14 -> 0 //_LATB15 = 0; //LED blinking } return 0; } Quote Share this post Link to post Share on other sites More sharing options...
kovigor 6 Tuesday at 11:14 AM Posted Tuesday at 11:14 AM · Report post Заграждающий БИХ - фильтр (на частоту 50 Гц), опять же, пока без оптимизаций. В работе я опирался вот на эту статью от Analog Devices, оттуда же взяты и коэффициенты импульсной характеристики: https://www.analog.com/en/resources/analog-dialogue/articles/ecg-front-end-design-simplified.html /* * Simple IIR 50 Hz notch filter (Fs = 500 Hz) */ #include <stdio.h> #include <stdlib.h> #include <p33FJ128GP706.h> //Входные отсчеты long in_samples[6]; //Выходные отсчеты long out_samples[6]; //Числитель static const long b_coeffs[3] = {4096, -6627, 4096}; //Знаменатель static const long a_coeffs[3] = {4096, -6211, 3598}; long out_signal = 0; // Internal FRC oscillator w/ PLL (Fcy=23031250Hz,Tcy=43.419ns) //xx = _FOSCSEL(); _FOSCSEL(0x0083); //????????????? ?? ???????? ?????? ? ?????????????? PLL _FOSC(0x0041); //Clock switching is enabled, FSCM is disabled; //Allow multiple reconfigurations; //OSC2 is the clock output and the instruction cycle (FCY) clock is output on OSC2 pin; //XT Crystal Oscillator mode; // Watchdog timer off _FWDT(FWDTEN_OFF); /* * */ //БИХ - фильтрация long bih_filter(long input_signal) { unsigned char i; //Смещаем входные отсчеты в буфере, например, текущий отсчет //на место предыдущего, и т.д. in_samples[2] = in_samples[1]; in_samples[1] = in_samples[0]; in_samples[0] = input_signal; out_signal = 0; //Вычисляем новое значение выходного сигнала фильтра for (i = 0; i < 3; i++) { out_signal += (in_samples[i] * b_coeffs[i]); } for (i = 0; i < 2; i++) { out_signal = (out_signal - (out_samples[i+1] * a_coeffs[i+1])); } //Смещаем выходные отсчеты в буфере out_samples[2] = out_samples[1]; //Мы умножали коэффициенты импульсной характеристики на 4096, //и теперь делим только что вычисленный выходной отсчет на 4096 if (out_signal < 0){out_samples[1] = (((out_signal * (-1)) >> 12) * (-1)); return (((out_signal * (-1)) >> 12) * (-1)); } else{out_samples[1] = (out_signal >> 12); return (out_signal >> 12); } } int main(int argc, char** argv) { OSCCON = 0x3301; //Primary Oscillator with PLL; //Clock switching is enabled, system clock source may be modified by clock switching; //Peripheral Pin Select is not locked. Writes to Peripheral Pin Select registers are allowed; //Disable Secondary Oscillator; //????????? oscillator switch to selection specified by the NOSC<2:0> bits; CLKDIV = 0x0000; //FCY divided by 1; //Processor clock and peripheral clock ratio forced to 1:1; //Output divided by 2, i.e. "N2" = 1; //Input divided by 2, i.e. "N1" = 2; PLLFBD = 0x000e; //PLLDIV<8..0> = 14, i.e. "M" multiplier = 16; //7.37 MHz OSCTUN = 0x0000; //Fast RC Oscillator Tuning bits (? ????? ?????? ?? ????????????) /// //--------------------------------------------------------------------------- // ????????? ??????? TMP1 T1CON = 0b1000000000000000; //TON = 1, // |||||||||||||||+-- ?????????????? // ||||||||||||||+--- TCS: Internal clock (FOSC/2) // |||||||||||||+---- TSYNC: Do not synchronize external clock input // ||||||||||||+----- ?????????????? // ||||||||||++------ TCKPS1:TCKPS0: prescale value 00 = 1:1 // |||||||||+-------- TGATE: 0 -> Gated time accumulation disabled // |||++++++--------- ?????????????? // ||+--------------- TSIDL: 0 -> Continue timer operation in Idle mode // |+---------------- ?????????????? // +----------------- TON: 1 -> Starts the timer PR1=0xFFFF; // ?????? ????? // /// //?????? ??????????? ???????? ? ?????? PLL, Fosc / 2 // Configure RRB14, 15 as digital outputs // Configure RB9 as digital input TRISB = 0x3fff; // Configure RG15 as digital input TRISG = 0xffff; // Configure PORT D as digital outputs (but 10, 11 will be tuned as inputs //because of 10 (not 12) - bits ADC) TRISD = 0x0c00; //The PORTB pins have alternate functions as analog inputs. //You need to configure the ADPCFG register for digital pins (bits set to 1) //as the reset value is all zeros (analog pins). ADPCFG = 0xfdfc; //Using PORTB.9 as analog input pin (ADC input)) //Using PORTB.0, 1 as analog input pins (Vref+, Vref-)) //The code below configures and enables ADC1, AN9 (PIN = PINB.9) to 12 bit, integer, //automatic conversion mode, with no scanning. //disable ADC AD1CON1bits.ADON = 0; // Configure RB9 as digital input TRISB = 0x3fff; AD1PCFGLbits.PCFG9 = 0; //set AD1 AN9 input pin as analog //Configure AD1CON1 AD1CON1bits.AD12B = 0; //set 10b Operation Mode (this bit is UNDOCUMENTED !!!)) AD1CON1bits.FORM = 0; //set integer output AD1CON1bits.SSRC = 0x7; //set automatic conversion //Configure AD1CON2 AD1CON2 = 0; //not using scanning sampling //Configure AD1CON3 AD1CON3bits.ADRC = 0; //internal clock source AD1CON3bits.SAMC = 0x1F; //sample-to-conversion clock = 31Tad AD1CON3bits.ADCS = 0x2; //Tad = 3Tcy (Time cycles) //Leave AD1CON4 at its default value //enable ADC AD1CON1bits.ADON = 1; // Flash LED on RB15 while (1) { //_LATB15 = 1; //LED blinking _LATB14 = 1; // RB14 -> 1 //The code below will sample ADC1 AN9 with the above configuration: AD1CHS0bits.CH0SA = 9; //set ADC to Sample AN9 pin AD1CON1bits.SAMP = 1; //start to sample while(!AD1CON1bits.DONE); //wait for conversion to finish AD1CON1bits.DONE = 0; //MUST HAVE! clear conversion done bit LATD = bih_filter(ADC1BUF0); // while(1){}; _LATB14 = 0; // RB14 -> 0 //_LATB15 = 0; //LED blinking } return 0; } Quote Share this post Link to post Share on other sites More sharing options...
kovigor 6 20 hours ago Posted 20 hours ago · Report post Простейшая реализация ДПФ. Частота дискретизации - 1 КГц, 50 точек, ДПФ считается чуть дольше секунды. Т.е., получился несложный спектроанализатор. Экрана нет (не хочется сейчас заниматься его реализаций), поэтому амплитудный спектр значение за значением выводится на экран осциллографа. Чтобы можно было отличить одно значение от другого, каждое значение стробируется переходом из "0" в "1" на линии PORTB.15, а осциллограф засинхронизирован от входа внешней синхронизации, на который подается сигнал с PORTB.14: /* * Simple DFT computing */ #include <stdio.h> #include <stdlib.h> #include <math.h> #include <p33FJ128GP706.h> //DFT coefficients (real parts) float dpf_real [256]; //DFT coefficients (imagine parts)) float dpf_imagine [256]; //Amplitudes array (Amplitude = sqrt(dpf_real^2 + dpf_imagine^2))) float amplitudes [256]; //Input samples array unsigned int in_samples[256]; //How many samples and sampling frequency unsigned int how_many_samples, freq_diskr; unsigned int i; unsigned long j; // Internal FRC oscillator w/ PLL (Fcy=23031250Hz,Tcy=43.419ns) //xx = _FOSCSEL(); _FOSCSEL(0x0083); //????????????? ?? ???????? ?????? ? ?????????????? PLL _FOSC(0x0041); //Clock switching is enabled, FSCM is disabled; //Allow multiple reconfigurations; //OSC2 is the clock output and the instruction cycle (FCY) clock is output on OSC2 pin; //XT Crystal Oscillator mode; // Watchdog timer off _FWDT(FWDTEN_OFF); /* * */ //DFT counting void dft_spectr (void) { unsigned int n, k; //"n" - sample number, "k" - DFT coefficient number for (k = 0; k < (how_many_samples - 1); k++){ dpf_real[k] = 0; dpf_imagine[k] = 0; for (n = 0; n <= (how_many_samples - 1); n++){ dpf_real[k] = dpf_real[k] + in_samples[n] * cos(2 * 3.14 * n * k / how_many_samples); dpf_imagine[k] = dpf_imagine[k] - in_samples[n] * sin(2 * 3.14 * n * k / how_many_samples); } //Amplitude computing. //Amplitude = (sqrt(real^2 + imagine^2)) dpf_real[k] = dpf_real[k] / how_many_samples; dpf_imagine[k] = dpf_imagine[k] / how_many_samples; amplitudes[k] = sqrt(powf(dpf_real[k], 2) + powf(dpf_imagine[k], 2)); } } int main(int argc, char** argv) { OSCCON = 0x3301; //Primary Oscillator with PLL; //Clock switching is enabled, system clock source may be modified by clock switching; //Peripheral Pin Select is not locked. Writes to Peripheral Pin Select registers are allowed; //Disable Secondary Oscillator; //????????? oscillator switch to selection specified by the NOSC<2:0> bits; CLKDIV = 0x0000; //FCY divided by 1; //Processor clock and peripheral clock ratio forced to 1:1; //Output divided by 2, i.e. "N2" = 1; //Input divided by 2, i.e. "N1" = 2; PLLFBD = 0x000e; //PLLDIV<8..0> = 14, i.e. "M" multiplier = 16; //7.37 MHz OSCTUN = 0x0000; //Fast RC Oscillator Tuning bits (? ????? ?????? ?? ????????????) /// // Configure RRB14, 15 as digital outputs // Configure RB9 as digital input TRISB = 0x3fff; // Configure RG15 as digital input TRISG = 0xffff; // Configure PORT D as digital outputs (but 10, 11 will be tuned as inputs //because of 10 (not 12) - bits ADC) TRISD = 0x0c00; //The PORTB pins have alternate functions as analog inputs. //You need to configure the ADPCFG register for digital pins (bits set to 1) //as the reset value is all zeros (analog pins). ADPCFG = 0xfdfc; //Using PORTB.9 as analog input pin (ADC input)) //Using PORTB.0, 1 as analog input pins (Vref+, Vref-)) //The code below configures and enables ADC1, AN9 (PIN = PINB.9) to 12 bit, integer, //automatic conversion mode, with no scanning. //disable ADC AD1CON1bits.ADON = 0; // Configure RB9 as digital input TRISB = 0x3fff; AD1PCFGLbits.PCFG9 = 0; //set AD1 AN9 input pin as analog //Configure AD1CON1 AD1CON1bits.AD12B = 0; //set 10b Operation Mode (this bit is UNDOCUMENTED !!!)) AD1CON1bits.FORM = 0; //set integer output AD1CON1bits.SSRC = 0x7; //set automatic conversion //Configure AD1CON2 AD1CON2 = 0; //not using scanning sampling //Configure AD1CON3 AD1CON3bits.ADRC = 0; //internal clock source AD1CON3bits.SAMC = 0x1F; //sample-to-conversion clock = 31Tad AD1CON3bits.ADCS = 0x2; //Tad = 3Tcy (Time cycles) //Leave AD1CON4 at its default value //enable ADC AD1CON1bits.ADON = 1; //50 samples how_many_samples = 50; while (1){ //Taking "how_many_samples" input samples for (i = 0; i < how_many_samples; i++){ //The code below will sample ADC1 AN9 with the above configuration: AD1CHS0bits.CH0SA = 9; //set ADC to Sample AN9 pin AD1CON1bits.SAMP = 1; //start to sample while(!AD1CON1bits.DONE); //wait for conversion to finish AD1CON1bits.DONE = 0; //MUST HAVE! clear conversion done bit in_samples[i] = ADC1BUF0; for (j = 0; j < 1055; j++) {}; // 1 millisecond delay } //DFT computing dft_spectr(); //Sending amplitude spectre to R-2R DAC on port "D" (10 bits) _LATB14 = 1; //Only for oscilloscope sync (0 -> 1 edge) for (i = 0; i < (how_many_samples / 2); i++){ _LATB15 = 1; // RB14 -> 1 LATD = amplitudes[i]; for (j = 0; j < 1055; j++) {}; // 1 millisecond delay _LATB15 = 0; // RB14 -> 0 for (j = 0; j < 1055; j++) {}; // 1 millisecond delay } _LATB14 = 0; } } Quote Share this post Link to post Share on other sites More sharing options...