SPI0DR register always loaded with oxFF on a read.

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

SPI0DR register always loaded with oxFF on a read.

5,163 Views
NZ_Design
Contributor I
I are trying to read a register on a MAX7301 device. The logic analyser tells me that the data on the pins is correct. I read of 0xFF when I should be getting 0x55.
 
Code:
void MAX7301_SPI_init( void ){SPI0CR1 = 0x50;SPI0CR2 = 0x00;DDRS |= 0xE0;PERS |= 0x10;PTS |= 0x80;MAX7301_WriteMAX7301_Config,MAX7301_On);}void MAX7301_Write(uchar cCommand, uchar cData){PTS &= ~0x80; - SS lowwhile(!(SPI0SR & 0x20));SPI0DR = cCommand; - MAX commandwhile(!(SPI0DR & 0x20));SPI0DR = cData; - MAX dataasm("nop"); x 23 times for delay.PTS |= 0x80; - SS high }uchar MAX7301_Read(uchar cCommand){uchar cData;cCommand |= 0x80;PTS &= ~0x80; - SS lowwhile(!(SPI0SR & 0x20));SPI0DR = cCommand;while(!(SPI0SR & 0x20));SPI0DR = cData; - rubish dataasm("nop"); x 23 times for delayPTS |= 0x80; SS highwhile(!(SPI0SR & 0x20));SPI0DR = 0x00; - shift data outwhile(!(SPI0SR & 0x20));SPI0DR = 0x00; - shoft data outwhile(!(SPI0SR & 0x80));cData = SPI0DR; - read data.return cData;}

 
The MAX shift register is 16 bits wide therefore I need to write 2 dummy bytes to get it shifted out to the S12 buffer.
I can write to registers fine and if I put the logic analyser on the signal lines the lines toggle exactly as expected. The SPI0DR registor however always reads 0xFF. for the registor I are reading off it should be 0x55. I know this as it is what I have loaded it with. If it wasnt loaded with 0xff I would not be able to toggle the status of the relivant port pins. The registor is RW that I are trying to read.
(Moderator edited post to highlight source code)

Message Edited by Alban on 02-03-2006 10:07 AM

Labels (1)
0 Kudos
3 Replies

743 Views
NZ_Design
Contributor I

That looks good will try it in the next couple of days. Have already found the SS to be  a problem. I have still had to change out of SPI mode ion that port and clocked the data in with software.

The reason I was using the nops as delays was because when I scoped the lines the SS was going high before the data was all sent on the MOSI lines. Nops give better control of the time rather than a while loop witch seems to take forever in itself.

Thanks

0 Kudos

743 Views
bigmac
Specialist III

Hello NZ-Design,

The primary problem with with your code seems to be that you are not making SS low again when you attempt to read the MAX7301.  Once you have finished sending the command sequence, SS will need to pulse high, and then return low.

I also notice that you are using NOPs to delay until the SPI transaction is completed, so you can return SS high.  A better method, independent of baud rate, would be to monitor the SPIF bit within SPI status register for when it becomes set, and then read the SPI data register to clear the flag.  The value in the data register is discarded if not needed. This should be done for each SPI byte.

To clarify this, I have modified your code along these lines. I have also created another function SPI_Proc() that handles the SPI transaction for a single byte. This is used within both write and read functions to make their operation a little clearer.


Code:

#define SS PTS_PTS7

void MAX7301_SPI_init( void )
{
  SPI0CR1 = 0x50;
  SPI0CR2 = 0x00;
  DDRS |= 0xE0;
  PERS |= 0x10;
  SS = 1;
  MAX7301_Write(MAX7301_Config,MAX7301_On);
}

void MAX7301_Write(uchar cCommand, uchar cData)
{
  SS = 0;
  SPI_Proc (cCommand);
  SPI_Proc (cData);
  SS = 1;
}

uchar MAX7301_Read(uchar cCommand)
{
  uchar cData;

  cCommand |= 0x80;
  MAX7301_Write(cCommand,0);
  
  SS = 0;
  SPI_Proc(0);
  cData = SPI_Proc(0);
  SS = 1;
  return cData;
}

uchar SPI_Proc (uchar value)
{
  while(!(SPI0SR & 0x20)); /* Wait for SPTEF set */
  SPI0DR = value;
  while(!(SPI0SR & 0x80)); /* Wait for SPIF set */
  return SPIODR;
}


I hope this assists.

Regards,

Mac

 

0 Kudos

743 Views
Nabla69
Contributor V
Hi NZ,
 
Do you use a single line between the two devices ?
If yes, you need to use open-collector output (SPI Wired-Or Mode) and push an 0xFF on the bus to avoid contention.
 
Cheers,
Alvin.
0 Kudos