Hi,
For reading from AD7780 I'm waiting for DOUT/~RDY pin to go low and after about 100us reading 32-bit. Then by checking eight status bit if equals 0x0D (according to filter and gain that is set) (which indicated that there is no error with communication and the conversion is completed), using 24-bit output for my application.
By this method everything is ok and the result is correct but two things occur that sometimes make the output wrong:
1) In some reading, the status bit is correct but the data output is 0xFFFFFF or 0x000000. This occurs once in "about" every 10 conversions.
2) Worse than first, In some reading the data output is wrong (far from what it should be). This occurs occasionally and too late after about every thousand conversions.
I can ignore the first one by filtering the 0x0 or 0xFFFFFF data because my input never is zero or full-scale (may be a bad practice because this assumption seems to be not absolutely true) but the second problem is unacceptable.
STM32F1xx is used for reading from adc. First I used SPI peripheral of STM3F1 for reading data from adc. But after that I use a basic and simple code for reading data to ensure there is no problem in my communication with ADC. This simple code makes the condition better and the wrong data is occurred at a lower frequency. Nevertheless the problem with wrong data is remained and is not solved completely.
Edge detection of DOUT/~RDY pin for getting low and reading operation all is done in a 100us-period timer.
This is my code:
/*check if timer 1 interrupt(100us) is occured or not*/
if(htim->Instance == TIM1)
{
/*check if RDYLow flag is set*/
if(RDYLow == 1)
{
/*toggle SCLK pin 64 times (for 32-bit reading)*/
/*clock cylce is 200us*/
if(bitNum < 64)
{
HAL_GPIO_TogglePin(GPIOA,GPIO_PIN_5);
/*read pin in rising edge of sclk*/
if(bitNum % 2 != 0)
{
readPin = HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_6);
a = bitNum/2;
adc8 [a] = readPin ;
}
bitNum++;
}
else
{
/*32-bit reading complete*/
bitNum = 0;
adcCnt++;
/*check status byte to be 0x0D*/
if(adc8[31] == 1 && adc8[30] == 0 && adc8[29] == 1 && adc8[28] == 1) /*0x00001101*/
{
adc32 = 0;
/*shift the seperated 24-bit data into a 32-bit integer*/
for(b = 0;b < 24;b++)
adc32 += (uint32_t)( adc8[b] << (23-b));
/*check if data is not 0xFFFFFF or 0x0*/
if(adc32 != 0xFFFFFF && adc32 != 0)
{
temp32 = adc32 & 0x7FFFFF;
adcValidBit = (temp32 >> 9);
/*convert adc value to real pressure*/
adcVinput = (5.0f * adcValidBit)/powf(2,14);
if((adc32 >> 23) == 1)
pressTemp = adcVinput * (100.0f/(4.07f-0.792f)) - 24.16f;/*hardware: .792v --> 0bar,4.07v--> 100bar*/
else
pressTemp = -1.0f * adcVinput * (100.0f/(4.07f-0.792f)) - 24.16f;/*hardware: .792v --> 0bar,4.07v--> 100bar*/;
/*calibration*/
pressTempCal = pressGain * pressTemp + pressOff;
pressure = pressTempCal - pressZero;
}
}
RDYLow = 0;
adc8[31] = 0;
adc8[30] = 0;
adc8[29] = 0;
adc8[28] = 0;
}
}
one_ms_counter3++;
/*RDY pin edge detection*/
if(HAL_GPIO_ReadPin(adcStart_GPIO_Port,adcStart_Pin) == 0)
{
if(adcStatus == 1)
{
adcStatus = 0;
adcIntCnt++;
one_ms_counter3 = 0;
}
}
else
{
if(adcStatus == 0)
adcStatus = 1;
}
/* if RDY level is low set RDYLow flag for reading*/
if(adcStatus == 0)
{
one_ms_counter2 = 0;
RDYLow = 1;
}
}
ADC input and reference voltage is stable in my test and I don't think the problem is due to hardware design (good hardware design according to considerations).
Please help me with this problem.
Thanks.