EQADC output

キャンセル
次の結果を表示 
表示  限定  | 次の代わりに検索 
もしかして: 

EQADC output

2,689件の閲覧回数
Saidev
Contributor II

Hi,

I'm currently working on MPC5777C, In this I'm using EQADC to read voltage.

As per the spec and some reference program from the forum made a program.

I'm also getting the output, however the issue is there is a huge variations in the output .

Attached the output image of EQADC_A.

and also attached the program.

 

 

/*
 * main implementation: use this 'C' sample to create your own application
 *
 */

#include "derivative.h" /* include peripheral declarations */

#include <string.h>
#include <stdio.h>

#include "eQADC_macros_MAMBA.h"
#include "D_UART.h"


#define IDEAL_RES75 0x3000	// Ideal value of 75%(VDH-VDL)
#define IDEAL_RES25 0x1000	// Ideal value of 25%(VDH-VDL)


#define APC 0x2000
#define OBE 0x0200
#define IBE 0x0100
#define ODE 0x0020
#define SRC 0x0004
#define WPE 0x0002
#define WPS 0x0001
#define ALT0 0x0000
#define ALT1 0x0400
#define ALT2 0x0800
#define ALT3 0x0C00


#define ANB16_pin 484 // PCR number
#define ANB17_pin 485
#define ANB18_pin 486
#define ANB19_pin 487

#define ANA29_chnl 29 // channel number
#define ANA18_chnl 18
#define ANA19_chnl 19
#define ANA20_chnl 20

//   Conversion Command Format for the Standard Configuration
#define ANA29_command \
( EOQ | MESSAGE_TAG(RFIFO0) | CHANNEL(ANA29_chnl) )
#define ANA18_command \
( EOQ | MESSAGE_TAG(RFIFO0) | CHANNEL(ANA18_chnl) )
#define ANA19_command \
( EOQ | MESSAGE_TAG(RFIFO0) | CHANNEL(ANA19_chnl) )
#define ANA20_command \
( EOQ | MESSAGE_TAG(RFIFO0) | CHANNEL(ANA20_chnl) )


#define ANA17_command_cal \
( CAL | EOQ | MESSAGE_TAG(RFIFO0) | CHANNEL(ANA17_chnl) )
#define ANA18_command_cal \
( CAL | EOQ | MESSAGE_TAG(RFIFO0) | CHANNEL(ANA18_chnl) )
#define ANA19_command_cal \
( CAL | EOQ | MESSAGE_TAG(RFIFO0) | CHANNEL(ANA19_chnl) )
#define ANA20_command_cal \
( CAL | EOQ | MESSAGE_TAG(RFIFO0) | CHANNEL(ANA20_chnl) )





extern void xcptn_xmpl(void);

static void HW_init(void);

static uint32_t Result = 0;

char str[10u] = "receive\n";

static void HW_init(void)
{
    /* set round robin for all slaves */
    XBAR.PORT[0].CRS.B.ARB = 1;
    XBAR.PORT[1].CRS.B.ARB = 1;
    XBAR.PORT[2].CRS.B.ARB = 1;
    XBAR.PORT[3].CRS.B.ARB = 1;
    XBAR.PORT[4].CRS.B.ARB = 1;
    XBAR.PORT[6].CRS.B.ARB = 1;
    XBAR.PORT[7].CRS.B.ARB = 1;

}


void D_PLL_Init()
{
// Disable PLL0
  PLLDIG.PLL0CR.R = 0;
// Disable PLL1
  PLLDIG.PLL1CR.R = 0;

// Select XOSC as PLL0 source
// Select PHI1 output of PLL0 as PLL1 source
  SIU.SYSDIV.R = 0x04000010;

 /* Program PLL0
 RFDPHI1 = 0x0C
 RFDPHI = 0x03
 PREDIV = 0x5
 MFD = 0x48
*/
  PLLDIG.PLL0DV.R = 0x60035048;

  //PLLDIG.PLL0DV.R = 0x40025060; //20 MHz crystal

// Wait for stable XOSC
   while (!SIU.RSR.B.XOSC);
 // Turn on PLL0 and wait for lock
   PLLDIG.PLL0CR.R = 0x0300;
   while (!PLLDIG.PLL0SR.B.LOCK);

/* Program PLL1
  RFDPHI = 0x02
  MFD = 0x16
*/
   PLLDIG.PLL1DV.R=0x00020016;
// Turn on PLL1 and wait for lock
   PLLDIG.PLL1CR.R = 0x0300;
   while (!PLLDIG.PLL1SR.B.LOCK);

/*
#******************************
# Select clock dividers and sources
#   PLL0 ref = XOSX
#   PLL1 ref = PLL0 PHI1
#   PERCLKSEL = PLL1
#   PERDIV = Divide-by-2
#   MCANSEL = XOSC
#   SYSCLKSEL = PLL1
#   ETPUDIV = Divide-by-1
#   SYSCLKDIV = Divide-by-1
#   PCS = Disabled
#******************************
*/
 SIU.SYSDIV.R = 0x05002110;
 SIU.ECCR.B.ECCS  = 0;
 SIU.ECCR.B.ENGDIV = 64;

}


static uint32_t ConvertChannel(int32_t channel, int32_t bCal)
{
    uint32_t ret = 0;

    /* Conversion command: convert "channel" */
    /* with ADC0, set EOQ, and send result to RFIFO 0 */
    /* 128 adc clocks sampling */
    EQADC_A.CFPR[0].R = 0x800C0000 | (channel<<8) | (bCal<<24);
    EQADC_A.CFCR0.R = 0x04100000;   /* Trigger CFIFO 0 using Single Scan SW mode */
    /* Wait for RFIFO 0's Drain Flag to set */
    while (EQADC_A.FISR[0].B.RFDFX != 1){}

    ret = EQADC_A.RFPR[0].R;

    /* Clear RFIFO 0's Drain Flag */
    /* Clear CFIFO's End of Queue flag */
    /* RFDF + EOQF */
    EQADC_A.FISR[0].R = 0x10020000;

    return ret;
}

int Compare (const void * p0, const void * p1)
{
    uint32_t a0 = (uint32_t) *(uint32_t*)p0;
    uint32_t a1 = (uint32_t) *(uint32_t*)p1;

    if(a0==a1) return 0;
    if(a0<a1) return -1;
    else return 1;
}

static uint32_t ConvertChannel_Median(int32_t channel, int32_t bCal)
{
    uint32_t results[21];

    int32_t i = 0;
    for(i=0;i<sizeof(results)/sizeof(results[0]);i++)
    {
        results[i] = ConvertChannel(channel, bCal);
    }

    /* sort results */
    qsort((void*)results,21,sizeof(results[i]),Compare);

    return results[10]; /* median */
}





static int32_t EQADC_PowerUpCalibration(void)
{
    unsigned long raw_res75, raw_res25;
    unsigned long cal_res75, cal_res25;

    float gccf, occf;

    unsigned short gain;
    short offset;

    /* Convert channel 43 (75%VRH)with CAL=0 */
    raw_res75 = ConvertChannel_Median(43,0);
    /* Convert channel 44 (25%VRH)with CAL=0, 64 sample time (errata) */
    raw_res25 = ConvertChannel_Median(44,0);

    /* Compute Gain and Offset */
    gccf = (float)(8192.0)/(raw_res75 - raw_res25);
    gain = gccf * 16384;
    occf = (float)(IDEAL_RES75 - (gccf * raw_res75) - 2.0);
    offset = occf;

    /* now store Gain in ADCn_GCCR */
    EQADC_A.CFPR[0].R = (gain<<8) | 0x00000004;
    /* now store offset in ADCn_OCCR */
    EQADC_A.CFPR[0].R = ((unsigned short)offset <<  | 0x00000005;

    /* now store Gain in ADCn_AGR */
    EQADC_A.CFPR[0].R = (gain<<8) | 0x00000031;
    /* now store offset in ADCn_ACR */
    EQADC_A.CFPR[0].R = ((unsigned short)offset <<  | 0x00000032 | 0x80000000;

    EQADC_A.CFCR0.R = 0x04100000;    /* Trigger CFIFO 0 using Single Scan SW mode */
    while (EQADC_A.FISR[0].B.EOQFX !=1) {} /* Wait for End Of Queue flag */
    EQADC_A.FISR[0].R = 0x10000000;

    cal_res75 = ConvertChannel(43,1);
    cal_res25 = ConvertChannel(44,1);

    // Check the results
    if ((abs(cal_res75 - IDEAL_RES75) > 0xF) || (abs(cal_res25 - IDEAL_RES25) > 0xF))
    {
	    /* error */
	    return 1;
    }

    return 0; /* no error */
}



static void eQADCA_init(void)
{

    #define SINGLE_SCAN_TRIGGER_Q0 EQADC_A.CFCR0.R=0x04100000
    #define SINGLE_SCAN_TRIGGER_Q1 EQADC_A.CFCR0.R=0x00000410

    #define EQADC_A_IDCR_PIE_MASK      0x2000
    #define EQADC_A_IDCR_EOQIE_MASK    0x1000
    #define EQADC_A_IDCR_CFFE_MASK     0x0200
    #define EQADC_A_IDCR_CFFS_MASK     0x0100
    #define EQADC_A_IDCR_RFDE_MASK     0x0002
    #define EQADC_A_IDCR_RFDS_MASK     0x0001

    #define FISR_EOQ_MASK 0x10000000

    int32_t i = 0;
    uint32_t res = 0;
    vint32_t counter = 0;

    // expecting per_clk = 96 MHz (PLL0/2 = 192/2)
    // fADC < 16.5MHz => 96/6 = 16MHz => ADC0/1_CLK_PS[0:4] = 0b00010
    // => ADC0/1_CR = 0x8002

    PUSH_TO_CFIFO1_A( B0                     |
                       ADC_REG_VALUE (0x8002) | // enables ADC0
                       ADC_REG_ADDR (ADC0_CR) );

    PUSH_TO_CFIFO1_A( EOQ                    |
                       B1                     |
                       ADC_REG_VALUE (0x8002) | // enables ADC1
                       ADC_REG_ADDR (ADC1_CR) );

    // Trigger CFIFO 0 using Single Scan SW mode
    SINGLE_SCAN_TRIGGER_Q1;


    // Wait for End Of Queue flag
    while (EQADC_A.FISR[1].B.EOQFX !=1)
    {
    }

    // Clear End Of Queue flag
    EQADC_A.FISR[1].R = FISR_EOQ_MASK;

    // eQADC calibration
    for(i=0;i<100000;i++) {}

    // note b05111: - this notation calls the function until it returns 0
    //              - would be probably better to use 'while' loop
    i=1;
    res=0;
    for(;i==1;i=EQADC_PowerUpCalibration())
    {
        res++;
    }

    D_UART_TransmitData("eqadc init\n",12);

}





int main(void)
{
	volatile int counter = 0;
	
	xcptn_xmpl ();              /* Configure and Enable Interrupts */


	// Hardware initialization
	    HW_init();

	    D_PLL_Init();

	    D_Init_eSCI_A ();
	    // eQADC initialization and calibration
	    eQADCA_init();




	/* Loop forever */
	for(;;) {	   

		PUSH_TO_CFIFO0_A( ANA29_command );

		        // Trigger CFIFO 0 using Single Scan SW mode
		        EQADC_A.CFCR0.B.MODE0 = SOFTWARE_TRIGGER_SINGLE_SCAN;
		        EQADC_A.CFCR0.B.SSE0 = 1;

		        // Wait for RFIFO 0's Drain Flag to set
		        while (EQADC_A.FISR[0].B.RFDFX != 1)
		        {
		        }

		        // Read conversion result
		        Result = POP_FROM_RFIFO0_A;

		        // Clear RFIFO 0's Drain Flag
		        EQADC_A.FISR[0].B.RFDFX = 1;

		        // Clear CFIFO's End of Queue flag
		        EQADC_A.FISR[0].B.EOQFX = 1;


		        // Display converted value
		        dec_to_str(str,(uint32_t)((5000*Result)/0x3FFC),5u);
		        	   	D_UART_TransmitData(str,5u);
		        	   	D_UART_TransmitData("\n",1);


	}
}

 

タグ(4)
0 件の賞賛
返信
4 返答(返信)

2,662件の閲覧回数
Saidev
Contributor II

thanks for your reply.

I have some mVolt variations in my source, only when reading in CRO otherwise in multimeter it is showing constant voltage.

can you help me with how to program with calibration, what changes I have to make?

0 件の賞賛
返信

2,631件の閲覧回数
davidtosenovjan
NXP TechSupport
NXP TechSupport

The example contains everything needed. Just use

PUSH_TO_CFIFO0_A( ANA29_command_cal );

instead of

PUSH_TO_CFIFO0_A( ANA29_command );
0 件の賞賛
返信

2,614件の閲覧回数
Saidev
Contributor II

Thanks for your reply,

Now I'm getting the closer output value, there is a 50mV variation in source that is what the issue earlier. 

Thank you 

タグ(2)
0 件の賞賛
返信

2,667件の閲覧回数
davidtosenovjan
NXP TechSupport
NXP TechSupport

What is the voltage you are converting? Is it is stabilized output of laboratory power supply?

Also you are converting without calibration, convert WITH calibration.

タグ(1)
0 件の賞賛
返信