Jump to content
    

dsPIC33. Простейший проект для старта (мигание лампочкой). Вот, нашел:

Три дня искал. Может, кому-то сэкономлю время:

 

https://batchloaf.wordpress.com/2012/11/17/simple-dspic33fj32mc202-example/

 

Компилируется и работает. Там, правда, для другого МК (у меня dsPIC33FJ128GP706), так что пришлось немного подправить ...

Share this post


Link to post
Share on other sites

А вот пример с настройкой осциллятора:

 

(

Взят вот отсюда:

 

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) {}; } 

Share this post


Link to post
Share on other sites

Вот пример с использованием таймера. Проверил, работает:

 

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;
}

 

Share this post


Link to post
Share on other sites

Методичка какого-то зарубежного ВУЗа, там пример с АЦП и еще много интересного. Правда, пример пришлось немного подправить, а то не компилировался:

 

https://cs-people.bu.edu/rmancuso/courses/cs454_654-sp20/material/labmanual.pdf

Share this post


Link to post
Share on other sites

А вот - простейший цифровой фильтр скользящего среднего, без всяких оптимизаций. Сам написал (только не смейтесь). Может, кому-то пригодится:

 

/* 
 * Пример простейшего КИХ - фильтра скользящего среднего
 */

#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;
}

 

Share this post


Link to post
Share on other sites

А вот - простейший цифровой фильтр скользящего среднего, без всяких оптимизаций. Сам написал (только не смейтесь). Может, кому-то пригодится:

Какие уж тут смехи...
А теперь то же самое, но без цепочки пересохранений в массиве-буфере (а прикиньте если бы 256 отсчётов) и цикла суммирования ;-)
Edited by Obam

Share this post


Link to post
Share on other sites

Сейчас ...

Вот, сегодня написал (в работе я опирался на 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;
}

 

Share this post


Link to post
Share on other sites

Заграждающий БИХ - фильтр (на частоту 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;
}

 

Share this post


Link to post
Share on other sites

Простейшая реализация ДПФ. Частота дискретизации - 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;    
         }
}

 

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...