2
\$\begingroup\$

I am trying to get SPI working on an ATmega328. This is my code:

#include <avr/io.h>
#include <util/delay.h>
#include <avr/interrupt.h>
#define ACK 0x7E
#define LONG_TIME 10000
//Initialize SPI Master Device
void spi_init_master (void)
{
 DDRB = (1<<PORTB5)|(1<<PORTB3); //Set MOSI, SCK as Output
 SPCR = (1<<SPE)|(1<<MSTR); //Enable SPI, Set as Master
}
//Function to send and receive data
unsigned char spi_tranceiver (unsigned char data)
{
 PORTC = 1<<PORTC2;
 PORTC = 0<<PORTC2;
 SPDR = data; //Load data into the buffer
 while(!(SPSR)&(1<<SPIF));
 return(SPDR); //Return received data
}
//Main
int main(void)
{
 DDRC= 0XFF; 
 spi_init_master();
 spi_tranceiver(6); 
 //spi_tranceiver(6);
 //spi_tranceiver(6); 
}

This is the output from the logic analyzer:

enter image description here

Notice those two comment lines. spi_tranceiver(6); If I remove those comments, I should get, from the logic analyzer:

  • 3 times the amount of clock pulses for the blue layer.
  • 3 times the amount of data sent, and;
  • 3 times the amount of PORTC2 pules.

This is not the case. I get the below:

enter image description here

The device I am trying to SPI with isn't configured correctly. Does this matter?

JYelton
35.7k34 gold badges149 silver badges281 bronze badges
asked Oct 5, 2014 at 6:41
\$\endgroup\$

1 Answer 1

4
\$\begingroup\$

It looks like you have the parantheses in the wrong spot while waiting for the SPI transaction to complete. Because the ! operator has a higher precedence than & it will be trying to do a bitwise not of the SPSR register first. Instead you want something like this:

while (!(SPSR & (1<<SPIF)))
 ;

At the moment presumably that wait is returning immediately so the SPDR register is getting set three times in rapid succession without enough time for the data to be transferred.

answered Oct 5, 2014 at 6:51
\$\endgroup\$
2
  • \$\begingroup\$ many thanks! I have spent many many hours on this! \$\endgroup\$ Commented Oct 5, 2014 at 6:55
  • \$\begingroup\$ Also, assuming that PORTC2 is the SS/CS line, that should be held low for the entirety of your SPI 'transaction', and should be taken out of your spi_tranceiver function and moved to somewhere surrounding that. \$\endgroup\$ Commented Oct 5, 2014 at 16:53

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.