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
atmega2560 - LTC2440 SPI communication...need help troubleshooting
Started by ●April 13, 2012
Reply by ●April 13, 20122012-04-13
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.comJust 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.