I've been playing around with some analog devices ADCs (SPI parts). One that I'm fairly familiar with is the AD7794. However, I've never used it in continuous read mode. (Teensy 3.0, Teensyduino 1.18)
In continuous read, the part uses its DOUT to indicate conversion complete and ready to read by pulling it low. You then clock in 24 bits of 0 to read the 24 bit data register, and DOUT is pulled high as soon as the last bit is clocked out. I'm just using the SPI.h library for this.
The problem I'm having is that the interrupt routine runs twice, resulting in valid data the first time, and 0xFFFFFF the second, since it's just reading the DOUT line pulled high. I'm new to the world of Arduino/Teensy, so I'm not sure if I'm misunderstanding how attachInterrupt works, and how it masks the interrupt its processing. Anyway, here is what I see on the scope: DOUT is pulled low, three bytes of 0 are clocked in, all good, but then it clocks in another 3 bytes of 0's for no apparent reason (DOUT is high). I've tried putting a delay inside the interrupt function in case it was catching the last 0 on the data line, but it makes no difference.
What am I missing?
In continuous read, the part uses its DOUT to indicate conversion complete and ready to read by pulling it low. You then clock in 24 bits of 0 to read the 24 bit data register, and DOUT is pulled high as soon as the last bit is clocked out. I'm just using the SPI.h library for this.
The problem I'm having is that the interrupt routine runs twice, resulting in valid data the first time, and 0xFFFFFF the second, since it's just reading the DOUT line pulled high. I'm new to the world of Arduino/Teensy, so I'm not sure if I'm misunderstanding how attachInterrupt works, and how it masks the interrupt its processing. Anyway, here is what I see on the scope: DOUT is pulled low, three bytes of 0 are clocked in, all good, but then it clocks in another 3 bytes of 0's for no apparent reason (DOUT is high). I've tried putting a delay inside the interrupt function in case it was catching the last 0 on the data line, but it makes no difference.
What am I missing?
Code:
#include <SPI.h>
volatile long adcValue; // AD7794 continuous read value
// attachInterrupt function for AD7794 continuous read
void readADC() {
adcValue = SPI.transfer(0x00) << 16 | SPI.transfer(0x00) << 8 | SPI.transfer(0x00); // clock in 24 0's to read AD7794 data register
}
void setup() {
Serial.begin(9600);
// setup _CS_ AD7794
pinMode(6, OUTPUT); digitalWrite(6, HIGH);
// setup interrupt pin (wired to pin 12 - was originally attaching interrupt to pin 12, but moved in case of SPI library conflict - but no difference)
pinMode(9, INPUT);
SPI.begin();
delay(3000);
digitalWrite(6, LOW); // select AD7794
for (int i = 0; i < 8; i++) { // reset AD7794
SPI.transfer(0xFF);
}
delay(1); // settle time only 10uS actually needed
// *** this is just set and readback code for the configuration registers on the AD7794 while I'm testing the part ***
Serial.println(); Serial.println("...............<<<<>>>>................."); Serial.println();
// **** STATUS REGISTER ****
SPI.transfer(0b01000000); // set to read the Status register - 8 bits
long response = SPI.transfer(0x80);
Serial.print("Status Register: "); Serial.println(response);
delay(1);
// ***** CONFIGURATION REGISTER ****
SPI.transfer(0b01010000); // set to read the register - 16 bits
response = SPI.transfer(0x80) << 8 | SPI.transfer(0x80);
Serial.print("Configuration Register: "); Serial.println(response);
SPI.transfer(0b00010000); // set to write the register - 16 bits
SPI.transfer(0b00010000); SPI.transfer(0b00100000);
delay(1);
SPI.transfer(0b01010000); // set to read back the configuration - 16 bits
response = SPI.transfer(0x80) << 8 | SPI.transfer(0x80);
Serial.print("Configuration Register: "); Serial.println(response);
delay(1);
// ***** MODE REGISTER ****
SPI.transfer(0b01001000); // set to read the mode register - 16 bits
response = SPI.transfer(0x80) << 8 | SPI.transfer(0x80);
Serial.print("Mode Register: "); Serial.println(response);
delay(1);
// Internal Calibration: zero scale
SPI.transfer(0b00001000); //select mode register for write
SPI.transfer(0b10000000); SPI.transfer(0b00001000); //write configuration bits to calibrate
delay(1); //wait a moment
SPI.transfer(0b01001000); //select mode register for read
response = SPI.transfer(0x80) << 8 | SPI.transfer(0x80); //read new configuration
Serial.print("Mode Register: "); Serial.println(response);
delay(1);
// Internal Calibration: full scale
SPI.transfer(0b00001000); //select mode register for write
SPI.transfer(0b10100000); SPI.transfer(0b00001000); //write configuration bits
delay(1); //wait a moment
SPI.transfer(0b01001000); //select mode register for read
response = SPI.transfer(0x80) << 8 | SPI.transfer(0x80); //read new configuration
Serial.print("Mode Register: "); Serial.println(response);
delay(1);
// Return to continuous conversion mode
SPI.transfer(0b00001000); //select mode register for write
SPI.transfer(0b00000000); SPI.transfer(0b00001000); //write configuration bits
delay(1); //wait a moment
SPI.transfer(0b01001000); //select mode register for read
response = SPI.transfer(0x80) << 8 | SPI.transfer(0x80); //read new configuration
Serial.print("Mode Register: "); Serial.println(response);
delay(500);
// enable interrupt on pin 6 and initiate continuous read
attachInterrupt(9, readADC, LOW);
SPI.transfer(0x5C);
}
void loop() {
}
Last edited: