SPI issue, using Maxim DS1305 RTC

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

Hi,

I have already searched through the numerous messages here already regarding using the DS1305 with AVRs. I still seem to be having a problem getting it to play nicely with my AVR Mega168, I have included the code I am using below (avr-gcc) in case anyone can spot what I'm doing wrong.

Running this code simply returns 0 from the SPI interface, no matter what address I try and read or what I write to the address. Note in the code below, write address A0 corresponds to read address 20.

void spiTest()
{
   spiInit();

   PORTB |= 1<<2;          // Set SS high
   spiTransferByte (0x8f); // Select Control Register of DS1305
   spiTransferByte (0x00); // Enable osc, enable write, disable alarms 
   PORTB &= ~(1<<2);       // Set SS low

// read write test
   PORTB |= 1<<2;          // Set SS high
   spiTransferByte (0xA0); //  empty data space
   spiTransferByte (0xff); // set to 255
   PORTB &= ~(1<<2);       // Set SS low
  
   PORTB |= 1<<2;       
   spiTransferByte(0x20);    // read address corresponds to A0 write addres
   rprintf("output= %d \r\n", spiTransferByte(0x00));
   PORTB &= ~(1<<2);
}
void spiInit()
{
    // setup SPI I/O pins
    sbi(PORTB, 5);  // set SCK hi
    sbi(DDRB, 5);   // set SCK as output
    cbi(DDRB, 4);   // set MISO as input
    sbi(DDRB, 3);   // set MOSI as output
    sbi(DDRB, 2);   // SS must be output for Master mode to work
	
	// setup SPI interface :
	// master mode
	sbi(SPCR, MSTR);
   
   // clock speed = Fosc/16
	cbi(SPCR, SPR0);
	sbi(SPCR, SPR1);

	// select clock phase positive-going in middle of data
	cbi(SPCR, CPOL);
        sbi(SPCR, CPHA); 

	// Data order MSB first
	cbi(SPCR,DORD);

	// enable SPI
	sbi(SPCR, SPE);
		
	// clear status
	inb(SPSR);
	spiTransferComplete = TRUE;
}
u08 spiTransferByte(u08 data)
{
	// send the given data
	spiTransferComplete = FALSE;
	outb(SPDR, data);

		while(!(inb(SPSR) & (1<<SPIF)));

		// set flag
		spiTransferComplete = TRUE;

	// return the received data
	return inb(SPDR);
}

I have tried applying +5v to MISO pin and output changes from 0 to 255 as expected. I have checked the wiring and everything seems to be ok, no shorts. If anyone can shed any light on the issue here I would be most grateful.

Thanks in advance,

John

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

Quote:

// clear status
inb(SPSR);
spiTransferComplete = TRUE;

I don't know if this does what you want--it needs to be followed by a read of SPDR.

Quote:

PORTB |= 1<<2; // Set SS high
spiTransferByte (0x8f); // Select Control Register of DS1305
spiTransferByte (0x00); // Enable osc, enable write, disable alarms
PORTB &= ~(1<<2); // Set SS low

Pretty much like I do at startup (CodeVision's spi() primitive):

// Start the RTC
SELECT_RTC = 1;			// select RTC
spi (0x8f);		// select the Control Register Write
spi (0x00);		// enable oscillator /EOSC, enable write WP, disable alarms
SELECT_RTC = 0;			// de-select RTC

Let's take a peek at my SPI setup:

// SPI initialization
// SPI Type: Master
// SPI Clock Rate: 1843.200 kHz
// SPI Clock Phase: Cycle Half
// SPI Clock Polarity: Low
// SPI Data Order: MSB First

SPCR=0x54;	// No SPIE, SPE, DORD MSB, MSTR,  CPOL low when idle, CPHA 1, Fck/4
SPSR=0x00; 	// If low bit on, reduce Fck divisor by /2

// Clear the SPI interrupt flag
#asm
    in   r30,spsr
    in   r30,spdr
#endasm

Looks pretty much the same--you might want to cross-check with your settings.

So now we are down to crystal and power. Is the crystal starting to oscillate? Are you using single-power or twin? Is that set up correctly?

Note that the DS1305 will actually run without a crystal, clocking off the SPI clock. The seconds will change & everything, but very very slowly--32k SCKs for each second.

After enabling the chip with the 8f, read address 0 (seconds) repeatedly--like 10000 times. If the seconds change after every 500 or so reads, then the crystal isn't running. If not, then I suspect there is a power problem.

Lee

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Hi Lee,

I tried your method of setting SPCR=0x54; SPSR=0x00; but it's still behaving the same. At the start of your post you say that SPDR needs to be read, why is this, in the initialisation routine? The only part I haven't been able to replicate from your code is the asm bit as winAVR chokes on that, I'm assuming it's codevision specific.

After doing many consecutive reads of address 00 it still outputs 0. It's strange though that if I unplug the DS1305 completely from port B i get 255 output? So it seems it's not the clock anyway, I have already checked but will check again the power connections when I can get to a scope.

Cheers,

John

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

Quote:

At the start of your post you say that SPDR needs to be read, why is this,

From an AVR datasheet:
Quote:

• Bit 7 – SPIF: SPI Interrupt Flag

When a serial transfer is complete, the SPIF flag is set. ... Alternatively, the SPIF bit is cleared by first reading the SPI Status Register with SPIF set, then accessing the SPI Data Register (SPDR).

So, in my startup sequence I'm just clearing the SPI subsystem in case SPIF is set. The #asm isn't necessary; I don't know whaere I picked it up from. Probably

    fred = SPSR;
    fred = SPDR;

would serve as well, if the compiler doesn't optimize it away.

You didn't answer about single-supply (Vcc only) or dual-supply (battery plus Vcc) for your setup. IIRC there are some rules about the battery level & the Vcc level and the switching mechanism. I haven't done one for a couple of years; I'll have to pull the prints & datasheet.

You are sure that you don't have MISO & MOSI swapped, and the /SS is an output (I don't see any DDR stuff in your code)? Can you see the SCK pulse train on a 'scope?

You can put lipstick on a pig, but it is still a pig.

I've never met a pig I didn't like, as long as you have some salt and pepper.

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

Hi Lee,

I have tried reading SPSR and SPDR to clear the SPIF bit but no difference. OK today I hooked my board up to a scope and I took some photos of the trace :) It seems MOSI, CS and SCLK are working as expected but I'm not sure whats happening with MISO.

You can see these pics here:

http://www.charlottest.plus.com/...

Maybe they will help diagnose the fault, I really don't know whats going on with MISO? I have annotated them with the base points of the trace, this is especially important for MISO as you can see it's sitting just below 5v wiggling around, this is without being connected to the DS1305 I should say. The following code is used to generate the test:

  while (1)
   {
            PORTB |= 1<<2;   // set ss high
            spiTransferByte (0x0f); 
            rprintf("output= %d \r\n", spiTransferByte (0x00));  
            PORTB &= ~(1<<2);       // Set SS low
     
   }

I am using a single source supply by the way so the power shouldn't be a problem. Also, I do the DDR stuff at the top of my spiInit() function.

Cheers!

John

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

OK MISO was just wiggling around under 5v because I guess it is tristated when not connected to anything, when connected to the DS1305 it is driven low, hence the constant 0 output.

I have noticed something else, in my spiTransferByte function, if I try reading the SPIF flag at the start it is set, which it shouldn't be until a transfer is completed. I have tried reading the SPSR register followed by SPDR, as stated in the Atmel datasheet to clear it but to no avail.

Can somebody offer any suggestions as to what is going on here?!!

Cheers,

John

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

Can anyone please offer me any advice or suggestions on this issue as this is a university project I have to have completed soon!

John