Rpi SPI (Master) to Atmega1281 SPI (Slave) Communication Does not works.

Go To Last Post
6 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello,

I want to communicate Rpi SPI with Atmega1281 hardware SPI module. Rpi is Master configured and Atmega1281 slave. I want to read and write data from Rpi to Atmega1281. 

I am using following code on Rpi side.

// spi.c
//
// Example program for bcm2835 library
// Shows how to interface with SPI to transfer a byte to and from an SPI device
//
// After installing bcm2835, you can build this 
// with something like:
// gcc -o spi spi.c -l bcm2835
// sudo ./spi
//
// Or you can test it before installing with:
// gcc -o spi -I ../../src ../../src/bcm2835.c spi.c
// sudo ./spi
//
// Author: Mike McCauley
// Copyright (C) 2012 Mike McCauley
// $Id: RF22.h,v 1.21 2012/05/30 01:51:25 mikem Exp $

#include <bcm2835.h>
#include <stdio.h>

int main(int argc, char **argv)
{
    // If you call this, it will not actually access the GPIO
// Use for testing
//        bcm2835_set_debug(1);

    if (!bcm2835_init())
    {
      printf("bcm2835_init failed. Are you running as root??\n");
      return 1;
    }

    if (!bcm2835_spi_begin())
    {
      printf("bcm2835_spi_begin failed. Are you running as root??\n");
      return 1;
    }
    bcm2835_spi_setBitOrder(BCM2835_SPI_BIT_ORDER_MSBFIRST);      // The default
    bcm2835_spi_setDataMode(BCM2835_SPI_MODE0);                   // The default
    bcm2835_spi_setClockDivider(BCM2835_SPI_CLOCK_DIVIDER_65536); // The default
    bcm2835_spi_chipSelect(BCM2835_SPI_CS0);                      // The default
    bcm2835_spi_setChipSelectPolarity(BCM2835_SPI_CS0, LOW);      // the default
    
    // Send a byte to the slave and simultaneously read a byte back from the slave
    // If you tie MISO to MOSI, you should read back what was sent
    uint8_t send_data = 0x31;
    uint8_t read_data = bcm2835_spi_transfer(send_data);
    printf("Sent to SPI: 0x%02X. Read back from SPI: 0x%02X.\n", send_data, read_data);
    if (send_data != read_data)
      printf("Do you have the loopback from MOSI to MISO connected?\n");
    bcm2835_spi_end();
    bcm2835_close();
    return 0;
}

 

*The Rpi code works loopback *

 

 

And the below code is on Atmega1281 Hardware SPI module:

 

#include <stdio.h>
#include <stdlib.h>
#include <avr/io.h>
#include <util/delay.h>
#include "SPI.h"

void SPI_Init()
{
    char clear = 0;
    
    PRR0 = (1<<PRSPI);
    
    DDRB |= 0xF0;
    
    SPCR |= 0x00;                   // SPI slave Mode = 0
    
    DDRB |= (1<<DDB3);              // MISO as Output
    
    SPCR |= ((1<<SPE)|(1<<SPIE));   // Enable SPI and SPI Interrupt
    
    clear = SPDR;
    
    clear = SPSR;
    
    SREG |= (1<<SREG_I);        // Enable Global interrupt
}

void SPI_write(char val)
{
    char data = 0;
    
    SPDR = val;
    while(!(SPSR & (1<<SPIF)))
        ;
    data = SPDR;
}

char SPI_read()
{
    char value = 0;
    
    //SPDR = 0xff;
    
    while(!(SPSR & (1<<SPIF)))
        ;
    value = SPDR;
    
    return value;
}

void main()
{
while(1)
{
         value = SPI_read();
         SPI_write(value);
}
}



 

 

But i am not getting any data on Rpi side.. 

 

Any Help/

Rakesh 

 

 

Thanks
Rakesh Patel

Last Edited: Fri. Aug 7, 2020 - 05:35 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Please see Tip #1 in my signature, below, for how to properly post source code.

 

What testing / debugging / investigation have you done to find what's going on ?

 

Are you sure that your hardware connections are correct? Post your schematic (again, see Tip #1).

 

Are you sure that the RPi logic levels are compatible with your AVR ?

 

How have you proved that the RPi code is working on its own ? Does it work with a "standard" slave ?

 

How have you proved that the AVR code is working on its own ?

 

Have you used an oscilloscope or logic analyser to see what - if anything - is actually happening on the wires ?

 

etc, etc, ...

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thanks, 

 

 Yes Its working with arduino Due card as slave and i am getting data in Rpi using same code. 

 

 I think I need to improve the Atmega1281 Code. 

 

Any Help/

 

Rakesh

Thanks
Rakesh Patel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You enable the spi interrupt but there is no isr. Your code will crash. Do not set spie.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Thank Mate, 

 

It working now.. working code is as per below.: 

void SPI_Init()
{
    
    DDRB |= 0xF0;
    
    SPCR |= 0x00;                   // SPI slave Mode = 0
    
    DDRB |= (1<<DDB3);              // MISO as Output
    
    SPCR |= (1<<SPE);   // Enable SPI and SPI Interrupt
    
}

void SPI_write(char val)
{
        
    SPDR = val;
    while(!(SPSR & (1<<SPIF)));
    clear = SPDR;
}

char SPI_read()
{
    char value = 0;
    
    while(!(SPSR & (1<<SPIF)));
    
    value = SPDR;
    
    return value;
}

void main()
{
    SPI_Init();
    
    while(1)
    {
      value = SPI_read();  
      SPI_write(value);
    }
    
}

 

Thanks For your Support. 

 

Rakesh

 

Thanks
Rakesh Patel

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The below code works in Interrupt routine.. Rpi send receive the data using below slave code. 

void SPI_Init()
{
    
    DDRB &=~(1<<DDB0);          // CS as input
    
    DDRB &=~(1<<DDB1);          // SCK as input
    
    DDRB &=~(1<<DDB2);          // MOSI as input
    
    DDRB |= (1<<DDB3);          // MISO as output
    
    SPCR &=~(1<MSTR);           //SPI as slave
    
    SPCR |= (1<<SPIE);          // SPI Interrupt Enable.
    
    SPCR  |= (1<<SPE);          // SPI Enable
    
    sei();                      // Global Interrupt enable
  
}



ISR (SPI_STC_vect)
{
    SPIFalg = 1;
    
    retvalue = SPDR;
    
    SPDR = retvalue;
}


int  main() {
 
    SPI_Init();

    
    while(1)
    {
        if(retvalue == 0x87)
        {
            PORTF = 0x00;
        }
        else
        {
            PORTF = 0x02;
        }
       
    }

}

 

Thanks
Rakesh Patel

Last Edited: Fri. Aug 7, 2020 - 08:29 AM