I'm trying to get SPI communications working on a ATmega1284P. This is the code I'm using:
// clocked by external 12.000 MHz crystal, lfuse=0xce
#define F_CPU 12000000
#include <avr/io.h>
#define SPI_SCK PB7
#define SPI_MISO PB6
#define SPI_MOSI PB5
#define SPI_SS PB4
#define SPI_PORT PORTB
#define SPI_DDR DDRB
#define SPI_PIN PINB
//#include "spi.h"
//#include "serial.h"
void initUart()
{
#define BAUD 38400
#include <util/setbaud.h>
UBRR0H = UBRRH_VALUE;
UBRR0L = UBRRL_VALUE;
#if USE_2X
UCSR0A |= _BV(U2X0);
#else
UCSR0A &= ~_BV(U2X0);
#endif
UCSR0B |= (_BV(RXEN0) | _BV(TXEN0));
UCSR0C |= (_BV(UCSZ01) | _BV(UCSZ00));
}
void cOut(unsigned char c)
{
while (!(UCSR0A & _BV(UDRE0)))
;
UDR0 = c;
}
inline void spi_init()
{
// set MISO as input
SPI_DDR &= ~(_BV(SPI_MISO));
// set MOSI and SCK as output
SPI_DDR |= (_BV(SPI_SCK) | _BV(SPI_MOSI));
// enable SPI, master mode, and SPI prescaler
SPCR = (_BV(SPE) | _BV(MSTR) | _BV(SPR1) | _BV(SPR0));
// SPCR = (_BV(SPE) | _BV(MSTR));
}
unsigned char spi_transact(unsigned char c)
{
cOut('t');
// put byte to transmit into buffer
SPDR = c;
cOut('+');
// wait until the SPI timer has overflowed
while (!(SPSR & _BV(SPIF)))
;
cOut('T');
// return the byte transferred in via SPI
return SPDR;
}
int main()
{
// disable JTAG for full access to port C
// register unsigned char regTemp = MCUCR | _BV(JTD);
// MCUCR = regTemp;
// MCUCR = regTemp;
initUart();
SPI_DDR |= SPI_SS;
spi_init();
// sOut_P(CRLF);
cOut('\r');
cOut('\n');
// SPI_PORT |= SPI_SS;
cOut('1');
spi_transact(0xa0);
cOut('2');
spi_transact(0);
cOut('3');
spi_transact(0);
cOut('4');
spi_transact(0x12);
cOut('5');
spi_transact(3);
cOut('6');
spi_transact(1);
cOut('7');
spi_transact(1);
cOut('8');
spi_transact(0x13);
cOut('9');
// SPI_PORT &= ~SPI_SS;
// sOut_P(CRLF);
cOut('\r');
cOut('\n');
cOut('!');
// sOut("Clock reset\r\n");
}
I currently have nothing actually connected to the SPI pins yet, as I'm trying to see if I can get it working before I connect the SPI slave to it.
My terminal outputs "1t+T2t+" from the UART, showing a stall on waiting for SPIF to be set, but if I touch the end of a lead connected to SCK it does eventually get past that and completes the SPI session. Why would loading SCK externally make it work, when the clock is supposed to be generated by the master internally?
<util/setbaud.h>
was explicitly designed to work when included in the middle of code, even multiple times. \$\endgroup\$