Google_links

воскресенье, 3 августа 2014 г.

DAC MCP4921 generation Sinus output + programm

DAC MCP4921 generation Sinus output. MCU dsPIC33FJ64GP706 Microchip.
Figure 3. top signal is pack size of 16 bits send MCP4921. Below this is the signal at the output of DAC MCP4921
Figure 1. MCP4921 Connect
Figure 2. MCP4921 CS and SCK




Figure 3. top signal is pack size of 16 bits which peredayutsya MCP4921. Below this is the signal at the output of DAC MCP4921

Soft

/*=======================================================================
prepare values ​​for sinus
=======================================================================*/
void Sinus_OUT(void)
{
RAD_STEP = 6.28/NUM_OUT;
RAD_ACCUM = 0;
for(i = 0; i < NUM_OUT; i++)
{
SIN_VALUE = sin(RAD_ACCUM);
if(SIN_VALUE >= 0)
{
VALUE_OUT[i] = (int)((SIN_VALUE * 2048) + 2047);
}
else
{
VALUE_OUT[i] = (int)(((SIN_VALUE * 2048) + 2048));
}
RAD_ACCUM = RAD_ACCUM + RAD_STEP;
}
}


/******************************************************************************
           Init  SPI
 ******************************************************************************/
void Init_SPI1(void)
{
    // setup the SPI peripheral
    SPI1STAT = 0x0000;          // disable the SPI module (just in case)
    SPI1CON1bits.MSTEN = 1;  // Master Mode
    SPI1CON1bits.MODE16 = 1; // 16 bit format
    SPI1CON1bits.SMP = 0;    
    SPI1CON1bits.SSEN = 0;
    SPI1CON1bits.SPRE = 6;   
    SPI1CON1bits.PPRE = 3;   
    SPI1CON1bits.CKE = 0x01; // Clock Edge Select bit  0x01
    SPI1CON1bits.CKP = 0x00; //  SCK

    SPI1STAT = 0x8000;// enable the SPI module

    IPC2bits.SPI1IP = 2;
    IFS0bits.SPI1IF = 0;
    //IEC0bits.SPI1IE = 1; 
}

/******************************************************************************
     Send command to MCP4921 SPI (16bit)
 ******************************************************************************/
void Write_SPI1(int command)
{
    int temp0;
    SPI1_CS = 0;                  // CS LOW
    SPI1BUF = command;            // write the data out to the SPI peripheral
    while(SPI1STATbits.SPITBF) ;  // Cheking FLAG
    while(!SPI1STATbits.SPIRBF) ; // Cheking FLAG
    temp0 = SPI1BUF;              // Warning! Need read SPI1BUF, else error Transmit
    SPI1_CS = 1;                  // CS HI
    Nop();  // total delay 50nS
    Nop();
    SPI1_LDAC = 0;                // Output data MCP4921
    Nop();  // total delay 100nS
    Nop();
    Nop();
    Nop();
    SPI1_LDAC = 1;                // Output data MCP4921
}


/***********************************************************************
 TIM2 interrupt,  DAC MCP4921 generation Sinus output  
 ***********************************************************************/
void __attribute__((interrupt, no_auto_psv)) _T2Interrupt(void)
{
 IFS0bits.T2IF = 0; // Clear Timer 2 interrupt
 DmaBuffer = (0x0001)&(~(DmaBuffer & 0x0001));
 LATBbits.LATB0 = DmaBuffer;
 if(i >= NUM_OUT)
{
     Nop();
i = 0;
}

 Write_SPI1(VALUE_OUT[i] | 0x3000); // Sin OUT MCP4921
 i = i + 1;

}

/*=============================================================================
Timer 2 time delay for output via the SPI port for external DAC MCP4921
=============================================================================*/
void Init_TMR2(void)
{
    TMR2 = 0x0000;
    PR2  = TIM2_PR2;        // Trigger 5 usec  (value 199)
    IFS0bits.T2IF = 0; // Clear Timer 2 interrupt
    IPC1bits.T2IP = 2;          // приоритет 2
    IEC0bits.T2IE = 1; // Enable Timer 2 interrupt
    T2CONbits.TON = 1; // Start Timer 3
}

/******************************************************************************
            Init Ports
 ******************************************************************************/
void Ports_Init (void)
{
//**********************************
    TRISB = 0x0000;
    TRISBbits.TRISB2 = 0; // SS1 SPI1
//**********************************
    TRISCbits.TRISC2 = 1; // RC2 AN17 - analog
//**********************************
    TRISD = 0x0000;
//**********************************
    TRISFbits.TRISF2 = 1; // SDI SPI вход
    Nop();
    TRISFbits.TRISF3 = 0; // MCP4921 SDO SPI
    Nop();
    TRISFbits.TRISF4 = 0; // MCP4921 LDAC SPI
    Nop();
    LATFbits.LATF4 = 1;   // MCP4921 set LDAC = 1
    Nop();
    TRISFbits.TRISF5 = 0; // MCP4921 CS SPI
    Nop();
    LATFbits.LATF5 = 1;   // MCP4921 set CS = 1
    Nop();
    TRISFbits.TRISF6 = 0; // MCP4921 SCK SPI
 //**********************************
    TRISG = 0x0000;
}


main.c 
#include <xc.h>
//#include "GlobalVars.h" // lib varibal
#define  FCY 40000000UL // определение тактовой частоты для макросов __delay_ms() и __delay_us()
#include <libpic30.h>   // __delay_ms() & __delay_us()
#include <limits.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>

#define NUM_OUT 40 // out point sinus
#define SPI1_CS     LATFbits.LATF5
#define SPI1_LDAC   LATFbits.LATF4

_FGS(GWRP_OFF & GCP_OFF);
_FOSCSEL(FNOSC_PRIPLL);
_FOSC(FCKSM_CSECMD & OSCIOFNC_OFF & POSCMD_XT);
_FWDT(FWDTEN_OFF);

int VALUE_OUT[NUM_OUT]; // массив для выходного значения
float RAD_STEP;
float RAD_ACCUM;
float SIN_VALUE;
int   i; // cycle for

unsigned int DmaBuffer;

void Init_ADC1(void);
void Ports_Init(void);
void Init_TMR2(void);
void Init_TMR3(void);
void Init_DMA0(void);
void __attribute__((interrupt, no_auto_psv)) _DMA0Interrupt(void);
void __attribute__((interrupt, no_auto_psv)) _T2Interrupt(void);
void __attribute__((interrupt, auto_psv)) _SPI1Interrupt(void);
void ProcessADCSamples(int * AdcBuffer);
void Init_SPI1(void);
void Write_SPI1(int command);
void Sinus_OUT(void);



/******************************************************************************
            Основная программа
 ******************************************************************************/
int main(void)
{
  /* Configure Oscillator to operate the device at 80MHz.
     * Fosc= Fin*M/(N1*N2), Fcy=Fosc/2
     * Fosc= 8MHz*40/(2*2)=80Mhz for 8MHz input clock */

  PLLFBD = 38; // M = PLLDIV + 2, умножить на 40, это биты CLKDIV
  CLKDIVbits.PLLPOST = 0; // N1=2 Деление входной частоты (если 0 то на 2) (если 1 то на 4)
  CLKDIVbits.PLLPRE = 0; // N2=2 Деление входной чаты на 2
  OSCTUN = 0;

  RCONbits.SWDTEN = 0; // Disable Watch Dog Timer
  
  __builtin_write_OSCCONH(0x03); /* Initiate Clock Switch to Primary Oscillator with PLL (NOSC=0b011)*/
  __builtin_write_OSCCONL(0x01);
  while (OSCCONbits.COSC != 0b011); /* Wait for Clock switch to occur */
  while (!OSCCONbits.LOCK);
//-----------------------------------------------------------------------------------------------------------

//   INTCON1bits.NSTDIS = 0; // запрет всех прерываний

  AD1PCFGL=0xFFFF;
  AD1PCFGH=0xFFFF;
  AD2PCFGL = 0xFFFF; // all digital

  Ports_Init(); 
  
  Init_SPI1();
  Sinus_OUT();
  Init_TMR2();
  
  while(1)
    {
     Nop();

    }
}