Using SPI EEPROM 25AA512 On An HCS08 Microcontroller

This post will go to the forum eventually.  I need to fight with my hosting people first and get them to bump the limit on the amount of memory PHP can use.  So, for now, you can get all the good stuff here!

EDIT: I fixed the issue.  You can now view this topic on the forum.  Please post your comments there as well.  >>>>

-/-

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

[/code]

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.

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
[/code]
~ 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 */
[/code]
Posted in Microcontrollers, comp-e, forum | Tagged , , , , | Leave a comment

Calculate Min Max and Average Using Assembly

This assembly program reads in 8, 8-bit numbers and is able to calculate the min, max, and average of those numbers.  The code has been optimized for speed, but if compact code is what you want, by all means use a looping structure.  I should mention that this program is an introduction to assembly and runs on the 8085 simulator.  I will however, be posting Verilog code that effectively creates the Intel 8085 and which, will also accept a precompiled hex file via RS232!  That will be in a couple months however (time permitting).  For now, enjoy your nice and easy Assembly example.

COMP-E

~ we do it with NAND gates

Posted in Assembly, comp-e, forum | Tagged , , , , | Leave a comment

Digital Design with Pipeline 6 Bit Registers

This SLSL / ‘sudo verilog’ program implements the digital design of a pipeline having multiple registers, an adder, and multiplication architecture. The program can easily be re-implemented in Verilog at your discretion. SLSL is a wonderful language that allows for rapid development of digital designs, which is why many of my programs are done in it. Conceptually, you can code from a block diagram to an HDL with it. Unfortunately SLSL is not available to the public, but it should be quite easy for anyone with a couple Verilog or VHDL programs under their belt to understand. The code can be found here.

COMP-E
~a place where computer engineers can play

Posted in Verilog, comp-e, forum | Tagged , , , , , | Leave a comment

Nexys 2 Spartan 3 FPGA Arrives

It took a week to get it from Washington state, but it’s finally here.  My gorgeous Nexys 2 board I ordered from Digilent.  It uses the Xilinx Spartan 3-e chip and has a lot of nice extra features that the one that Xilinx makes didn’t have.  Digilent’s website also has a ton of cool addons for the board which I hope to get when there’s some money to spare.   I’m going to start out slow and try and reacquaint myself a bit with verilog.   My intent is to make a simple calculator and then perhaps move to converting my SLSL code for the 8085 over to verilog.  The Nexys 2 board does come with some cool peripherals such as a ps2 port so I may get sidetracked and see what I can do if I hook up an old ball mouse too it.  I’ll try to keep you all posted here so the RSS grabs it, but check the forum for code postings and photos.  I’ll try to include links as things crop up.

- COMP-E

Posted in Verilog, comp-e, forum | Tagged , , , , , , , , | 1 Comment

Digital Design Implementing 8085

All op codes are not represented / implemented in this design however adding them should be very straight forward. This digital design utilizes a bus in order to achieve high efficiency and throughput.  The design is scaled back a bit and uses less registers than the actual 8085.  This can be easily modified though.  Additional op-codes can also be added. Included in this post is are the .src (source) .fmt (format/debug) files. Note that the ‘cpu’ is reading op codes from memory not a .in file!

Click here for the full post including SLSL code.

- COMP-E

Posted in Verilog, comp-e, forum | Tagged , , , , | 2 Comments

Robots /o_O\

Robots are fun, robots are cool, robots will defeat the zombies that are coming!  Well, not quite, but robots are coming to the comp-e.com forum.  I will be posting Matlab code dealing with kinematics and perception ( robot movement and robot vision).    The code on robot vision shows how one can utilize gaussian kernels and some special vectors and masks to easily allow oneself to implement robot vision in about 40 lines of code.  Stay tuned, all will be posted after some commenting, cleanup, and formatting.

\\: COMP-E

Posted in comp-e, forum | Tagged , , | Leave a comment

FPGAs!!!

Howdy all,

I’ve been getting into some realy hobby stuff as of late and you will be seeing some forum posts on it in the near future.  I just got myself a Nexys 2 board ( Xilinx Spartan 3 – based) and will be seeing what I can get out of it.  The overall goal is to write some verilog to create the 8085 for it and then from that make a ‘quad’ 8085 :D   So, we’ll see how it goes you can check out my updated progress on this page and the FPGA directory on the comp-e forum which you can check out here.

Nexys 2: Spartan 3 board

Nexys 2: Spartan 3 board

Cheers,

- COMP-E

Posted in comp-e, forum | Tagged , , , | Leave a comment

COMP-E Forum

Hey all,

The COMP-E forum is starting to grow as I add and encourage others to add usefull new content.  Here is a list and quick link guide to all the current topics on the forum.

Signals & Systems

Digital Design Implementing 8085 in SLSL / Verilog

Digital Design with Pipeline 6 Bit Registers (Add & Mult)

Digital Design with Handshakes and the Use of an Arbiter

C – Example Using Realloc And Pointers

Fun With Pointers == Obfuscated Code

UNIX / LINUX / SOLARIS : Implementing the cat Command in C

C++ Linked List : Hash Table : Template Class

C++ Linked List Utilizing A Hash Table – Includes Makefile

C++ Example :: Find Prime Numbers

OS: C++ Using UNIX Commands fork() execv() execev() pipe()

OS: Crack a UNIX Password Using A Dictionary Attack

Operating Systems: Simulate / Create ‘ thrashing ‘

Operating Systems: Create the UNIX ls Command In C++

Assembly 8085 :: Read In Numbers and Create a Histogram

Assembly 8085 :: Read In Characters and CAPS Letters

Calculate MIN MAX and AVG of 8 Numbers Using Assembly

Building a 2-1 MUX and 4-1 MUX Using NAND Gates

An Introduction To IRC

Tweaking and Cleaning Windows + Some Antivirus Tools

All in all, please add to and enjoy the thuroughness of these posts.  Remember… if you are stuck on mars and all you have are nand gates, you’ll be all set, for you can build anything with nand gates :P

- COMP-E

Posted in comp-e, forum | Tagged , , , , | Leave a comment

C++ Examples

I’ve added quite a few more examples to the section on C++

( linked lists, hash tables, template classes, Makefile)

follow the link: COMP-E Forum: C++ Examples

    – comp-e

Posted in comp-e, forum | Tagged , | Leave a comment

Another Day, Another COMP-E / Engineering Joke :)

– from engineering edu

Five Surgeons

Five surgeons were taking a coffee break and were discussing their work. The first said, “I think accountants are the easiest to operate on. You open them up and everything inside is numbered.” The second said, “I think librarians are the easiest to operate on. You open them up and everything inside is in alphabetical order.” The Third said, “I like to operate on electricians. You open them up and everything inside is color-coded.” The fourth one said, “I like to operate on lawyers. They’re heartless, spineless, gutless, and their heads and their butts are interchangeable.” Fifth surgeon said, “I like Engineers…they always understand when you have a few parts left over at the end…”

- comp-e

Posted in comp-e | Tagged , , , | Leave a comment