read a differential signal using the Arduino Due ADC

int val;
float voltage;
void setup()
{
pinMode(A0,INPUT);
pinMode(A1,INPUT);
float analogReference(DEFAULT);
pmc_enable_periph_clk(ID_ADC);
adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST);
adc_disable_interrupt (ADC, 0xFFFFFFFF);
adc_disable_all_channel(ADC);//ADC->ADC_CHDR = 0xFFFF ;
adc_set_resolution(ADC, ADC_12_BITS);
adc_configure_timing(ADC,2,ADC_SETTLING_TIME_3,1);
ADC-> ADC_MR=ADC_MR_PRESCAL(1);
bitClear(ADC->ADC_WPMR, 0);
ADC->ADC_IER = 0xC0 ;
ADC->ADC_CGR = 0x15555555 ; // All gains set to x1
ADC->ADC_COR = 0xC00000; // All offsets off,A6 A7 diff mode
adc_enable_anch(ADC);
adc_enable_channel (ADC, ADC_CHANNEL_7);
adc_enable_channel (ADC, ADC_CHANNEL_6);
adc_enable_channel_differential_input(ADC, ADC_CHANNEL_7);
adc_enable_channel_differential_input(ADC, ADC_CHANNEL_6);// Pin A1. CH6+. pg.1327
adc_configure_trigger(ADC, ADC_TRIG_SW,1);
Serial.begin(115200);
adc_start(ADC);

}

void loop()
{
while((adc_get_status(ADC) & ADC_ISR_DRDY) != ADC_ISR_DRDY)
{}; //Wait for end of conversion

val = adc_get_latest_value(ADC);
voltage = val * 3.3;
voltage /= 4095.0;
Serial.println(voltage);
}

But this doesnot print differential voltage,prints A0 value and then A1 value alternately

Try adding these lines:

In setup() : adc_enable_channel(ADC, ADC_CHANNEL_3); // In differrential mode CH3 = CH6 - CH7

On loop(): replace adc_get_latest_value(ADC); by adc_get_channel_value(ADC, ADC_CHANNEL_3);

And I Wonder if val shouldn't be a signed int16_t value.

How come CH3 is CH6-CH7?

Its CH6 in manual and no i m not getting the differential voltage by enabling and reading CH3?

I get 0.47 v + A0 voltage,there is no affect of pin A1 with the changes you mentioned.

Sam3 and Sam4 share a very similar ADC controller, and I suspect that Sam4 datasheet is more up to date.

See table 42_4 page 1093 of Sam4 datasheet. It is stated that in differential mode, CH6 - CH7 = CH3.

And in fact, I did test it, if you enable channel 3 in differrential mode, with analog inputs ONLY in channels 6 and 7, you will read (something) in channel 3 , whilst there is no direct analog input in channel 3.

I guess something is still missing, but this should be a right track.

I have found how to subtract 2 input values thru the fully differential mode.

Below is a snippet with a minimal code to demonstrate that it works. Note that OFFSET is mandatory, as well as ANACH bit to 1 ( except if ch0 and ch1 are already in differential mode) and of course DIFF bits accordingly. The subtract result is available in ADC->ADC_LCDR.

void setup()
{


  adc_setup();

}


void loop()
{

  int16_t Diff67Value;
  Diff67Value =  ADC->ADC_LCDR;

}


void adc_setup() {

  PMC->PMC_PCER1 |= PMC_PCER1_PID37;      // ADC power on
  ADC->ADC_CR = ADC_CR_SWRST;            // Reset ADC

  ADC->ADC_MR |=  ADC_MR_FREERUN
                  | ADC_MR_ANACH_ALLOWED;  
  ADC->ADC_COR =  ADC_COR_DIFF7 // Differential mode for channel 7 and channel 6 (6 - 7); Gain = 

0.5
                  | ADC_COR_DIFF6
                  | ADC_COR_OFF6  // Offset is mandatory
                  | ADC_COR_OFF7;

  ADC->ADC_CHER |=  ADC_CHER_CH6 | ADC_CHER_CH7; // Enable Channels 7,6 = A0,A1  

}

One major interest should be to suppress a part of the noise.

Thanks,yeah its mentioned in the Manual that we need to use external decouplinp capacitors for noise