Greetings!
I'm using the ADS131A04EVM and I'm trying to interface the ADC chip to Odroid C1+. However, the chip doesn't respond to any of the commands that I send and instead, all I'm able to read is 0x1. It doesn't send me anything else, regardless of what I transmit.
For reference here is the EVM configuration I'm using:
I've shorted the JP1 header to enable external digital signals (hold the on board processor in RESET and disable the level shifter).
I've also switched S4 down for manual control of the ADC chip's mode pins:
M0: pins 1 and 2 connected (IOVDD) for asynchronous interrupt mode
M1: pins 1 and 2 connected (IOVDD) for 32 bit word size
M2: pins 2 and 3 connected (GND) for no hamming code
Other switches and headers are left to their default positions (sbau259)
Reference voltage is EVM board generated reference voltage and adc input signal is 1.2V DC. (Though I don't think this matters for my problem)
Lastly, the board uses USB power for both analog and digital power supplies.
SPI wiring:
The schematics showed that there already is a pull-up resistor connected to MISO so I didn't bother to add anymore pull-ups when I wired the two modules together.
I wrote the code below for initializing the adc chip. I've made sure to set SPI mode to 1, word size to 32 bits, and frame length to 1 word (since the ads131a04 uses dynamic frame size by default). I used 1MHz SCLK frequency which is far from the chip's max (25MHz). The datasheet specified that when in 32 bit mode, the 16 bit commands to be sent should have their LSBs padded with zeroes, I've followed that too (ie. 0x00110000 for RESET command).
I've tried isolated tests to see if both components that I'm using are working. For the ADS131A04 chip, I tested it by re-enabling the on board processor and running the TI program that came with it. It was working fine. For the Odroid C1+, I tested the code above (with minor changes like SPI settings and commands) with the ArduCAM Mini and I was able to communicate with it through SPI.
I'm only using a really old 100Mhz analog oscilloscope to check the signals and I can't actually see the bit by bit waveform being transmitted/received (the signal isn't stable). I've checked the forum but the existing thread which almost had the same problem that I had doesn't have an answer (nobody replied to it yet and it's been posted about a month ago). I've ran out of ideas for tests to pinpoint where I went wrong. Any suggestions? Thanks in advance!
/* SPI interface for ADS131a04 * SPI Mode: 1 * Sampling rate: 500 sps * Bit per word: 32 bits */ #include <stdint.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <getopt.h> #include <fcntl.h> #include <sys/ioctl.h> #include <linux/types.h> #include <linux/spi/spidev.h> #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0])) static void pabort(const char *s) { perror(s); abort(); } /*** SPI variables initialization ***/ static const char *device = "/dev/spidev0.0"; static uint8_t mode = SPI_MODE_1; static uint8_t bits = 32; static uint32_t speed = 1000000; //static uint16_t delay; static uint16_t delay = 1; //Check CS behavior per transfer first static uint8_t deselect_cs = 1; static void waitForADCReady(int fd) { int ret; uint32_t tx[1] = {0}; uint32_t rx[ARRAY_SIZE(tx)] = {0, }; struct spi_ioc_transfer tr = { .tx_buf = (unsigned long)tx, .rx_buf = (unsigned long)rx, .len = ARRAY_SIZE(tx), .delay_usecs = delay, .speed_hz = speed, .bits_per_word = bits, }; printf("Waiting for READY...\n"); while (1) { ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); if (ret < 1) pabort("can't send spi message"); printf("0x%x\n", rx[0]); if(rx[0] == 0xFF040000) { printf("0x%x", rx[0]); break; } } } void sendADCcommand(int fd, uint32_t command, uint32_t status) { int ret; int i = 0; uint32_t tx[1] = {0}; uint32_t rx[ARRAY_SIZE(tx)] = {0, }; struct spi_ioc_transfer tr = { .tx_buf = (unsigned long)tx, .rx_buf = (unsigned long)rx, .len = ARRAY_SIZE(tx), .delay_usecs = delay, .speed_hz = speed, .bits_per_word = bits, //.cs_change = deselect_cs, }; tx[0] = command; printf("Sending command = 0x%x\n", tx[0]); ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); if (ret < 1) pabort("can't send spi message"); tx[0] = 0; printf("Waiting for acknowledgement = 0x%x...\n", status); while (1) { ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); if (ret < 1) pabort("can't send spi message"); if (i == 10000) { printf("tx = 0x%x, rx = 0x%x\n", tx[0], rx[0]); i = 0; } if(rx[0] == status) { printf("0x%x", rx[0]); break; } i++; } } void readADCdata(int fd, float* ADCvalues) { int ret, i; uint32_t tx[5] = {0, 0, 0, 0, 0}; uint32_t rx[ARRAY_SIZE(tx)] = {0, }; struct spi_ioc_transfer tr = { .tx_buf = (unsigned long)tx, .rx_buf = (unsigned long)rx, .len = ARRAY_SIZE(tx), .delay_usecs = delay, .speed_hz = speed, .bits_per_word = bits, //.cs_change = deselect_cs, }; ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr); if (ret < 1) pabort("can't send spi message"); for (i = 0; i < 3 ; i++) { *(ADCvalues + i) = rx[i+1] >> 8; //data is 24 bits left aligned on a 32 bit word *(ADCvalues + i) *= (float) 2.5/8388608; //ADC conversion factor } } int main(int argc, char *argv[]) { int ret = 0; int fd; fd = open(device, O_RDWR); if (fd < 0) pabort("can't open device"); /*** SPI mode init ***/ ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); if (ret == -1) pabort("can't set spi mode"); ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); if (ret == -1) pabort("can't get spi mode"); /*** Set bits per word ***/ ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); if (ret == -1) pabort("can't set bits per word"); ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); if (ret == -1) pabort("can't get bits per word"); /*** Set max speed hz ***/ ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); if (ret == -1) pabort("can't set max speed hz"); ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); if (ret == -1) pabort("can't get max speed hz"); printf("spi mode: %d\n", mode); printf("bits per word: %d\n", bits); printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); //waitForADCReady(fd); sendADCcommand(fd, 0x00110000, 0xFF040000); //send RESET command and wait for READY sendADCcommand(fd, 0x06550000, 0x06550000); //unlock ADC sendADCcommand(fd, 0x4D020000, 0x2D020000); //set CLK1 register sendADCcommand(fd, 0x4E400000, 0x2E400000); //set CLK2 register sendADCcommand(fd, 0x4F0F0000, 0x2F0F0000); //enable ADC sendADCcommand(fd, 0x00330000, 0x00330000); //wakeup ADC sendADCcommand(fd, 0x05550000, 0x05550000); //lock registers /*** Data acquisition part ***/ //float* ADCvalues; //readADCdata(fd, ADCvalues); printf("Done! \n"); close(fd); return ret; }