AVR & SPI w/ DS1306 RTC

Go To Last Post
3 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I was having some issues trying to communicate with DS1306. I managed to get the communication working (am able to both read and write), but there's still something that's puzzled me. Below is the code. In the ioinit() method, I set the SPI port to master and enable it. Then in the beginning of the main function (should be executed right after ioinit), I have to read the SPCR register and reinit the SPCR register. If I remove either of these lines, it will hang on the first SPI transaction. Any idea why those extra lines are needed? Or is there something else or a cleaner way I should be doing the init?

static void ioinit(void)
{
	// Set SPI port to master, sample on falling edge and enable it
	SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPHA);

	// Set SCK, CS, MOSI and RTC_CS as output
	DDRB = (1<<RTC_SDO) | (1<<RTC_SCK) | (1<<RTC_CS) | (1<<PORT2);
	
	// Set CS high to avoid problems with SPI slave mode
	PORTB |= _BV(PORT2);
	
	// Set RTC_CS low to de-select DS1306
	RTC_PO &= ~_BV(RTC_CS);
}

int main(void)
{
	ioinit();

	// WHY ARE THESE LINES REQUIRED???
	char clear;
	clear = SPCR;
	SPCR = (1<<SPE)|(1<<MSTR)|(1<<CPHA);
	// WHY ARE THESE LINES REQUIRED???

	while ( 1 )
	{
		char secs = ReadRTC( 0x00 );
		fprintf( stderr, "Secs: %x\n", secs );
		_delay_ms(30);
    }

    return 0;
}

char SPITransfer( char aDat )
{
	SPDR = aDat;
	while ( ! (SPSR & (1<<SPIF)) ) {};
	return SPDR;                    
}
	
void WriteRTC( char aReg, char aDat )
{
	RTCTransfer( aReg, aDat );
}

char ReadRTC( char aReg ) 
{
	return RTCTransfer( aReg, 0 );
}

char RTCTransfer( char aReg, char aDat )
{
	char spiByte;

	// Clear SPIE bit if set
	spiByte = SPSR;
	spiByte = SPDR;
	
	// Set CS to high to enable DS1306
	RTC_PO |= _BV(RTC_CS);

	// Send register, then send/read data
	SPITransfer( aReg );
	spiByte = SPITransfer( aDat );

	// Set CS to low to disable DS1306
	RTC_PO &= ~_BV(RTC_CS);
	
	return spiByte;
}

Clancy _________________ Step 1: RTFM Step 2: RTFF (Forums) Step 3: RTFG (Google) Step 4: Post

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Shortly after posting this, I think I figured it out. I set SPCR register up before I init the port. I guess after I set up the SPI, I then init the port and set the CS high, which must have somewhere during init caused the SPI to get confused and go into slave mode. Resetting it after CS is high I guess fixes it. Why the line that just reads the SPCR register is also required I don't know...

In any case, I removed those lines and put the SPCR config line at the bottom of the ioinit function and it works ok.

Clancy _________________ Step 1: RTFM Step 2: RTFF (Forums) Step 3: RTFG (Google) Step 4: Post

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:
Resetting it after CS is high I guess fixes it.
When you use the SPI as a master are you configuring the SS pin of the SPI as an output? Otherwise if the SS pin changes you will get a SPI collision and the SPI will revert to slave.

John Samperi

Ampertronics Pty. Ltd.

www.ampertronics.com.au

* Electronic Design * Custom Products * Contract Assembly