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