help with spi function - QG8

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

help with spi function - QG8

4,140 Views
rick123
Contributor I
Hello
im very new to freescale and microcontrollers as a whole and im trying to use one to receive data from an EEPROM chip connected to the SPI port my code is very simple and im using polling rather than interrupts but is not working
 
[code]
PTBD_PTBD5 = 0;   /* chip select low */
SPID = 0x03;    /* send read instruction to memory */
while ((SPIS & 0x20) == 0) ;   /* Wait for instruction byte to be sent */
SPID = 0;                    /* provide first read address */
while ((SPIS & 0x20) == 0) ;   /* wait for address byte to be sent */
 SPIC1 = 0x46;        /* set spi as slave to receive data  */
for (memorycounter =0 ;memorycounter < 50000; memorycounter ++)
{
  while ((SPIS & 0x80) == 0) ;   /* Wait for memory data byte to be sent back */
  memorydata = SPID;
  SCID = memorydata;
  while ((SCIS1 & 0x80) == 0) ;   /* Memory data out serially to RS232/computer */
}
PTBD_PTBD5 = 1;   /* chip select high */
 
[/code]
i basically just want to read the first 50,000 bytes of memory from EEPROM, just wondering if anything in my code jump out at anyone as being particularly wrong? before i get into the nity gritty stuff.
 
Much Appreciated
Rick
 
sorry forgot to mention the micro is a hcs08 QG8
and in the debug mode my code seems to send the instruction byte ok ( i think) but then then gets stuck sending the address to the EEPROM ( code does not reach any instructions after this one) so maybe im not reseting the status register properly or something?



Message Edited by rick123 on 2008-02-04 06:28 PM

 

Added p/n to subject.



Message Edited by NLFSJ on 2008-02-05 07:42 AM
Labels (1)
0 Kudos
23 Replies

1,259 Views
rick123
Contributor I
Hi all thanks for your help i now have it working and receiving FF data responses as expected , cheers for all your patience!
 
0 Kudos

1,259 Views
rick123
Contributor I
Hi sorry i have one more question i am able as i said before to read the memory and i can erase it but i seem to run into a problem when writing to i.
Im trying to just as a test write the character "A" to memory location 4, but it seems to write a completley different character to memory location 0 instead?
 
not sure why, i assumed it would be very similar to the coding you have given me on this forum already
 
Code:
if (PTAD_PTAD5 == 0) //write to the chip  {    address = 4;    PTBD_PTBD5 = 0;  //chip select low    SPI_proc(6);     // Command to enable the write latch    PTBD_PTBD5 = 1;  // chip select high    PTBD_PTBD5 = 0;  // chip select low    SPI_proc(2);     // Command to write data to EEPROM    SPI_proc((address >> 16) & 0x01);  // Send highest byte, only LSB matters    SPI_proc((address >> 8) & 0xFF);   // Send middle byte    SPI_proc(address & 0xFF);    SPI_proc('A' & 0xFF);  // send charcter "A" to memory location 4    PTBD_PTBD5 = 1; //chip selct high  }

 
using the function below that you have me already to actually send the data byte
Code:
byte SPI_proc (byte data){   while (!SPIS_SPTEF);  /* Wait for Tx buffer empty */   SPID = data;          /* Send byte */   while (!SPIS_SPRF);   /* Wait for Rx buffer full */   return (SPID);        /* Received byte value */}

 
any ideas? 
 
 


Message Edited by rick123 on 2008-02-08 02:18 PM
0 Kudos

1,259 Views
JimDon
Senior Contributor III
What does it write? Does it alway write the same thing?

You are supposed to read the status register to know when the write is done.

See the RDSR command. You should loop until the WIP bit goes to 0.
Also, it is hard to say that you can read if you can't write - when you are reading back FF you don't know
what address you are reading - are you sure you are reading the correct address back?
Do you do an erase before each test run?
0 Kudos

1,259 Views
rick123
Contributor I
Yeh just as a test i was havin the same character written to just one memory address.
 
The read code im pretty sure is working since i read the first 50 memory locations and each has FF data ( once erased) .  when i use my write code memory address 0 takes the value 0x01 even though in the code it says write "A"  to memory address 4.
im leaving at least  3 second gaps between reading/writing/erasing so the previous read/write or erase action should defineltey have been completed.
 
0 Kudos

1,259 Views
JimDon
Senior Contributor III
Well, I don't know how you are timing this, and a chip erase can take up to 4 seconds.

I also don't know how you can say with any degree of certainty that you are reading correctly when you are reading FF at all locations. You should write an  address in address test - meaning you write 0 in address 0 and 1 in address  1 and so on  from 0 to 255  to prove that all is working.

I am just trying to share with you the problems I had.

You should write a function to poll the status register and wait for the  WIP to be zero. Even if this is not a problem now it will be a problem later. If you use a timer, then for one thing you will be mostly waiting too long, and if you ever change the time period of the timer down the road, all of a sudden your flash code may stop working and you will be wondering why.

0 Kudos

1,259 Views
allawtterb
Contributor IV
I agree with Jim, try writing 0-255 to address 0-255 then read all the data back and see what you get.  Also, try to poll the status register.  All it takes to do this is:
Code:
void SPI_Write_Wait(void){   unsigned char Status_Register = 0x01;   // Perhaps turn on an LED here if one is avaliable   while (Status_Register == 0x01)      // Continue until bit is cleared   {      PTBD_PTBD5 = 0;                   // Select the EEPROM      SPI_proc(5);                      // Command to read the status register      Status_Register = (SPI_proc(0xFF) & 0x01); // Write dummy bytes, read data back in and mask it      PTBD_PTBD5 = 1;                   // Disable the EEPROM select   }   // Turn LED off if available}

 
You might be able to put the chip select and de-select outside of the whlie loop.
 
The steps should be:
1) Page erase of page to be written
2) Call SPI_Write_Wait for erase to complete
3) Write all 256 bytes
4) Call SPI_Write_Wait for write to complete
5) Read back in all 256 bytes
 
0 Kudos

1,259 Views
rick123
Contributor I
Tried everything  you have told me, not sure why it is not working, when i write to the chip it is writing rubbish.  I know the erase part works since when i erase it and re-read all the garbled bits have value FF so it is just the write function that is not working am i setting up the the control registers wrong or something i really dont have a clue... :smileysad:
i thought i would include the code as an attachment, it is a really small program however.
 
Any last ideas
 
 


Message Edited by rick123 on 2008-02-11 01:33 PM
0 Kudos

1,259 Views
bigmac
Specialist III
Hello,
 
Some comments about your posted code -
  1. When you read each byte, you send the raw value to the SCI.  If you are monitoring this using Hyperterminal, or similar, the displayed results will probably not make sense unless you are writing an ASCII character.  If not ASCII, you will need to convert the raw value to some sort of ASCII format, perhaps two hexadecimal characters to represent each byte.  Incidently, it would be usual to test the TDRE flag prior to writing to the SCI, not following the write.
  2. Within your EEPROM write process, you seem to be writing the same ASCII character "$" to all locations.  Not sure whether this was your intent.
  3. Check the EEPROM specification, but it may be possible to send consecutive bytes to the EEPROM, without the need to repeatedly enable writes, and separately send each address value.  If this is possible, you need to be aware of the internal buffer size within the EEPROM.
  4. The function SPI_Statuscheck() may be problematic because of the use of a while loop.  For the first pass through the loop, the value within Status_Register has not been updated.  Alternatively, you might use a do/while loop.
  5. You have a setting of CPHA = 0, CPOL = 0.  Check that this matches the EEPROM requirements.
  6. You seem to be manually controlling PTBD5 as the SS (CS) output line.  Yet you have also enabled automatic SS output at PTB5.  The automatic operation will take precedence over GPIO control, and this will not meet the requirements of the EEPROM device.
Regards,
Mac
 


Message Edited by bigmac on 2008-02-12 02:33 PM
0 Kudos

1,259 Views
JimDon
Senior Contributor III
Thanks for taking the time to look over his code. I just didn't have the time.

Your are 100% correct about the chip - after setting up the write you can write a full page of data by just by sending  the data.

You should read macs post carefully and heed his advice, I am confident he his correct in all that he said.
There is s good chance it is working, but because you did not convert the data to ASCII before sending it, it looks like garbage.



Message Edited by JimDon on 2008-02-12 08:54 AM
0 Kudos

1,259 Views
sebastian
Contributor I

Hello

 

I am using a microcontroller and a MC9S08QE128 MCF51QE128 QE128 module.  I implemented the code that was corrected during the forum but I have problems.
 When I read a byte from the same address, I get different values, I think I am not writing correctly in memory.

I wonder who could be wrong in the code. Below is the data EEPROM memory.

 

I do not know if my clock is set correctly or if the timing diagram of EEPROM memory that can fit the value of CPOL and CPHA.,

 

This is my code:

 

#include <hidef.h> /* for EnableInterrupts macro */
#include "derivative.h" /* include peripheral declarations */

typedef unsigned char UINT8;
typedef unsigned int UINT16;

void SPI_Write_Wait(void);   //polling, de escritura realizandoze
UINT8 SPI_proc (byte data);
 void SPI_registersetup(void);
 void SPI_enable(void);
 void delay(UINT16 a);  //del demo SPI MASTER

/*********************************************************************/
/*  Function declarations                                            */
/*********************************************************************/

void delay (UINT16 a) {

  UINT16 i = 0;
  for (i; i<=a; i++){            
  }   
}


void MCU_Init(void) {
 SOPT1 = 0x23;          /* Watchdog disable. Stop Mode Enable. Background Pin enable. RESET pin enable */   
 SCGC1 = 0x01;          /* Bus Clock to the SCI1 module is enable */
 SCGC2 = 0x02;          /* Bus Clock to the SPI2 module is enabled */
}

void GPIO_Init(void) {

  PTDD_PTDD3 = 1;      /* The SS signal must be generated by software using a GPIO */

  PTCDD = (UINT8) (PTCD | 0x3F);          /* Configure PTC0-PTC6 as outputs */
  PTEDD = (UINT8) (PTED | 0xC0);          /* Configure PTE6 and PTE7 pins as outputs */
  PTCD = 0x3F;           /* Put 1's in port C in order to turn off the LEDs */
  PTED = 0xC0;           /* Put 1's in port E port in order to turn off the LEDs */
}


/*********************************************************************/
/*  CONFIG SERIAL PORT                                         */
/*********************************************************************/

void SCI_configuration (void) {
 
  SCI1C1 = 0x00;        /* 8-bit mode. Normal operation */
  SCI1C2 = 0x2C;        /* Receiver interrupt enable. Transmitter and receiver enable */
  SCI1C3 = 0x00;        /* Disable all errors interrupts */
  SCI1BDL = 0x1A;       /* This register and the SCI1BDH are used to configure the SCI baud rate */
  SCI1BDH = 0x00;       /*                    BUSCLK               4MHz                */
                        /* Baud rate = -------------------- = ------------ = 9600bps   */
}                       /*               [SBR12:smileyfrustrated:BR0] x 16        26 x 16              */


/*********************************************************************/
/* FUNCTIONS  SPI                                                    */
/*********************************************************************/

void SPI_Write_Wait(void) {
 
  //Command to read the status register y verfificar si el ciclo de escritura esta en progreso
   unsigned char Status_Register = 0x01;
   // Perhaps turn on an LED here if one is avaliable
   while (Status_Register == 0x01)      // Continue until bit is cleared
   {
      PTDD_PTDD3 = 0;                   // Select the EEPROM
      SPI_proc(5);                      // Command to read the status register//READ STATUS REGISTER (RDSR)
      Status_Register = (SPI_proc(0xFF) & 0x01); // Write dummy bytes, read data back in and mask it
                                        //Bit 0 (RDY) =1, entonces ciclo de escritura en progreso(pag 9)
      PTDD_PTDD3 = 1;                  // Disable the EEPROM select
   }
}



UINT8 SPI_proc (byte data){

   while (!SPI2S_SPTEF);  /* Wait for Tx buffer empty */
      SPI2D = data;          /* Send byte */
   while (!SPI2S_SPRF);   /* Wait for Rx buffer full */
      return (SPI2D);        /* Received byte value */
}


UINT8 SendRecieveSPI( UINT8 data ) /*---SPI_PROC opcional*/
{
   SPI2D = data;
   while(!SPI2S_SPRF) ;
   data = SPI2D;
   return data;
}



 void SPI_registersetup(void)
  {
        PTDD_PTDD3 = 0;                   // Select the EEPROM
        SPI_proc(1);                      // Command to write the status register
        SPI_proc(0x00);
        PTDD_PTDD3 = 1;
  }



void SPI_enable(void)
{
  PTDD_PTDD3 = 0;
  SPI_proc(6);     //Enable write latch
  PTDD_PTDD3 = 1;
}


void SPI_configuration (void) {
 

  SPI2BR = 0x76;//0x77;//0x75;        /* Select the highest baud rate prescaler divisor and the highest baud rate divisor */
  SPI2C1 = 0x52; //spi enabled polling para SPRF y SPTEF, tipo master and without interrupts
  SPI2C2 = 0x10;        /* Different pins for data input and data output */
 
  (void)SPI2S;
  (void)SPI2D;
}



/*********************************************************************/
/* MAIN                                                              */
/*********************************************************************/

void main(void) {

  volatile unsigned long address=0;  
  volatile unsigned char memorydata=0;
  volatile long int memorycounter=0;
  volatile long int writecounter=0;
  volatile UINT8 highAdd=0;
  volatile UINT8 lowAdd=0;


  MCU_Init();       /* Function that initializes the MCU */      
  GPIO_Init();      /* Function that initializes the Ports of the MCU */
  SCI_configuration();  /* Function that initializes the SCI module */

  SPI_configuration ();


  EnableInterrupts; /* enable interrupts */
  /* include your code here */
 

/*-------------READ--------------------*/
PTDD_PTDD3 = 0;        //chip select low  

    SPI_proc(3);     // Command to read data from EEPROM      
    SPI_proc(address & 0x00);         // Send highest
    SPI_proc(address & 0x00);         //ssend lowest
 
 for (memorycounter=0; memorycounter<10; memorycounter ++)
   {  
    memorydata = SPI_proc(0xFF);   // Read in a byte from the EEPROM     
     
    while (!SCI1S1_TDRE);           // Make sure SCI transmit buffer is empty
    SCI1D = memorydata;  
   }
 
PTDD_PTDD3 = 1;   // chip select high  

delay(600000);
 
 
  //-----------------WRITE------------------------//
 SPI_registersetup();
 SPI_enable();//SPI_erase();  // erase the chip
 SPI_Write_Wait();//SPI_statuscheck(); // make sure erase is complete
 
 //delay(60000);
 
 for (writecounter =0; writecounter <10; writecounter ++) //write to first 10 memory locations
 {
 
        highAdd =  (writecounter >> 8) & 0xFF;
        lowAdd =   writecounter & 0xFF;
 
            PTDD_PTDD3 = 0;      //chip select low

                 SPI_proc(2);      // Command to write data to EEPROM
                 SPI_proc(highAdd);//SPI_proc((writecounter >> 8) & 0xFF);   // Send high add
                 SPI_proc(lowAdd); //SPI_proc(writecounter & 0xFF);          // Send low add
                 SPI_proc(0xF0);   //DATA send the current counter value to memory     ??????
 
            PTDD_PTDD3 = 1;  //chip select low
            SPI_Write_Wait();
 }
 
 
 PTCD_PTCD0 = 0; //LED
 
  for(;:smileywink: {
 

  } /* loop forever */


  /* please make sure that you never leave main */
}


 

Thanks

0 Kudos

1,259 Views
kef
Specialist I

Clearly format is CPOL=CPHA=0. Look at figure 4-1 in Atmel datasheet. You may notice that 1) before communication clock idles low, 2) in-data is sampled on rising edge, 3) out-data is shifted out on falling clock edge. Now open your QE reference manual and look at two figures with CPHA=0 format and CPHA=1 format. Clearly CPOL should be 0, because clock should idle low. Now decide do you need CPHA=0 or CPHA=1.

 

In SPI configuration you enabled SSOE bit. Clearly your should not use automatic SS and toggle chip select pin from your code. It looks like you are trying to do so, but SS pins is already driven automatically from SPI module. Try disabling SSOE and MODFEN.

 

Please comment all your magic (and annoying) figures, what each bit means. It is not nice at all to decifier them.

0 Kudos

1,259 Views
sebastian
Contributor I

 

Thank you all for your help, I wrote "PTDD_PTDD3 = 1;"
and I had to change "PTDDD_PTDDD3 = 1;" for this right. I can now read and write. Thanks

0 Kudos

1,259 Views
allawtterb
Contributor IV
You can remove the SPI_erase, it seems the chip does an erase automatically before a write.  Also, can you explain what you mean when you say it writes rubbish?
0 Kudos

1,259 Views
rick123
Contributor I
Hi again thanks for the reply im really not getting this however i have done what you have mentioned in the code but im not sure im grasping the whole thing here could you please show me which part of my code to change  ( im prettysure my sendign 0xff bit is wrong ) really new to this thanks for your patience.
 
 
void main(void)
{

/**************************************************************/
/********** SETUP VARIABLES ***********************************/
/**************************************************************/   
long int memorycounter=0;
unsigned char memorydata=0;
unsigned char address=0;
volatile char temp=0;
/**************************************************************/
/**************************************************************/
        
for(;:smileywink:
{
  
__RESET_WATCHDOG(); /* feeds the dog */     

/**************************************************************/       
/************* DATA DIRECTION AND PULL UP REGISTERS** *********/
/**************************************************************/ 
PTADD = 0x00;
PTAPE = 0x24;
PTBDD = 0xee;
PTBPE = 0x11;
PTBD_PTBD5 = 1;
/**************************************************************/
/**************************************************************/

/**************************************************************/       
/************ SET UP SPI REGISTERS*****************************/
/**************************************************************/  
SPIC1 = 0x52;
SPIC2 = 0x10;   /* 9600 baud */
SPIBR = 0x00; /* Normal mode, 8 bits,  no parity */
(void)SPIS;
(void)SPID;
/************************************************************/
/**************************************************************/
 

/**************************************************************/
/************ SET UP SCI REGISTERS ****************************/
/**************************************************************/  
SCIBDH = 0;
SCIBDL = 26;   /* 9600 baud */
SCIC1 = 0x00; /* Normal mode, 8 bits,  no parity */
SCIC2 = 0x4C; /* Enable transmitter and receiver, no interrupts */      
/*************************************************************/
/**************************************************************/
 
  
/**************************************************************/  
/******************** DETERMINE MODE READ/WRITE **************/
/**************************************************************/
       
       
if (PTAD_PTAD2 == 0)  /* read chip */
{
PTBD_PTBD5 = 0        //chip select low
SPID = 0xff;         //send the byte to clock the chip?
while (!SPIS_SPRF) ;
PTBD_PTBD5 = 1;      //chip select high
PTBD_PTBD5 = 0;   /* chip select low */
SPID = 0x03;    /* send read instruction to memory */
while (!SPIS_SPRF) ;   /* Wait for read instruction byte to be sent */
temp = SPID;
temp = SPIS;
SPID = 0x000;                    /* provide first read address */
for (memorycounter=0; memorycounter<50; memorycounter ++)
{
while (!SPIS_SPRF) ;   /* wait for address byte to be sent */
temp = SPID;
temp = SPIS;
while (!SPIS_SPRF) ;   /* Wait for memory data byte to be sent back */
temp = SPIS;
memorydata = SPID;
SCID = memorydata;
while ((SCIS1 & 0x80) == 0) ; /* Memory data out serially to RS232/computer */
}
PTBD_PTBD5 = 1;   /* chip select high */
}      
}
}
0 Kudos

1,259 Views
JimDon
Senior Contributor III

You need to send 3 bytes of address.
Please consider doing as  mac hassuggested, use a subroutine to send /receive from the spi.

0 Kudos

1,259 Views
allawtterb
Contributor IV
The for loop used to clock the data from the EEPROM is still incorrect.  You are never sending dummy data (0xFF) to the EEPROM so that it will send the data you want back to you.  All you are doing is reading the SPI Status Register and SPI Data Register.  I would suggest you read the wiki page on SPI to get a better understanding of how SPI communication works:
 
You really should be using a function to send/receive through the SPI, it will make the code much cleaner and easier to use in the future.  From the link bigmac provided is the following simple function to send/receive SPI data, it has been modified for your microcontroller registers:
Code:
byte SPI_proc (byte data){   while (!SPIS_SPTEF);  /* Wait for Tx buffer empty */   SPDR = data;          /* Send byte */   while (!SPIS_SPRF);   /* Wait for Rx buffer full */   return (SPDR);        /* Received byte value */}

 
Now before your for loop you need to send 3 address bytes, you declared the address as an unsigned character but you need 17 bits to address all of the EEPROM so declare it as an unsigned long.  To start a read from address 0 then set the variable address to 0 then:
Code:
SPI_proc(3);     // Command to read data from EEPROMSPI_proc((address >> 16) & 0x01);  // Send highest byte, only LSB mattersSPI_proc((address >> 8) & 0xFF);   // Send middle byteSPI_proc(address & 0xFF);          // Send lowest byte

Now you have your for loop and you simply send dummy bytes, 0xFF will work but so will any other byte.
Using the variables you provided:
Code:
for (memorycounter=0; memorycounter<50; memorycounter ++){   memorydata = SPI_proc(0xFF);   // Read in a byte from the EEPROM   while (!SCIS1_TDRE);           // Make sure SCI transmit buffer is empty   SCID = memorydata;             // Send the byte over the SCI}

The first time that you use the SPI module though it should be initialized by the code JimDon posted:
  (void)SPIS;          // Read the status register
  (void)SPID;          // Read the device register
 
All that being said,if you haven't written anything to the EEPROM yet all you will read is 0xFF from it.  I would suggest testing the above code with that in mind then using the SPI_proc function to test writing then reading the same data back from the EEPROM.
 


Message Edited by allawtterb on 2008-02-05 03:59 PM
0 Kudos

1,259 Views
bigmac
Specialist III
Hello,
 
A minor point -

allawtterb wrote:

The first time that you use the SPI module though it should be initialized by the code JimDon posted:

  (void)SPIS;          // Read the status register
  (void)SPID;          // Read the device register

My understanding is that, for HCS08 and HCS12 devices (but not for HC08 devices), it is required to read SPIS prior to the first write to SPID.  It is not necessary to read SPID.
 
Since the SPI_proc() function incorporates the test of the SPTEF flag, this will provide the required first-time read for SPIS.
 
Regards,
Mac
 
0 Kudos

1,259 Views
rick123
Contributor I
Hi thanks for all your replies i have tried to do most of what you have said i am able to send data out now and recieve i think but it is comng back garbled :smileysad: im displaying the data from EPROM  via SCI which i know is said up correctly as im using that in a similar project. (displaying info through hyperterminal)
the chip im using is a microchip 25LC1024, this is the entire code any idea what else have i missed?  Im not sure what you mean by send off hex ff, what does this do ?
 
thanks again
 
#include "derivative.h" /* include peripheral declarations */
#include "MC9S08QG8.h" /* include peripheral declarations */

void main(void)
{

/**************************************************************/
/********** SETUP VARIABLES ***********************************/
/**************************************************************/   
long int memorycounter=0;
unsigned char memorydata=0;
long int address=0;
unsigned char temp=0;
/**************************************************************/
/**************************************************************/
        
for(;:smileywink:
{
  
__RESET_WATCHDOG(); /* feeds the dog */
       

/**************************************************************/       
/************* DATA DIRECTION AND PULL UP REGISTERS** *********/
/**************************************************************/ 
PTADD = 0x00;
PTAPE = 0x24;
PTBDD = 0xee;
PTBPE = 0x11;
PTBD_PTBD5 = 1;
/**************************************************************/
/**************************************************************/

/**************************************************************/       
/************ SET UP SPI REGISTERS*****************************/
/**************************************************************/  
SPIC1 = 0x52;
SPIC2 = 0x10;  
SPIBR = 0x00;
/************************************************************/
/**************************************************************/
 

/**************************************************************/
/************ SET UP SCI REGISTERS ****************************/
/**************************************************************/  
SCIBDH = 0;
SCIBDL = 26;   /* 9600 baud */
SCIC1 = 0x00; /* Normal mode, 8 bits,  no parity */
SCIC2 = 0x4C; /* Enable transmitter and receiver, no interrupts */      
/*************************************************************/
/**************************************************************/

  
/**************************************************************/  
/******************** DETERMINE MODE READ/WRITE **************/
/**************************************************************/
       
       
if (PTAD_PTAD2 == 0)  /* read chip */
{
for (address =0; address <50 ; address ++) { 
PTBD_PTBD5 = 0;   /* chip select low */
SPID = 0x03;    /* send read instruction to memory */
while ((SPIS & 0x80) == 0) ;   /* Wait for instruction byte to be sent */
temp = SPID;
temp = SPIS;
SPID = address;                    /* provide first read address */
while ((SPIS & 0x80) == 0) ;   /* wait for address byte to be sent */
temp = SPID;
temp = SPIS;
while ((SPIS & 0x20) == 0) ;   /* Wait for memory data byte to be sent back */
temp = SPIS;
memorydata = SPID;
PTBD_PTBD5 = 1;   /* chip select high */
SCID = memorydata;
while ((SCIS1 & 0x80) == 0) ; /* Memory data out serially to RS232/computer */
}
}      
}
}


Message Edited by rick123 on 2008-02-04 11:51 PM
0 Kudos

1,259 Views
JimDon
Senior Contributor III
Ok, first of all to read a byte you have to send a byte to clock the chip. If you have to send a byte, I am suggesting that it be FF. I the case of this chip it does not matter, because the spec says the SI line is "don't care" when the chip is sending data.

It would make life easier if you created a function to send/recieve a byte.

byte SendRecieveSPI( byte data )
{
  SPID = data;
   while(!SPIS_SPRF) ;
   data = SPID;
   return data;
}

Also as peg pointed out, you should do this in your init code, before you start using the SPI:
  (void)SPIS;          // Read the status register
  (void)SPID;          // Read the device register

You should also declare temp as volatile in  case  the compiler decides to optimize away the code that in it's mind is not doing any thing useful.

You need to send a 24 bit address.
Quoting the spec.
The device is selected by pulling CS low. The 8-bit read instruction is transmitted to the 25XX1024 followed by the 24-bit address, with seven MSBs of the address being don’t care bits. After the correct read instruction and address are sent, the data stored in the memory at the selected address is shifted out on the SO pin. The data stored in the memory at the next address can be read sequentially by continuing to provide clock pulses. The internal address pointer is automatically incremented to the next higher address after each byte of data is shifted out. When the highest address is reached (1FFFFh), the address counter rolls over to address 00000h allowing the read cycle to be continued indefinitely. The read operation is terminated by raising the CS pin (Figure 2-1).


So what you need to do is:
Raise Chip Select             do this to be sure you have cleared the chip
Lower Chip Select
Send Read Command
(Send address >> 16) & 1       Send the highest byte - only the lsb counts here.
(Send address >> 8) & 0xff      Send the middle
(Send  address) & 0xff              Send  the lo byte.

Now you can loop on reading back as many bytes as you need.
Note however, you must NOT raise the CS line until you are done reading.
Raising the CS line signals you are done and resets the chip to receive another command.
However, when you are done reading and wish to start another command, you MUST raise the CS line.
Also, don't forget you must erase a sector or a block before writing.













Message Edited by JimDon on 2008-02-04 08:45 PM
0 Kudos

1,259 Views
bigmac
Specialist III
Hello Rick,
 
The following old thread may be of assistance for your problem.
 
 
Regards,
Mac
 


Message Edited by bigmac on 2008-02-05 06:18 PM
0 Kudos