It is currently Thu Sep 09, 2010 12:22 am




Post new topic Reply to topic  [ 1 post ] 
Using SPI EEPROM 25AA512 On An HCS08 Microcontroller 
Author Message
Site Admin

Joined: Sat Jan 24, 2009 3:56 pm
Posts: 32
Post Using SPI EEPROM 25AA512 On An HCS08 Microcontroller
Most things that use SPI are rather straight forward, a simple MISO, MOSI, and Slave Select and you’re good to go. That was not the case in my pursuit to get this EEPROM to work. It is incredibly finicky and took about a month hooked up to a logic analyzer and multiple revisions to the way instructions interact, before I was finally able to get it up in running. I hope this code works for you. The particular chip came from Microchip and you can find the data sheet easily enough by searching 25AA512. I am including the .c and .h files here. You will be able to view the entire project along with the .mcp file for which I used the memory end such. I’m not ready to post that project yet but it will have ‘SWIM’ somewhere in the topic title.

As a side note, make sure that Vcc on the EEPROM is tied to the Vcc of the microcontroller otherwise you will find as I did, that odd bits and data come back on reads instead of what you want!!

You will notice that slave select pin is not used. Because I only used this one chip, I tied the SS, WP, and HOLD pins to hi/low as per my needs.

- COMP-E


~ XOR would be pleased

The following code was used in SPI1.c

Code:

**     Settings  :
**          Bean name                                      : SPI1
**          Device                                         : SPI
**          Settings
**            Clock settings
**              Value of Preselection                      : 5
**              Value of Selection                         : 64
**              Frequency                                  : 12.5 kHz
**            Mode Select                                  : Master
**            Clock Polarity                               : active-high
**            Clock Phase                                  : First edge
**            Data shift order                             : MSB first
**            Bidirectional mode                           : Disabled
**            Output enable in Bidirect.                   : no
**            Stop in Wait Mode                            : Disabled
**          Pins
**            SCK pin                                      : PTB2_KBIP6_SPSCK_ADP6
**            SCK pin signal                               :
**            MISO pin allocation                          : Enabled
**            MISO pin                                     : PTB4_MISO
**            MISO pin signal                              :
**            MOSI pin allocation                          : Enabled
**            MOSI pin                                     : PTB3_KBIP7_MOSI_ADP7
**            MOSI pin signal                              :
**            SS pin allocation                            : Disabled
**          Interrupts
**            Interrupt                                    : Vspi
**            Receive and fault interrupt                  : Disabled
**            Transmit Interrupt                           : Disabled
**            ISR name                                     :
**          Initialization
**            Call Init in CPU init. code                  : yes
**            Enable SPI system                            : yes
**     Contents  :
**         Init - void SPI1_Init(void);
**

/* MODULE SPI1. */

#include "SPI1.h"

void SPI1_Init(void)
{
  /* SPIC1: SPIE=0,SPE=1,SPTIE=0,MSTR=1,CPOL=0,CPHA=0,SSOE=0,LSBFE=0 */
  setReg8(SPIC1, 0x50);
  /* SPIC2: ??=0,??=0,??=0,MODFEN=0,BIDIROE=0,??=0,SPISWAI=0,SPC0=0 */
  setReg8(SPIC2, 0x00);
  /* SPIBR: ??=0,SPPR2=1,SPPR1=0,SPPR0=0,??=0,SPR2=1,SPR1=0,SPR0=1 */
  setReg8(SPIBR, 0x45);  // note that specific baud rates were not functional
}                        // I believe I had success with 0x45 and 0x00



This EEPROM specific initialization was key to getting things working. It was a function in my main file, but probably belongs in the SPI1.c file.

Code:
void powerUpEEprom(void) {

    CS_OFF;
    delay(2);
    SPI1_Init();
    delay(2);

    delay(2);
    CS_OFF;
    delay(1);
    CS_ON;
    delay(1);

    SPI_WREN();
    SPI_WRSR(0x00);

    /* A small bit of test code */
    SPI_WRITE(0x00, 0x00, 0x11);
    delay(10);
    SPI_WRITE(0x00, 0x01, 0x22);
    delay(10);
    SPI_WRITE(0x00, 0x02, 0x33);
    delay(10);
    SPI_WRITE(0x00, 0x03, 0x44);
    delay(10);
    SPI_WRITE(0x00, 0x04, 0x55);
    delay(10);
    testArray[1] = SPI_READ(0x00,0x00);
    delay(10);
    testArray[2] = SPI_READ(0x00,0x01);
    delay(10);
    testArray[3] = SPI_READ(0x00,0x02);
    delay(10);
    testArray[4] = SPI_READ(0x00,0x03);
    delay(10);
    testArray[5] = SPI_READ(0x00,0x04);
    delay(10);
}



EEPROM.h

Code:

#ifndef __EEPROM_H
#define __EEPROM_H

#include "Events.h"

/* EEPROM OP-CODES */

#define READ    0x03          // Read  from mem array beg. at selected address
#define WRITE   0x02          // Write to mem array beg. at selected address
#define WREN    0x06          // Set   the latch (enable write operations)
#define WRDI    0x04          // Reset the latch (disable write operations)
#define RDSR    0x05          // Read         – STATUS register
#define WRSR    0x01          // Write        – STATUS register
#define PE      0x42          // Page Erase   – erase one page in mem array
#define SE      0xD8          // Sector Erase – erase one sector in mem array
#define CE      0xC7          // Chip Erase   – erase all sectors in mem array
#define RDID    0xAB          //
#define DPD     0xB9          //

/* Program Constants */

#define CS_ON     PTBD_PTBD6 = 0
#define CS_OFF    PTBD_PTBD6 = 1
#define DUMMY     0x00

/* MODULE EEPROM */

void delay(int);

/* Set the write enable latch on the chip */
void SPI_WREN(void);

/* Perform the read status register sequence */
byte SPI_RDSR(void);

/* Write to status register
*
* Pre: User sends 8 bit value
*
* Post: Status register written to
*/
void SPI_WRSR(byte val);

/* Generic transmit of single op code in
*   which chip select is toggled
*/
void SPI_trans(byte val);

/* Perform Read sequence
*
* Pre:  User sends upper and lower address bytes
*
* Post: User recieves value stored at given address
*/
byte SPI_READ(byte upAddr, byte lwAddr);
void Dummy_Read(byte upAddr, byte lwAddr);
/* Perform Write sequence
*
* Pre:   User sends upper and lower address bytes
*        User sends data byte he wishes to have
*             written to the EEPROM
* Post:  Data is written and clocked out of SPID reg
*/
void SPI_WRITE(byte upAddr, byte lwAddr, byte val);

/* END EEPROM */

#endif


~ Computer Engineering is going to the laundromat and saying, "yeah, i can so pipeline this"

EEPROM.c
Code:

/* MODULE EEPROM */

#include "EEPROM.h"
unsigned char readin;
unsigned char garbage;

/*****************************************************************************+
*                        DELAY FUNCTIONS
*****************************************************************************/

void delay(int count)
{
int cnt;

for(cnt = 0; cnt < count; cnt++)
{
int delay1 = 100;         // coarse adjustment
int delay2 = 100;         //  fine adjustment
while(delay1 > 1)
{
--delay1;
while(delay2 >= 1)
{
--delay2;
}
}
}
}

/*****************************************************************************+
*                        WRITE FUNCTIONS
*****************************************************************************/

void SPI_trans(byte val)
{
CS_ON;
delay(2);

while (!(SPIS & 0x20));  // Wait until ready to send
SPID = val;           // Send byte value

delay(2);
CS_OFF;
delay(1);
}

void SPI_WREN(void)
{
CS_ON;
delay(2);

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = WREN;               // Send byte value

delay(1);
CS_OFF;
delay(1);
}

void SPI_WRSR(byte val)
{
CS_ON;
delay(2);

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = WRSR;               // Send byte value

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = val;                // Send byte value

delay(2);
CS_OFF;
delay(1);
}

void SPI_WRITE(byte upAddr, byte lwAddr, byte val)
{
SPI_WREN();

CS_ON;
delay(2);

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = WRITE;              // Send write command

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = upAddr;             // Send upper address

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = lwAddr;             // Send lower address

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = val;                // Send data value

delay(4);
CS_OFF;
delay(1);
}

/*****************************************************************************+
*                        READ FUNCTIONS
*****************************************************************************/

byte SPI_RDSR(void)
{
CS_ON;
delay(2);

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = RDSR;               // Send byte value

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = DUMMY;              // Send byte value
delay(1);
while (!(SPIS & 0x80));    // Wait until ready to send

delay(4);
CS_OFF;
delay(1);
return SPID;
}

byte SPI_READ(byte upAddr, byte lwAddr)
{
Dummy_Read(upAddr,lwAddr);
CS_ON;
delay(2);

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = READ;               // Send write command

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = upAddr;             // Send upper address

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = lwAddr;             // Send lower address

delay(1);
while (!(SPIS & 0x80));    // Wait until ready to send
readin = SPID;             // Dummy read

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = DUMMY;              // Send dummy value

while (!(SPIS & 0x80));    // Wait until ready to send
readin = SPID;             // Contains data from memory
delay(5);
CS_OFF;
delay(1);

return readin;
}

void Dummy_Read(byte upAddr, byte lwAddr)
{
CS_ON;
delay(2);

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = READ;               // Send write command

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = upAddr;             // Send upper address

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = lwAddr;             // Send lower address

delay(1);

while (!(SPIS & 0x80));    // Wait until ready to send
garbage = SPID;            // Dummy read

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = DUMMY;              // Send dummy value

while (!(SPIS & 0x80));    // Wait until ready to send
garbage = SPID;            // Dummy read

delay(1);

while (!(SPIS & 0x20));    // Wait until ready to send
SPID = DUMMY;

delay(5);
CS_OFF;
delay(1);

}

/* END EEPROM */



Fri Mar 13, 2009 9:13 pm
Profile
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1 post ] 


Who is online

Users browsing this forum: No registered users and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © phpBB Group.
Designed by Vjacheslav Trushkin for Free Forum/DivisionCore.