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);
}
}
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?
The example contains everything needed. Just use
PUSH_TO_CFIFO0_A( ANA29_command_cal );
instead of
PUSH_TO_CFIFO0_A( ANA29_command );
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.