MCP3901 (ADC) using SPI: configuration and reading
Posted: 02 Dec 2010 17:34
Good day
I'm a bit stuck with this device and SPI in general. I've never used SPI before, though I've read as much literature as I can find.
I'm paring the MCP3901 (ADC) with a dsPIC33FJ256MC710 by using the 2nd SPI module on the chip. In addition, I'm using channel 0 on the MCP3901. I'm trying to do this with the built in SPI library routines (also, I'm not using interrupts).
Ok, so the first byte sent to the ADC is the control byte, laid out as follows:
First 2 bits - Device address bits
Next 5 bits - Internal register address bits
Last bit - Read/Write bit.
So for instance a control byte looking like 0b00010010 would be a control byte stating that the device address is 00, 01001 would be the stat/comm address, and 0 would indicate that the next byte sent would be written to that register (the stat/comm register that is). Thats my understanding of it, so far.
Thereafter, the next bytes written to the ADC would be to the registers as they appear in sequence (every time after you write to the device, the address shifts to that of the next register so that the next write is to the following register).
So, first of all, will the ADC be the slave or the master of this pairing?
I've now configured it as follows (only applicable part of code):
//Set inputs to digital IO
AD1PCFGH = 0xFFFF;
AD1PCFGL = 0xFFFF;
AD2PCFGL = 0xFFFF;
//------------------------ADC CONFIGURATION------------------------
SPI2_Init_Advanced(_SPI_MASTER, _SPI_8_BIT, _SPI_PRESCALE_SEC_4,_SPI_PRESCALE_PRI_1, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_END, _SPI_CLK_IDLE_LOW,_SPI_ACTIVE_2_IDLE);
ADC_CS = 0; //Define in code not shown
//note: these written bytes are defines not shown here
SPI2_Write(INIT_CTR_BYTE); //Control byte - start at phase address, writing
SPI2_Write(PHASE_BYTE); //PHASE No phase delay - only one channel
SPI2_Write(GAIN_BYTE); //GAIN, BOOST = 0
SPI2_Write(STAT_COMM); //Read GROUP, wait for settled data, DR high Z when data not ready
SPI2_Write(CONFIG1); //Pre 8, OSR 356, width 16, mod off,
SPI2_Write(CONFIG2); //RST 0, ch1 off, dith 0 on, ext Vref on, ext clk on
ADC_CS = 1; //Deselct ADC, to start with new control byte
//Channel read setup
ADC_CS = 0;
SPI2_Write(READSET_CTR_BYTE); //Set ADC register address to the stat/com register, writing
SPI2_Write(STAT_COMM_READ); //Set address loop to only loop on DATCH0 group
ADC_CS = 1;
//Start reading from ADC channel 0 after intial control byte
ADC_CS = 0;
SPI2_Write(READ_CTR_BYTE); //Start reading from channel 1
//------------------------ADC READ------------------------
for (count = 0; count <= 9; count++) {
data_out[count] = SPI2_Read(buffer);
}
ADC_cs = 1;
I'm still reading 0 though in the data_out array. I'm obviously doing something very wrong here... Any ideas?
I'm a bit stuck with this device and SPI in general. I've never used SPI before, though I've read as much literature as I can find.
I'm paring the MCP3901 (ADC) with a dsPIC33FJ256MC710 by using the 2nd SPI module on the chip. In addition, I'm using channel 0 on the MCP3901. I'm trying to do this with the built in SPI library routines (also, I'm not using interrupts).
Ok, so the first byte sent to the ADC is the control byte, laid out as follows:
First 2 bits - Device address bits
Next 5 bits - Internal register address bits
Last bit - Read/Write bit.
So for instance a control byte looking like 0b00010010 would be a control byte stating that the device address is 00, 01001 would be the stat/comm address, and 0 would indicate that the next byte sent would be written to that register (the stat/comm register that is). Thats my understanding of it, so far.
Thereafter, the next bytes written to the ADC would be to the registers as they appear in sequence (every time after you write to the device, the address shifts to that of the next register so that the next write is to the following register).
So, first of all, will the ADC be the slave or the master of this pairing?
I've now configured it as follows (only applicable part of code):
//Set inputs to digital IO
AD1PCFGH = 0xFFFF;
AD1PCFGL = 0xFFFF;
AD2PCFGL = 0xFFFF;
//------------------------ADC CONFIGURATION------------------------
SPI2_Init_Advanced(_SPI_MASTER, _SPI_8_BIT, _SPI_PRESCALE_SEC_4,_SPI_PRESCALE_PRI_1, _SPI_SS_DISABLE, _SPI_DATA_SAMPLE_END, _SPI_CLK_IDLE_LOW,_SPI_ACTIVE_2_IDLE);
ADC_CS = 0; //Define in code not shown
//note: these written bytes are defines not shown here
SPI2_Write(INIT_CTR_BYTE); //Control byte - start at phase address, writing
SPI2_Write(PHASE_BYTE); //PHASE No phase delay - only one channel
SPI2_Write(GAIN_BYTE); //GAIN, BOOST = 0
SPI2_Write(STAT_COMM); //Read GROUP, wait for settled data, DR high Z when data not ready
SPI2_Write(CONFIG1); //Pre 8, OSR 356, width 16, mod off,
SPI2_Write(CONFIG2); //RST 0, ch1 off, dith 0 on, ext Vref on, ext clk on
ADC_CS = 1; //Deselct ADC, to start with new control byte
//Channel read setup
ADC_CS = 0;
SPI2_Write(READSET_CTR_BYTE); //Set ADC register address to the stat/com register, writing
SPI2_Write(STAT_COMM_READ); //Set address loop to only loop on DATCH0 group
ADC_CS = 1;
//Start reading from ADC channel 0 after intial control byte
ADC_CS = 0;
SPI2_Write(READ_CTR_BYTE); //Start reading from channel 1
//------------------------ADC READ------------------------
for (count = 0; count <= 9; count++) {
data_out[count] = SPI2_Read(buffer);
}
ADC_cs = 1;
I'm still reading 0 though in the data_out array. I'm obviously doing something very wrong here... Any ideas?