I work with atmega16, in both side master and slave. I want to send a number between 100-999 that entered by keypad to the slave. Numbers are 16 bit, but spdr register is 8 bit, so I send first lsb then msb bits. This works well and I send my number correctly.
But my problem is in slave side: I enabled interrupt spie in slave side so each spdr received from master took as a interrupt and goes to ISR function. But because of my number is 16 bit, I want to take each 16 bit or two byte as a interrupt. What should i do?
You know your message length (16 bit or 2 byte). Just create a ring buffer to store two bytes and fill the ring buffer. Maybe you can add a third byte as start or end byte or something else but this is up to you. Additional you set a flag if your transmission ends.
So your code can look like this. Note this code is only the ISR and for an XMega as SPI slave but it should help to understand the procedure.
#define SPI_BUFFER_SIZE 2
uint8_t SPI_RxSlaveBuffer[SPI_BUFFER_SIZE];
typedef struct
{
uint8_t* RxBuffer;
uint8_t BytesProcessed;
uint8_t Status;
} SPI_Buffer_t;
static SPI_Buffer_t SlaveBuffer;
int main()
{
// Some code
SlaveBuffer.RxBuffer = SPI_RxSlaveBuffer;
// Some other code
}
ISR(SPIC_INT_vect)
{
SlaveBuffer.RxBuffer[SlaveBuffer.BytesProcessed++] = SPIC.DATA;
if(SlaveBuffer.BytesProcessed >= SPI_BUFFER_SIZE - 1)
{
SlaveBuffer.BytesProcessed = 0x00;
SlaveBuffer.Status = 0x01;
}
}
You can also check the state of the SS
pin and reset the counter if the pin is asserted by the master (in case that the master has aborted the transmission or something else) - for example with polling the SS
pin or wiring the signal of the SS
pin to an interrupt pin to generate an additional I/O interrupt.