Help with Teensy 4.1 and MCP3464

Status
Not open for further replies.
Hello, I am trying to use the MCP3464 chip to sample arbitrary waveforms in a larger project, but right now I am just trying to get the chip sampling. I am not able to get any meaningful output.
I am using a Teensy 4.1 which claims to be able to use up to 20 MHz but I'm not trying to push its limits so using a 100kHz clock right now for debugging and cleaner waveforms.
Using my oscilloscope to view the SPI waveforms, the waveforms being sent to the chip look exactly as I would expect them to, but the MISO signal does not look remotely correct and thus my MCU says it only gets 0 back for every sample.

All four SPI Lines Image:
Yellow - Chip Select
Blue - SCLK
Purple - MOSI
Green - MISO

DS0012.PNG

Code:
#include <SPI.h>

#define SPI_CLK			100000 // 100 kHz
#define CHIP_SELECT		10

// Register definitions
#define REG_ADCDATA     0x00
#define REG_CONFIG0     0x01
#define REG_CONFIG1     0x02
#define REG_CONFIG2     0x03
#define REG_CONFIG3     0x04
#define REG_IRQ         0x05
#define REG_MUX         0x06
#define REG_SCAN        0x07
#define REG_TIMER       0x08
#define REG_OFFSETCAL   0x09
#define REG_GAINCAL     0x0A
#define REG_LOCK        0x0D

// Init Vectors
#define CONFIG0_INIT	0b11110011 // No total shutdown, internal clock present on pin 18, 0uA current source, ADC conversion mode
#define CONFIG1_INIT	0b00001100 // No prescaler value on clock, over sampling ratio = 256 (default)
#define CONFIG2_INIT	0b10001011 // 1x current boost, 1x Gain, auto zeroing disabled
#define CONFIG3_INIT	0b11000000 // Continuous conversion mode, 16 bit, crc-16 only, crc on communication disabled, offset calibration disabled, gain disabled
#define IRQ_INIT        0b00000110 // Fast commands enabled, IRQs enabled (although not used)
#define MUX_INIT		0b00000001 // Channel 0 -> +, Channel 1 -> -

// MCP3464R Byte Commands
#define CONV_START_FAST_COMM	0b01101000 // restarts ADC conversion, ADC_MODE = 11
#define STANDBY_MODE_FAST_COMM	0b01101100 // puts ADC into standby mode (no conversions, same power draw) ADC_MODE = 10
#define SHUTDOWN_MODE_FAST_COMM 0b01110000 // puts ADC into partial shutdown mode, ADC_MODE = 00
#define FULL_SHUTDOWN_FAST_COMM 0b01110100 // Puts ADC into full shutdown mode (essentially 0 current) CONFIG0 = 0x00
#define STATIC_READ				0b01000001 // must be |'ed with register address << 2
#define INCREMENTAL_READ		0b01000011 // must be |'ed with register address << 2
#define INCREMENTAL_WRITE		0b01000010 // must be |'ed with register address << 2

#define SPI_SETTINGS SPISettings(SPI_CLK, MSBFIRST, SPI_MODE0)

volatile uint8_t status = 0x00;

void sendFastCommand(uint8_t fastCommand) {
	SPI.beginTransaction(SPI_SETTINGS);
	digitalWrite(CHIP_SELECT, LOW);
	SPI.transfer(fastCommand);
	digitalWrite(CHIP_SELECT, HIGH);
	SPI.endTransaction();
}

void writeByteToRegisterWithAddress(uint8_t address, uint8_t data) {
	uint8_t commandByte = INCREMENTAL_WRITE | (address << 2);
	SPI.beginTransaction(SPI_SETTINGS);
	digitalWrite(CHIP_SELECT, LOW);
	status = SPI.transfer(commandByte);
	SPI.transfer(data);
	digitalWrite(CHIP_SELECT, HIGH);
	SPI.endTransaction();
}

uint8_t readByteFromRegisterWithAddress(uint8_t address) {
	uint8_t commandByte = STATIC_READ | (address << 2);
	SPI.beginTransaction(SPI_SETTINGS);
	digitalWrite(CHIP_SELECT, LOW);
	status = SPI.transfer(commandByte);
	uint8_t byte = SPI.transfer(0);
	digitalWrite(CHIP_SELECT, HIGH);
	SPI.endTransaction();
	return byte;
}

uint16_t readADC_DATA() {
	uint8_t commandByte = STATIC_READ; // | (ADC_DATA_ADDR << 2); This code is left out since ADC_DATA_ADDR = 0x00
	SPI.beginTransaction(SPI_SETTINGS);
	digitalWrite(CHIP_SELECT, LOW);
	status = SPI.transfer(commandByte);
	uint16_t sample = SPI.transfer16(0);
	digitalWrite(CHIP_SELECT, HIGH);
	SPI.endTransaction();
    //sendFastCommand(CONV_START_FAST_COMM);
	return sample;
}

void initializeADC() {
	writeByteToRegisterWithAddress(REG_CONFIG0, CONFIG0_INIT);
	writeByteToRegisterWithAddress(REG_CONFIG2, CONFIG2_INIT);
	writeByteToRegisterWithAddress(REG_CONFIG3, CONFIG3_INIT);
    writeByteToRegisterWithAddress(REG_IRQ, IRQ_INIT);
	writeByteToRegisterWithAddress(REG_MUX, MUX_INIT);
}

void setup() {
    Serial.begin(250000);
    while (!Serial) {
        ; // wait for serial port to connect. Needed for native USB
    }
    Serial.println("Serial Connection Established!");
	SPI.begin();
    delay(1000);
    initializeADC();
    //sendFastCommand(CONV_START_FAST_COMM);
}

void loop() {
    uint16_t temp = readADC_DATA();
    Serial.print("value: ");
    Serial.println(temp);
    delay(25);
}
 
Erm, surely
Code:
  pinMode (CHIP_SELECT, OUTPUT);
needs to be in setup - its certainly not being driven from that screen capture.
 
Yeah, that made it at least start communicating now. Thanks!
Any chance someone knows how to make sense of the data it sends?
I'm trying to use it in single ended mode and putting a 0-2V sine wave just to test it out but it's staying locked around 3.3V (which is what I'm powering it with)
 
Over 100 pages in the datasheet - I don't envy you figuring it out, they seldom (for some unfathomable reason) give
an example sane configuration in these datasheets, you have to read about every control register and figure out what
it defaults to and decide what value it should have for your application, which is very tedious.

However you might find someone's already written some sort of library or example code using this chip - which may help.
 
Status
Not open for further replies.
Back
Top