Constantin
Well-known member
Hi everyone,
I am currently trying to get my Teensy 3 and a MCP3911 to communicate via SPI (Code below). Unfortunately, I am getting nowhere. Instead of getting the desired response (i.e. an acknowledgement that the right register (0x0D) has been modified to put the ADCs into reset mode), I get nothing but the following:.
Other registers have responded with nothing but 1's.
For those of you well versed in the art of SPI, is there something obvious that I have missed? The bare electrical connections appear to be good, so I feel like I am running out of options... Any help is appreciated and thanks in advance. Constantin
I am currently trying to get my Teensy 3 and a MCP3911 to communicate via SPI (Code below). Unfortunately, I am getting nowhere. Instead of getting the desired response (i.e. an acknowledgement that the right register (0x0D) has been modified to put the ADCs into reset mode), I get nothing but the following:.
Command Register Received: 1101 - Command Received: 11000000
Write Command Byte Sent: 11010
Read Command Byte Used: 11011
Error for register: 1101 - Command Sent: 11000000 - Response Received: 0
Other registers have responded with nothing but 1's.
For those of you well versed in the art of SPI, is there something obvious that I have missed? The bare electrical connections appear to be good, so I feel like I am running out of options... Any help is appreciated and thanks in advance. Constantin
Code:
// SPI Stuff here
#include "SPI.h"
const uint8_t MCP3911_CS = 9; // Teensy SPI CS1 = MCP3911
const uint8_t SD_Card_CS = 10; // Teensy CS0 = SD Card
const uint8_t MCP3911_DR = 2; //Data Ready Signal for MCP3911
const uint8_t LED = 13; //LED on Teensy
void setup() {
//SPI Bus setup
pinMode (MCP3911_CS, OUTPUT); // MCP3911
pinMode (SD_Card_CS, OUTPUT); // SD Card
pinMode (MCP3911_DR, INPUT); //Data Ready Pin on MCP3911
SPI.setBitOrder(MSBFIRST);
SPI.setDataMode(SPI_MODE0);
SPI.setClockDivider(SPI_CLOCK_DIV8); //i.e. 6MHz on a Teensy running at 48MHz.
SPI.begin();
//Setup Serial Comms
Serial.begin(115200);
pinMode(LED,OUTPUT); //enable blinking LED
}
void loop()
{
bool led=1;
for (int i=0;i<2;i++) {
digitalWrite(LED,led);
delay(250);
led = !led;
}
Reset_ADC(); //Setup the MCP3911
}
uint8_t Write_MCP3911_Register (uint8_t MCP3911_Register_Address, uint8_t Command) {
Serial.print("Command Register Received: ");
Serial.print(MCP3911_Register_Address,BIN);
Serial.print(" - Command Received: ");
Serial.println(Command,BIN);
MCP3911_Register_Address = (MCP3911_Register_Address<<1) & B00111110;
//right shift address one digit
// and ensure last digit is a zero for write command
digitalWrite(MCP3911_CS, LOW);
SPI.transfer(MCP3911_Register_Address); // send address with write command to MCP3911
SPI.transfer(Command); //now send payload
digitalWrite(MCP3911_CS, HIGH); // deselect the CS pin.
Serial.print("Write Command Byte Sent: ");
Serial.println(MCP3911_Register_Address,BIN); // verify what command was sent (i.e. address and write bit = 0)
//Now Verify all went well
MCP3911_Register_Address += 1; //Turn on Read Operation by toggling last bit on
Serial.print(" Read Command Byte Used: ");
Serial.print(MCP3911_Register_Address,BIN); //show command used
digitalWrite(MCP3911_CS, LOW); //take CS low to initiat SPI
SPI.transfer(MCP3911_Register_Address); // send address with read command to MCP3911
uint8_t Response = SPI.transfer(0x0); //read one response
digitalWrite(MCP3911_CS, HIGH); //take CS pin back high again to end SPI transmission
//now verify that the register content matches the command sent. If so, have the function return value of one,
//otherwise, alert the user that something is amiss.
if (Response == Command) return 1;
else
{
Serial.println("");
Serial.print("Error for register: ");
Serial.print(MCP3911_Register_Address>>1,BIN);
Serial.print(" - Command Sent: ");
Serial.print(Command,BIN);
Serial.print(" - Response Received: ");
Serial.println(Response,BIN);
Serial.println("");
return 0;
}
}
uint8_t Read_MCP3911_Register (uint8_t MCP3911_Register_Address) {
Serial.print("Desired Register Address: ");
Serial.print(MCP3911_Register_Address,BIN);
MCP3911_Register_Address = (MCP3911_Register_Address<<1) & B00111110; //right shift address one digit and mask first two bits and last
MCP3911_Register_Address +=1; // add one to toggle read bit
Serial.print(" - Read Command Sent: ");
Serial.print(MCP3911_Register_Address,BIN);
digitalWrite(MCP3911_CS, LOW);
SPI.transfer(MCP3911_Register_Address); // send address with read command to MCP3911
uint8_t Response = SPI.transfer(0x0);
digitalWrite(MCP3911_CS, HIGH);
Serial.print(" - Response Received: ");
Serial.println(Response,BIN);
return Response;
}
void Reset_ADC()
{
// Puts ADC into Reset Mode, i.e. stops ADC conversions until setup is complete.
/*
bit 7:6 RESET<1:0>: Reset mode setting for ADCs
11 = Both CH0 and CH1 ADC are in reset mode
10 = CH1 ADC in reset mode
01 = CH0 ADC in reset mode
*00 = Neither ADC in reset mode(default)
bit5:4 SHUTDOWN<1:0>: Shutdown mode setting for ADCs
11 = Both CH0 and CH1 ADC in Shutdown
10 = CH1 ADC in Shutdown
01 = CH0 ADC in Shutdown
*00 = Neither Channel in Shutdown(default)
bit 3: Not implemented, read as 0
bit 2: VREFEXT Internal Voltage Reference Shutdown Control
1 = Internal Voltage Reference Disabled
*0 = Internal Voltage Reference Enabled (Default)
bit 1: CLKEXT Internal Clock selection bits
1 = External clock drive by MCU on OSC1 pin (crystal oscillator disabled, no internal power consumption) (Default)
*0 = Crystal oscillator is enabled. A crystal must be placed between OSC1 and OSC2 pins.
bit 0: Not implemented, read as 0
*/
Write_MCP3911_Register (0x0D, B11000000);
}