Sincronización de comunicación SPI

Estoy tratando de transmitir datos desde un microcontrolador (frecuencia de reloj predeterminada ATMega8A) a otro microcontrolador (ATMega16 16MHz-crystal).

He configurado ATMega16 como maestro con

DDRB |= (1 << DDB7) | (1 << DDB5); //Set MOSI, SCK as Output
SPCR |= (1 << SPE) | (1 << MSTR) | (1<<SPIE) | (1 << SPR0);//Enable SPI, Set as Master

tengo una funcion de recibir

 unsigned char ReceiveData(unsigned char Data)
 {
     SPDR = Data;
     while(!(SPSR & (1<<SPIF) ));
     return(SPDR);
}

El SS'pin de ATMega8A (esclavo) está conectado PB3y en el bucle principal que tengo

for(;;)
{
    PORTB &= ~(1<<PB3); //clear SS' of slave
    Data = ReceiveData(0x05); //sending dummy 0x08 to slave;
    if(Data == 0x08)
        //TOGGLE(SOME_PORT,SOMEPINWITHLED); toggle #defined
    _delay_ms(200);
    PORTB |= (1<<PB3);
}

En el dispositivo esclavo que tengo

int main() // slave main module
{
     DDRB |= (1<<DDB4); //MISO as OUTPUT
     SPCR |= (1<<SPE); //Enable SPI
     DDRB |= (1<<DDB0);
     char Data = 2, SendValue = 8;
     for(;;)
     {
          TOGGLE(PORTB,PB0); // #define'd TOGGLE(A,B) A ^= (1<<B);

          Data = SendData(SendValue); // exact same as ReceiveData() on master.
     }
     return 0;
}              

El led no se enciende en el módulo maestro pero sí en el módulo esclavo. ¿Podría sugerirme qué he hecho mal aquí? Puede ser que el maestro y el esclavo no estén sincronizados.

  1. ¿Debería marcar `while(!(SPSR & (1 <<SPIF) ));` en el esclavo o `SPDR = Data; return (SPDR);` es suficiente en el esclavo.
  2. ¿Cómo sabe el maestro cuando el esclavo está enviando datos? Entonces, ¿cuándo debería maser verificar `while(!(SPSR & (1 <<SPIF) ));`?

PD: En el futuro planeo usar múltiples esclavos y un solo maestro.

Editar : corregí deDDRB |= (1 << DDB3) | (1 << DDB5);

Sugiera leer atmel.com/images/doc2585.pdf y consultar el código de ejemplo asociado
Gracias por el documento @vicatcu. Me pregunto si esto se debe a la diferencia de frecuencia de reloj de los dos Microcnotrollers.

Respuestas (1)

El único problema que puedo encontrar es la inicialización del puerto SPI en el Maestro, más el uso de ReceiveData.

En el Maestro, configura B3 y B5 como salidas. Pero de acuerdo con este documento para ATmega16, SS = PB4, MOSI = PB5, MISO = PB6 y SCK = PB7 y su SS es PB3. Entonces deberías tener:

DDRB |= (1 << DDB3) | (1 << DDB5) | (1 << DDB7);

Y según este documento para ATmega8, SS = PB2, MOSI = PB3, MISO = PB4 y SCK = PB5. Deberías tener configurado PB4 como salida para MISO, y lo tienes.

No estoy seguro de para qué estás usando PB0, si es para sincronizar los dos procesadores, no es necesario.

Su método de envío y recepción de datos en ReceiveData es correcto y debe usarse tanto para el Maestro como para el Esclavo (de la transmisión anterior).

Recuerde que cada vez que envía un byte, obtiene un byte de vuelta del otro extremo.

Me di cuenta de que los bits que configuré alto DDRBestán mal, gracias por señalarlo. Lo corregí.