Hi all
I've been buried with datasheet details with a ADC I'm sampling the AD7708, so far everything seems to be working from a configuration point of view, however I hit a point where I don’t have a clue how to proceed as the datasheet makes no reference to timing diagrams or application notes.
The problem / confusion is two parts…
How do I reconstruct the 16-bit ADC value from the read-only register inside the ADC? I tried the following.
1) I used the SPI data in line to issue ISR when the SPI buffer is full. (SPI enhanced mode) , I get nothing the code locks up when I read the SPI1BUF register.
2) Then I tried a more formal approach and just read the port and built the data as it gets shifted in, however this works so so…
A successful ADC conversion is signalled via the READY pin which I can confirm is low (indicating success), but the ADC 16-bit conversion data packet only occurs approximately 350us later (while the READY pin is still low)
How do I go about correctly synchronising the conversion data with the READY PIN at the moment it seems incorrect as the conversion codes are random 65535 (Full scale) with 2.5v applied then it reads 65535 with 0v at the ADC input
adc_spi_start(0); // Setup ADC SPI.
adc_write_byte(ADC_REG_FILTER); // (ADC Filter Register)
adc_write_byte(0x45); // CHOP=Enabled, fADC=19.79(Hz, tADC=50.34(ms)
adc_write_byte(ADC_REG_CTRL); // (ADC Control Register)
adc_write_byte(0xf); // CH-1, enable unipolar coding mode, Input range ± 2.56 V
// ADC Calibration START.
adc_write_byte(ADC_REG_MODE); // (ADC Mode Register)
adc_write_byte(0x14); // Internal zero calibration, 10 pseudo-differential input, reference selected is REFIN1(+) and REFIN1(?) for the active channel.
// analog negative input (AINCOM) is unbuffered allowing it to be tied to AGND in single-ended input configuration, and chopping is enabled.
while(ADC_RDY);
adc_write_byte(ADC_REG_MODE); // (ADC Mode Register)
adc_write_byte(0x15); // Internal Full-Scale Calibration, 10 pseudo-differential input, reference selected is REFIN1(+) and REFIN1(?) for the active channel.
// analog negative input (AINCOM) is unbuffered allowing it to be tied to AGND in single-ended input configuration, and chopping is enabled.
while(ADC_RDY);
// ADC Calibration END.
adc_write_byte(ADC_REG_MODE); // (ADC Mode Register)
adc_write_byte(0x03); // Continuous conversion mode
while(ADC_RDY);
adc_write_byte(ADC_REG_CTRL); // (ADC Control Register)
adc_write_byte(0xf); // select channel 1 and its operating range.
while(ADC_RDY);
close_spi(); // Close Setup ADC SPI.
while(true)
{
#if TEST_ADC_READ
adc_spi_start(0); // Setup ADC SPI.
adc_write_byte(ADC_REG_DATA);
// adc_write_byte(ADC_REG_STATUS);
// while(ADC_RDY);
close_spi(); // Close Setup ADC SPI.
#endif
}
void __attribute__((__interrupt__,__auto_psv__)) _CNInterrupt(void)
{
/*
When a CN interrupt occurs, the user should read the PORT register associated with the CN
pin(s). This will clear the mismatch condition and set up the CN logic to detect the next pin
change. The current PORT value can be compared to the PORT read value obtained at the last
CN interrupt to determine the pin that changed.
The CN pins have a minimum input pulse-width specification. Refer to the ?Electrical
Characteristics? section of the specific device data sheet for further details.
*/
if( ADC_RDY == LOW )
{
__delay_us(350);
g_adc_value = adc_read_word();
}
process_rotray_encoder();
IFS1bits.CNIF = 0; // Clear flag for on change interrupt
}
long adc_read_word()
{
char i;
long adc_data = 0;
for( i = 1; i <= 16; ++i ) // Get the ADC data as a 16-bit value.
{
adc_data = adc_data << 1; // Shift one bit left prepare place for next bit.
if(ADC_DATA == HIGH) // ADC bit high ?
{
adc_data |= 0x01; // Append 1-bit at the start of word.
}
}
return adc_data;
}
[code]