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; }