I am trying to communicate between two ATmega using SPI. First, I initialized SPI for both ATmega. Here ATmega8 is master and ATmega32 is slave.
MASTER
Master initialization - ATMEGA8:
#define SPI_ddr DDRB
#define SPI_port PORTB
#define PIN_sck 5
#define PIN_mosi 3
#define PIN_ss 2
#define PIN_miso 4
#define SPI_PORT_enable() (SPI_ddr |= (1 << PIN_sck) | (1 << PIN_mosi) | (1 << PIN_ss))
#define CS_High SPI_port |= (1 << PIN_ss);
#define CS_Low SPI_port &= ~(1 << PIN_ss);
void SPI_Init()
{
SPI_PORT_enable();
SPI_ddr &= ~(1 << PIN_miso);
SPCR |= (1 << MSTR) | (1 << SPR0) | (1 << SPR1) | (1 <<SPE);
}
Functions to send data from master - ATMEGA8:
void send_char_SPI(char c)
{
SPDR = c;
/* Wait for transmission complete */
while(!(SPSR & (1 << SPIF)));
}
void send_string_SPI(char s[])
{
int i = 0;
while (s[i] != 0x00)
{
send_char_SPI(s[i]);
i++;
}
}
so now I have two strings which I want to send to slave one by one.
char freq_array[] = {0x01, '5', '0', '.', '0', '0', '\r'};
char volt_array[] = {0x02, '2', '9', '1', '.', '4', '\r'};
Main of master- ATMEGA8:
int main(void)
{
SPI_Init();
while (1)
{
CS_Low;
_delay_ms(10);
send_string_SPI(volt_array);
CS_High;
_delay_ms(1000);
CS_Low;
_delay_ms(10);
send_string_SPI(freq_array);
CS_High;
_delay_ms(1000);
}
}
Here is the main problem while I send only one array through SPI to slave I can get the data perfectly on slave side and further transmit it to the terminal via UART. But while I send both of the arrays, I don't receive both arrays perfectly. I rather receive one array most of the time and the other array sometimes. I want that the salve receives the array one by one. First, it will receive the first array and then again it should receive the next array. and should transmit it to UART simultaneously.
SLAVE
Slave initialization - ATMEGA32:
Here ATmega32 is receiving data using Interrupt
#define SPI_ddr DDRB
#define SPI_port PORTB
#define PIN_sck 7
#define PIN_mosi 5
#define PIN_ss 4
#define PIN_miso 6
#define SPI_PORT_enable() (SPI_ddr &= ~((1 << PIN_sck) | (1 << PIN_mosi) | (1 << PIN_ss)) )
void SPI_Init()
{
SPI_PORT_enable();
SPI_ddr |= (1 << PIN_miso);
SPCR &= ~(1 << MSTR);
SPCR |= (1<<SPR0)|(1<<SPR1); // divide clock by 128
SPCR |= (1<<SPE); // Enable SPI
SPCR |= (1<<SPIE);
}
ISR of slave- ATMEGA32:
Here I am checking for \r
as every string i am sending from master ends with \r
. So if I get \r
I will set spi_data_recieved
variable so that I can process it in main
(i.e can send the received data to the terminal via UART).
ISR(SPI_STC_vect)
{
data_array[data_index] = SPDR;
if(data_array[data_index] == '\r')
spi_data_recieved = 1;
if (data_index > 10)
{
data_index = 0;
Clear_Buffer(data_array, 10);
}
else
{
data_index++;
}
}
UART functions on slave - ATMEGA32:
void Serial_Init(unsigned int baud)
{
UBRRH = (unsigned char)(baud >> 8);
UBRRL = (unsigned char)baud;
UCSRB = (1 << RXEN) | (1 << TXEN) ;
UCSRC = (1 << URSEL) | (3 << UCSZ0);
}
void Serial_Transmit(unsigned char data)
{
UDR = data;
while ( !( UCSRA & (1 << UDRE) ) );
}
void Serial_Transmit_String(unsigned char *string)
{
while (*string != 0)
Serial_Transmit(*string++);
}
Main of slave - ATMEGA32:
int main(void)
{
SPI_Init();
Serial_Init(103);
data_index = 0;
spi_data_recieved = 0;
sei();
Serial_Transmit_String((unsigned char*)"TESTING SPI\r\n");
unsigned char copyBuff[10];
while (1)
{
if (spi_data_recieved == 1)
{
spi_data_recieved = 0;
strcpy((char*)copyBuff, (char*)data_array);
Clear_Buffer(data_array, 10);
data_index = 0;
switch(copyBuff[0])
{
case 0x01: Serial_Transmit_String((unsigned char*)"Frequency: "); break;
case 0x02: Serial_Transmit_String((unsigned char*)"Bus Voltage: "); break;
default: Serial_Transmit_String((unsigned char*)"SPI Data: "); break;
}
Serial_Transmit_String(copyBuff);
}
_delay_ms(10);
}
}
Expected output for this setup is:
Bus Voltage: 291.4 Frequency: 50.00 Bus Voltage: 291.4 Frequency: 50.00
and continuous in this manner
Getting the output as:
SPI Data: 0 Frequency: 50.00 SPI Data: 0 Frequency: 50.00 SPI Data: 0 Frequency: 50.00
And in very rare case I could see the bus voltage.
I figured out there is some synchronization issue between the ATmega's but I don't know how to solve this problem.