Estoy intentando que las comunicaciones SPI funcionen en un ATmega1284P. Este es el código que estoy usando:
// 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");
}
Actualmente no tengo nada conectado realmente a los pines SPI, ya que estoy intentando ver si puedo hacerlo funcionar antes de conectarlo con el esclavo SPI.
Mi terminal emite "1t + T2t +" desde el UART, mostrando un bloqueo al esperar a que se establezca SPIF, pero si toco el final de un cable conectado a SCK, eventualmente pasa eso y completa la sesión SPI. ¿Por qué cargar SCK externamente hace que funcione, cuando se supone que el maestro genera internamente el reloj?