EmbeddedRelated.com
Forums

atmega2560 - LTC2440 SPI communication...need help troubleshooting

Started by icabod8 April 13, 2012
New guy here trying to talk to an AD board via SPI. Was hoping someone
might help me troubleshoot.

I have an ATmega2560 attached to a STK600 development board.  I'm trying to
get data off of a LTC2440cgn AD board. But all I get out is 0...

The AD board is 24 bit resolution, but produces a 32 bit value with the
data being in bits 5-28... so I figure first I need to read in 4 bytes from
the AD via SPI.  Then I combine 4 those four bytes into one and peel off
the data bits.  Then I send the 8 most significant bits to LEDs to see if
I'm getting anything.

Here is my function to initialize the SPI...


void InitSPI(void)
{
	//SPI is done through PORTB.  SS is pin0, SCK is pin1, MOSI is pin2
	DDRB = (1<<PB2)|(1<<PB1) | (1<<PB0); //Set MOSI, SCK, and SS output
	
	//SPCR: SP Control Register...
	SPCR = ( (1<<SPE)|(1<<MSTR) | (1<<SPR1) |(1<<SPR0));	// Enable SPI,
Master, set clock rate fck/128  
}


Here is my function to read 1 byte from the SPI...


uint8_t ReadByteSPI()
{
        //writing data to the SPI data register to initiate transaction
	SPDR = 0xFF;		//Load dummy byte to SPI Data register
	
	while(!(SPSR & (1<<SPIF))); 	// Wait for transmission complete 
	return SPDR;        //data register should now contain data from AD?
}


Here is my function to read in 4 bytes, and combine them and pull out the
data portion...


uint32_t ReadADCspi(){
	//the LTC2440 transmits a 32 bit value
	//so read 4 bytes into memory and construct it
	
        //SELECT_ADC is defined as PORTB &= ~(1<<PB0)
        //DESELECT_ADC is defined as PORTB |= (1<<PB0)

	SELECT_ADC;	
	uint8_t a = ReadByteSPI();
	_delay_us(100);      //delay for next reading...do I need this?
	uint8_t b = ReadByteSPI();
	_delay_us(100);
	uint8_t c = ReadByteSPI();
	_delay_us(100);
	uint8_t d = ReadByteSPI();
	DESELECT_ADC;
	
	uint32_t result = 0;
	result = ((((((result | a) << 8) | b) << 8) | c) << 8) | d;
	
	//ADC_MASK is 0b00011111111111111111111111100000
	return (result & ADC_MASK)>>5;		//data bits are 5-28
	
}


Finally, this is the main loop that calls ReadADCspi.  I send the 8 most
significant bits to LEDs to give me some indication if I'm getting any data
out.  Right now the AD board is connected to a voltage source that I can
vary from 0-5 V. I would expect the LEDs to turn off and on based on the
voltage I'm sending, but they're only showing 0s.



InitSPI();
	
uint32_t output = 0;
	
//set up LEDs for test
DDRC  = 0xFF; //sets PORTC for output
PORTC = 0b11111111; 
	
while(1){
	output = ReadADCspi();
	PORTC = output>>16; //A# send the highest 8bits to LEDs to test output
	_delay_ms(200);		//delay to watch output
	PORTC = ~0;	//B# turn LEDs off briefly so I know Loop is executing
	_delay_ms(100);
}


At this point I'm pretty stuck.  I know the loop is running because the
LEDs flash off at the line marked B).  They ALL turn on at line A) (ie.
PORTC is all 0s which means output is zero always...) 

	   
					
---------------------------------------		
Posted through http://www.EmbeddedRelated.com
On Apr 13, 12:24=A0pm, "icabod8" <jwebster8@n_o_s_p_a_m.gmail.com>
wrote:
> New guy here trying to talk to an AD board via SPI. Was hoping someone > might help me troubleshoot. > > I have an ATmega2560 attached to a STK600 development board. =A0I'm tryin=
g to
> get data off of a LTC2440cgn AD board. But all I get out is 0... > > The AD board is 24 bit resolution, but produces a 32 bit value with the > data being in bits 5-28... so I figure first I need to read in 4 bytes fr=
om
> the AD via SPI. =A0Then I combine 4 those four bytes into one and peel of=
f
> the data bits. =A0Then I send the 8 most significant bits to LEDs to see =
if
> I'm getting anything. > > Here is my function to initialize the SPI... > > void InitSPI(void) > { > =A0 =A0 =A0 =A0 //SPI is done through PORTB. =A0SS is pin0, SCK is pin1, =
MOSI is pin2
> =A0 =A0 =A0 =A0 DDRB =3D (1<<PB2)|(1<<PB1) | (1<<PB0); //Set MOSI, SCK, a=
nd SS output
> > =A0 =A0 =A0 =A0 //SPCR: SP Control Register... > =A0 =A0 =A0 =A0 SPCR =3D ( (1<<SPE)|(1<<MSTR) | (1<<SPR1) |(1<<SPR0)); =
=A0 =A0// Enable SPI,
> Master, set clock rate fck/128 > > } > > Here is my function to read 1 byte from the SPI... > > uint8_t ReadByteSPI() > { > =A0 =A0 =A0 =A0 //writing data to the SPI data register to initiate trans=
action
> =A0 =A0 =A0 =A0 SPDR =3D 0xFF; =A0 =A0 =A0 =A0 =A0 =A0//Load dummy byte t=
o SPI Data register
> > =A0 =A0 =A0 =A0 while(!(SPSR & (1<<SPIF))); =A0 // Wait for transmission =
complete
> =A0 =A0 =A0 =A0 return SPDR; =A0 =A0 =A0 =A0//data register should now co=
ntain data from AD?
> > } > > Here is my function to read in 4 bytes, and combine them and pull out the > data portion... > > uint32_t ReadADCspi(){ > =A0 =A0 =A0 =A0 //the LTC2440 transmits a 32 bit value > =A0 =A0 =A0 =A0 //so read 4 bytes into memory and construct it > > =A0 =A0 =A0 =A0 //SELECT_ADC is defined as PORTB &=3D ~(1<<PB0) > =A0 =A0 =A0 =A0 //DESELECT_ADC is defined as PORTB |=3D (1<<PB0) > > =A0 =A0 =A0 =A0 SELECT_ADC; > =A0 =A0 =A0 =A0 uint8_t a =3D ReadByteSPI(); > =A0 =A0 =A0 =A0 _delay_us(100); =A0 =A0 =A0//delay for next reading...do =
I need this?
> =A0 =A0 =A0 =A0 uint8_t b =3D ReadByteSPI(); > =A0 =A0 =A0 =A0 _delay_us(100); > =A0 =A0 =A0 =A0 uint8_t c =3D ReadByteSPI(); > =A0 =A0 =A0 =A0 _delay_us(100); > =A0 =A0 =A0 =A0 uint8_t d =3D ReadByteSPI(); > =A0 =A0 =A0 =A0 DESELECT_ADC; > > =A0 =A0 =A0 =A0 uint32_t result =3D 0; > =A0 =A0 =A0 =A0 result =3D ((((((result | a) << 8) | b) << 8) | c) << 8) =
| d;
> > =A0 =A0 =A0 =A0 //ADC_MASK is 0b00011111111111111111111111100000 > =A0 =A0 =A0 =A0 return (result & ADC_MASK)>>5; =A0 =A0 =A0 =A0 =A0 =A0 =
=A0 =A0//data bits are 5-28
> > } > > Finally, this is the main loop that calls ReadADCspi. =A0I send the 8 mos=
t
> significant bits to LEDs to give me some indication if I'm getting any da=
ta
> out. =A0Right now the AD board is connected to a voltage source that I ca=
n
> vary from 0-5 V. I would expect the LEDs to turn off and on based on the > voltage I'm sending, but they're only showing 0s. > > InitSPI(); > > uint32_t output =3D 0; > > //set up LEDs for test > DDRC =A0=3D 0xFF; //sets PORTC for output > PORTC =3D 0b11111111; > > while(1){ > =A0 =A0 =A0 =A0 output =3D ReadADCspi(); > =A0 =A0 =A0 =A0 PORTC =3D output>>16; //A# send the highest 8bits to LEDs=
to test output
> =A0 =A0 =A0 =A0 _delay_ms(200); =A0 =A0 =A0 =A0 //delay to watch output > =A0 =A0 =A0 =A0 PORTC =3D ~0; =A0 =A0 //B# turn LEDs off briefly so I kno=
w Loop is executing
> =A0 =A0 =A0 =A0 _delay_ms(100); > > } > > At this point I'm pretty stuck. =A0I know the loop is running because the > LEDs flash off at the line marked B). =A0They ALL turn on at line A) (ie. > PORTC is all 0s which means output is zero always...) > > --------------------------------------- > Posted throughhttp://www.EmbeddedRelated.com
Just one thing i can think of, but might not be the problem. SS is not automatic in SPI master mode. Might want to add PORTB |=3D (1<<SS) to be sure.