SPI slave to master comunicating

hi

I am testing SPI interface for use with the Rf 24g. I am now testing SPI comunication between a atmega8(slave) and a atmega 16 (master) the problem i am having is sending data from slave to master. I am geting data from a ADC, and when I turn the mcu’s on it recives the data once, and no more. I want it to send/recive every 0.5 seconds.

I have no problem with the master to slave comunication.

The principle is that the slave reads the ADC and puts the result in SPDR register, it is then sendt, and when the entire byte is clocked into the Master the SPI innterupt occurs and puts the recived byte into “DATA” and prints it for me to see.

here is the code:

MASTER:

#include <mega16.h>    
#include <stdio.h>
#include <delay.h>


// SPI isr
interrupt [SPI_STC] void spi_isr(void)
{
unsigned char data; 

 data = SPDR ;   
 printf ("\n\r%d", data ) ;
           
}


void main(void)
{

// Port B initialization
PORTB=0x00;
DDRB=0xB0;


UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x33;

// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 2000,000 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0xD1;
SPSR=0x00;

// Clear the SPI interrupt flag
#asm
    in   r30,spsr
    in   r30,spdr
#endasm

// Global enable interrupts
#asm("sei")              

SPDR = 0x00 ;


while (1)
      {
           

      };
}

SLAVE:

#include <mega8.h> 
#include <stdio.h>
#include <delay.h>
                     

#define ADC_VREF_TYPE 0x60

unsigned char read_adc(unsigned char adc_input)
{
ADMUX=adc_input|ADC_VREF_TYPE;
// Start the AD conversion
ADCSRA|=0x40;
// Wait for the AD conversion to complete
while ((ADCSRA & 0x10)==0);
ADCSRA|=0x10;
return ADCH;
}
 

// SPI isr
interrupt [SPI_STC] void spi_isr(void)
{

}

void main(void)
{


// Input/Output Ports initialization
// Port B initialization
PORTB=0x00;
DDRB=0x10;

// USART initialization
UCSRA=0x00;
UCSRB=0x18;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0x33;

// SPI initialization
// SPI Type: Slave
// SPI Clock Rate: 2000,000 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First
SPCR=0xC0;
SPSR=0x00;

// Clear the SPI interrupt flag
#asm
    in   r30,spsr
    in   r30,spdr
#endasm

// Global enable interrupts
#asm("sei")
                   

// ADC Clock frequency: 62,500 kHz
// ADC Voltage Reference: AVCC pin
// 8-bit
ADMUX=ADC_VREF_TYPE;
ADCSRA=0x87;
              

while (1)
      {                
      read_adc(0x01);                   

      printf ("\n\r%d", ADCH ) ;         //printing for debug
      
      SPDR = ADCH ;
      
      delay_ms (500) ;
      };
}

The master must send in order to get something from the slave. It is after all the master that provides the clock signal. A slave device will often have a “data ready” or similar pin to arrange for this (i.e. the master knows it can l clock out data when this signal is active).

The rf24g is a good exampe. This is code for getting data out of the rf24g:

bool trf24gReceive(void *p) 
{    
   uint8_t dr = TRF24G_DR1_PIN & TRF24G_DR1_MASK; 
   if (dr) { 
      uint8_t n = TRF24G_PAYLOAD_SIZE; 
      uint8_t *buf = (uint8_t*)p; 
      do { 
         *buf++ = spiSend(0); 
      } while(--n); 
   } 
   return dr; 
}

Notice the spiSend(0), the 0 is a dummy value sent in order to receive data from the rf24g.

/Lars

thanks, now i recive data every .5 second, but I recive 0.

my new master code is:

// SPI interrupt service routine
interrupt [SPI_STC] void spi_isr(void)
{
unsigned char data; 

 data = SPDR ;   
 printf ("\n\r%d", data ) ;
                
 SPDR = 0x00 ; 
  
}

when I alter “SPDR = 0x00” to “SPDR = 0x01” I recive 1 instead of 0 so i recive the same data that I sendt…strange.

Lajon : what is the “uint8_t” ?

thanks, now i recive data every .5 second, but I recive 0.

But do you only recive 0? It is not unexpected that a lot of what you receive will be junk becuse the slave only puts something useful in SPDR every 0.5s while the master is reading data all the time (only limited by the time it takes to do the printf).

Lajon : what is the “uint8_t” ?

It is a C standard integer type from , same as unsigned char.

/Lars

it seams to bee working now, just put in a delay for the master.

great, now that the SPI is up and running I just need to write some sensible code to make it work with the RF24g:)

saw your code lars, looks great, but i am trying to make my own so maby i learn something:)

thank you very much for the help, if you ever take a trip over the border to norway ill buy you a beer :wink: