Simple SPI application not working !!

Hello,

I’m trying to perform the basic and simple SPI communication between two Arduino boards.

  1. Master: Uno board.
  2. Slave: Nano board.

Application: to send data from Master to blink LED on slave.
Problem: while loop in TX function running forever.

Master:

/* uno board is the Master and transmit 
   data to slave to blink LEDs */

void SPI_Init(void);
void SPI_TX(uint8_t data);

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);//start Serial
  Serial.println("Setting Up");
  void SPI_Init();
  delay(100);
  Serial.println("SPI intialization is complete");
}

void loop() {
PORTB = (0<<PB2); // Pull SS pin low
uint8_t d=0x02;
SPI_TX(d);
  Serial.println("just sent the 1st byte");
_delay_ms(400);
d=00;
SPI_TX(d);
  Serial.println("just sent the 2nd byte");
_delay_ms(400);
}

void SPI_Init(void)
{
DDRB = (1<<DDB3)|(1<<DDB1)|(1<<DDB2); // DDB3 MOSI, DDB1 SCK, DDB2 SS
SPCR = (1<<SPE)|(1<<MSTR)|(1<<SPR0);  // SPI enable, Master Mode, Fosc/16
}

void SPI_TX(uint8_t data)
{
SPDR = data;
while(!(SPSR & (1<<SPIF)));
}

Slave:

void SPI_Init_S(void);
void SPI_RX(void);

void setup() {
// put your setup code here, to run once:
Serial.begin(9600);//start Serial
Serial.println("Setting Up");
SPI_Init_S();
delay(100);  
Serial.println("SPI intialization is complete");
DDRB=(1<<DDB1); // output for blink LED
}

void loop() {
  // put your main code here, to run repeatedly:
  SPI_RX();
  PORTB=SPDR;     // blink on pin PB1
  _delay_ms(500);
  SPI_RX();
  PORTB=SPDR;     // blink off pin PB1
  _delay_ms(500);
}

void SPI_Init_S(void)
{
  SPCR = (1<<SPE)|(1<<SPR0);
}

void SPI_RX(void)
{
  return SPDR;
}
PORTB = (0<<PB2); // Pull SS pin low

This will pull ALL of PORTB low. That might be a problem.

Try:

PORTB &= ~(1<<PB2); // Pull SS pin low

But why are you fiddling with port manipulation anyway?

I would suggest to take a look at SPI.h .
It is relatively well documented - especially the tx / rx part
Good luck.
Jim

johnwasser:

PORTB = (0<<PB2); // Pull SS pin low

This will pull ALL of PORTB low. That might be a problem.

Try:

PORTB &= ~(1<<PB2); // Pull SS pin low

Well, PORTB = (0<<PB2); and PORTB = 0x04; are the same and they only take effect of that particular bit.

Actually, I’m doing testing on blinking the onboard LED.

Your bitwise technique didn’t work and stopped the blink. The two simple bitwise techniques are working fine :slight_smile:

septillion:
But why are you fiddling with port manipulation anyway?

Simple and quick effect. I would look for other applications like shift registers and other SPI modules, now I want to test my basic SPI technique. Which obviously is not working.

julyjim:
I would suggest to take a look at SPI.h .
It is relatively well documented - especially the tx / rx part
Good luck.
Jim

Yeah, that would be fine.

Any further suggestions are welcome.

Watch for code which " modifies" the SPI clock. You may find it does not - one user claims his app runs the SPI at 85 MHz, but this SPI.h code sets it to "standard / default " " 4 MHz, Not a big issue.
I am not sure if this is normal SPI handshake or it is generated by the slave device itself,
but when I send a command to slave (LCD) it responds with 0xFF.
Nice to know the SPI path is working.
Another minor way to check is to read the status register after you read the SDR.
I find the core SPI harder to navigate due to too may #ifdef #esle flags.
I guess that is th price for having "universal " core resources.
Jim

wolfrose:
Well, PORTB = (0<<PB2); and PORTB = 0x04; are the same and they only take effect of that particular bit.

No, they are not the same. No amount of good advice is any use if not listened to.

wolfrose:
Well, PORTB = (0<<PB2); and PORTB = 0x04; are the same and they only take effect of that particular bit.

You are wrong about that. PORTB = 0x04 will set all bits of PORTB low except for bit 2 which will be set HIGH. On the UNO, this means pins 8-13 will be set low except for pin 10, which will be set high.

julyjim:
Watch for code which " modifies" the SPI clock. You may find it does not - one user claims his app runs the SPI at 85 MHz, but this SPI.h code sets it to "standard / default " " 4 MHz, Not a big issue.
I am not sure if this is normal SPI handshake or it is generated by the slave device itself,
but when I send a command to slave (LCD) it responds with 0xFF.
Nice to know the SPI path is working.
Another minor way to check is to read the status register after you read the SDR.
I find the core SPI harder to navigate due to too may #ifdef #esle flags.
I guess that is th price for having "universal " core resources.
Jim

I didn't understand your answer and how it relates to my post.

MarkT:
No, they are not the same. No amount of good advice is any use if not listened to.

OK my friend I tested my idea practically and what he suggested to me. And I got the results and posted them in this thread. So what do you mean by your reply, I didn't get it?

PaulMurrayCbr:
You are wrong about that. PORTB = 0x04 will set all bits of PORTB low except for bit 2 which will be set HIGH. On the UNO, this means pins 8-13 will be set low except for pin 10, which will be set high.

Yes, that's what I want. If I wanted any other bits to be high then I would include those bits in PORTB value. Now I only want the 3rd bit of PORTB to be high

Yeah, but do you want all the other bit's to be low?

For example, doing

PORTB = 0x04;
PORTB = 0x08;
[code]
Will leave you with only pin 11 high, pin 10 will be low. So changing the whole port when you only want to set the state of one pin can give you trouble.

B[quote author=wolfrose link=msg=2951526 date=1475851564]
Simple and quick effect. I would look for other applications like shift registers and other SPI modules, now I want to test my basic SPI technique. Which obviously is not working.
[/quote]
It might be simple and quick but it is full of pit falls. That's why Arduino uses the whole wiring layer on top. That makes it even simpler to program and on top of that generates portable code. So just stick to that I would say
[code]
digitalWrite(SS, LOW);

septillion:
Yeah, but do you want all the other bit’s to be low?

For example, doing

PORTB = 0x04;

PORTB = 0x08;

[code]
Will leave you with only pin 11 high, pin 10 will be low. So changing the whole port when you only want to set the state of one pin can give you trouble.

BIt might be simple and quick but it is full of pit falls. That’s why Arduino uses the whole wiring layer on top. That makes it even simpler to program and on top of that generates portable code. So just stick to that I would say

[code]
digitalWrite(SS, LOW);

It’s OK I can apply the OR bitwise operator. I was testing them now. When you don’t apply the OR operator, then the port LEDs go at lower brightness with the fast looping means the bits go off and on very fast.

After I applied the OR operator, they are OK.

So, PORTB |= (1<<any bit); should be OK :slight_smile:

wolfrose:
I didn't understand your answer and how it relates to my post.

You asked for any other advise etc.
I guess you really do not need my experience with SPI , sorry.
Jim

OK my friend I tested my idea practically and what he suggested to me. And I got the results and posted them in this thread. So what do you mean by your reply, I didn't get it?

Yes, that's what I want. If I wanted any other bits to be high then I would include those bits in PORTB value. Now I only want the 3rd bit of PORTB to be high

johnwasser:

PORTB = (0<<PB2); // Pull SS pin low

This will pull ALL of PORTB low. That might be a problem.

Try:

PORTB &= ~(1<<PB2); // Pull SS pin low

OK my friend got your point !!

This technique worked for turning off or pulling down specific bit without effecting the other bits.

For setting high or pulling specific bit high I should go with the ORed techniques.

Thank you,

MarkT:
No, they are not the same. No amount of good advice is any use if not listened to.

Yes took me time to understand thank you,

johnwasser:

PORTB = (0<<PB2); // Pull SS pin low

This will pull ALL of PORTB low. That might be a problem.

Try:

PORTB &= ~(1<<PB2); // Pull SS pin low

Like this one too:

if (bitOrder == LSBFIRST) SPCR |= _BV(DORD);
    else SPCR &= ~(_BV(DORD));

Got your idea thank you :slight_smile: