I'm having some issues trying to get SPI working with an ATmega328p. From what I understand from the datasheet, the SPIF flag is set when an SPI transfer is complete, and then is cleared when the SPI status register (SPSR) is first read, and then the SPI data register (SPDR) is read; however what seems to be happening is that I transfer the data, but the transmit flag is never being set. I have a while loop that waits for the flag to be set, but the microcontroller never leaves the loop for some reason.
void spi_init(void) // SPI initialization function.
{
DDRB &=~ (1 << DDB4); // Ensure that the MISO pin is configured as in input
DDRB |= (1 << DDB3); // Configure the MOSI pin as an output
DDRB |= (1 << DDB5); // Configure the SCK pin as an output
DDRD |= (1 << DDD6); // TX Slave Select (CSN) // I have two modules that I am communicating with over SPI. the first I have named TX and the second RX. Unrelated to the problem, but just for references sake.
PORTD |= (1 << PORTD6); // Default the TX slave select pin to be idle high as it is active low
DDRB |= (1 << DDB0); // RX Slave Select (CSN)
PORTB |= (1 << PORTB0); // Default the RX slave select pin to be idle high as it is active low
//SPCR |= (1 << SPIE); // Enable the interrupt
SPCR |= (1 << SPE); // Enable the SPI
SPCR &=~ (1 << DORD); // Transmit the data MSB first
SPCR |= (1 << MSTR); // Configure the SPI as Master
SPCR &=~ (1 << CPOL); // Idle the clock line (SCK) at logic low
SPCR &=~ (1 << CPHA); // Set the clock phase so that data is sampled on the leading edge, and setup on the trailing edge
}
uint8_t spi_transfer(uint8_t transfer_data) // SPI transfer function
{
SPDR = transfer_data; // Write the data to be transfered into the SPI data register which will instantiate the trasfer
while(!(SPSR & (1 << SPIF))); // Wait until the transfer has complete <-- where the problem seems to be
return SPDR; // Return the data returned from the slave
}
When I call the transfer function, I first pull the specific slave select pin low, and then call the transfer function. After the transfer has complete, I pull the slave select pin back high. But what I am seeing is that the slave select pin is stuck low. It never gets pulled high. I have narrowed it down to the loop which waits for the interrupt flag to be set, as if I remove the loop, the transfer goes through (unsuccessfully I might add, but that's a separate issue I haven't pinpointed yet).