25LC256 ile SPI EEPROM uygulaması (pic 18F4685 ve c18)

25LC256 ile SPI EEPROM uygulaması (pic 18F4685 ve c18)

Proje spi eeprom için kullandığımız 25lcxxx kütüphanesi ve sonuçları görebilmek için kullandığımız LCD kütüphanesinden oluşmaktadır. LCD kütüphanesini daha önce paylaşmıştık, o yazıyı incelemek için tıklayınız.

Kullandığımız chip 25LC256’dır. bu chip 256kilobit’lik tir.

256 kilobit=256/8=32 kilo byte yapar.

Eğer 32kilobyte’lık alan size yetmiyorsa 64kbyte’lık olan 25LC512’yi, o da yetmiyorsa 128kbyte’lık 25LC1024 chip’ini kullanabilirsiniz. Bunlardan daha geniş hafızalı spi chiplerde elbette var…

Kütüphanenin algoritmasını merak ediyorsanız şu üç uygulama notunu incelemenizi öneririm: http://ww1.microchip.com/downloads/en/AppNotes/01018A.pdf

http://ww1.microchip.com/downloads/en/AppNotes/00995A.pdf

http://ww1.microchip.com/downloads/en/AppNotes/01000a.pdf

Örneğin yazı yazma işlemi için neler yapmalıyız yazayım:

spi ile “write enable” komutunu yani 0x06 komutunu gönderiyoruz peşine “write” komutunu(0x02) onun peşine adresimiz 16 bitlik olduğu için yazacağımız adresin yüksek bitlerini ve sonra düşük bitlerini gönderiyoryz, onun da peşine yazdıracağımız datayı gönderiyoruz.

main.c

#include <p18f4620.h>
//#include "p18cxxx.h"
#include <stdio.h>
#include <stdlib.h>
#include <delays.h>
#include "25lcxxx.h"
#include "lcd.h" // LCD kütüphanesi tanimlaniyor

#pragma config OSC = HS, WDT = OFF, LVP = OFF

void main(void)
{
    unsigned char i;

    unsigned char okunan=0,veri=0;
    unsigned int adres16=0x0000;

    unsigned char s1[20];
    unsigned char s2[20];

    TRISB=0x00; // LCD'ye bagli portlar çikis yapiliyor
    lcd_init(); // LCD ilk ayarlari yapiliyor

    eepromu_hazirla();

    for(i=0;i<16;i++)
    {
        veri=i;
        adres16=i;
        HighDensByteWrite(veri,adres16); //"adres16" adresine "veri" verisini yaz
        Delay10KTCYx(10);
        okunan = 0xFF;

        HighDensByteRead(&okunan,adres16); //yazilacak degiskenin pointer adresini veriyoruz

        sprintf(s1,"Oku Adres:0x%04X",adres16);
        sprintf(s2,"veri: 0x%02X",okunan);

        lcd_clear();
        lcd_gotoxy(1,1);
        lcd_yaz(s1);
        lcd_gotoxy(2,1);
        lcd_yaz(s2);

        Delay10KTCYx(100);
    }
    while(1);
}

25lcxxx.h dosyası

/********************************************************************
 * bu kutuphane microchip'in AN1018 yayınından,
 * M.Gökhan BEKEN tarafindan uyarlanmistir
 ** D I K K A T *****************************************************/

/** D E F I N E S **************************************************/
#define WREN        0b00000110          // WREN command
#define WRDI        0b00000100          // WRDI command
#define WRITE       0b00000010          // WRITE command
#define READ        0b00000011          // READ command
#define WRSR        0b00000001          // WRSR command
#define RDSR        0b00000101          // RDSR command

//pinlerimizi belirtiyoruz
#define CS_tris  TRISCbits.RC2
#define SCK_tris TRISCbits.RC3
#define SDI_tris TRISCbits.RC4
#define SDO_tris TRISCbits.RC5

#define CS_port  LATCbits.LATC2
#define SCK_port LATCbits.LATC3
#define SDI_port PORTCbits.RC4
#define SDO_port LATCbits.LATC5

/** P R O T O T Y P E S ********************************************/
void LowDensByteWrite(unsigned char,unsigned int);                  // Low-density Byte Write function
void LowDensByteRead(unsigned char*,unsigned int);                   // Low-density Byte Read function
void LowDensPageWrite(unsigned char*,unsigned int,unsigned char);   // Low-density Page Write function
void LowDensSeqRead(unsigned char*,unsigned int,unsigned char);     // Low-density Sequential Read function
void HighDensByteWrite(unsigned char,unsigned int);                 // High-density Byte Write function
void HighDensByteRead(unsigned char*,unsigned int);                  // High-density Byte Read function
void HighDensPageWrite(unsigned char*,unsigned int,unsigned char);  // High-density Page Write function
void HighDensSeqRead(unsigned char*,unsigned int,unsigned char);    // High-density Sequential Read function
unsigned char ReadStatusReg(void);                                  // Read Status Register function
void WriteStatusReg(unsigned char);                                 // Write Status Register function
void WriteEnable(void);                                             // Write Enable function
void WriteDisable(void);                                            // Write Disable function
void WIP_Poll(void);                                                // WIP polling function

25lcxxx.c dosyası:

/********************************************************************
 * bu kutuphane microchip'in AN1018 yayınından,
 * M.Gökhan BEKEN tarafindan uyarlanmistir
 ** D I K K A T *****************************************************/

#include <p18cxxx.h>
#include "25lcxxx.h"

void eepromu_hazirla()
{
	CS_tris=0;
	SCK_tris=0;
	SDI_tris=1;
	SDO_tris=0;

	CS_port=0;
	SCK_port=0;
	SDO_port=0;
}

/** P R I V A T E   P R O T O T Y P E S ****************************/
void byteout(unsigned char);            // Byte output function
unsigned char bytein(void);             // Byte input function

/********************************************************************
 * Function:        void LowDensByteWrite(unsigned char data,
 *                                        unsigned int address)
 *
 * Description:     This function performs a byte write operation for
 *                  low-density (<= 4 Kb) devices. It embeds the MSb
 *                  of the memory address into the instruction in
 *                  order to support the 25XX040X. After initiating
 *                  the write cycle, the WIP_Poll function is called
 *                  to determine the end of the cycle.
 *
 * Parameters:      data - Byte of data to be written
 *                  address - Memory location at which to start
 *******************************************************************/
void LowDensByteWrite(unsigned char data, unsigned int address)
{
    static unsigned char command;   // Temp. variable to store cmd.

    // First embed MSb of address (bit 8) into instruction
    command = address >> 5;         // Align MSb of address
    command &= 0x08;                // Mask off extra bits
    command |= WRITE;               // Merge in WRITE instruction

    WriteEnable();                  // Set WEL bit for write
    CS_port = 0;                         // Bring CS low (active)
    byteout(command);               // Output command & MSb of address
    byteout(address&0xFF);          // Output LSB of address
    byteout(data);                  // Write byte of data
    CS_port = 1;                         // Bring CS high (inactive)
    WIP_Poll();                     // Perform WIP polling
} // end of LowDensByteWrite(...)

/********************************************************************
 * Function:        void LowDensByteRead(unsigned char data,
 *                                       unsigned int address)
 *
 * Description:     This function performs a byte read operation
 *                  for low-density (<= 4 Kb) devices. It embeds the
 *                  MSb of the memory address into the instruction in
 *                  order to support the 25XX040X.
 *
 * Parameters:      data - Pointer to store byte of data read
 *                  address - Memory location at which to start
 *******************************************************************/
void LowDensByteRead(unsigned char *data, unsigned int address)
{
    static unsigned char command;   // Temp. variable to store cmd.

    // First embed MSb of address (bit 8) into instruction
    command = address >> 5;         // Align MSb of address
    command &= 0x08;                // Mask off extra bits
    command |= READ;                // Merge in READ instruction

    CS_port = 0;                         // Bring CS low (active)
    byteout(command);               // Output command & MSb of address
    byteout(address&0xFF);          // Output LSB of address
    *data = bytein();               // Read byte of data
    CS_port = 1;                         // Bring CS high (inactive)
} // end of LowDensByteRead(...)

/********************************************************************
 * Function:        void LowDensPageWrite(unsigned char *data,
 *                                        unsigned int address,
 *                                        unsigned char size)
 *
 * Description:     This function performs a page write operation for
 *                  low-density (<= 4 Kb) devices. It embeds the MSb
 *                  of the memory address into the instruction in
 *                  order to support the 25XX040X. After initiating
 *                  the write cycle, the WIP_Poll function is called
 *                  to determine the end of the cycle. Note that this
 *                  function does not check for page boundary
 *                  violations.
 *
 * Parameters:      data - Byte array of data to be written
 *                  address - Memory location at which to start
 *                  size - Number of bytes to write
 *******************************************************************/
void LowDensPageWrite(unsigned char *data, unsigned int address,
                      unsigned char size)
{
    static unsigned char i;         // Loop counter
    static unsigned char command;   // Temp. variable to store cmd.

    // First embed MSb of address (bit 8) into instruction
    command = address >> 5;         // Align MSb of address
    command &= 0x08;                // Mask off extra bits
    command |= WRITE;               // Merge in WRITE instruction

    WriteEnable();                  // Set WEL bit for write
    CS_port = 0;                         // Bring CS low (active)
    byteout(command);               // Output command & MSb of address
    byteout(address&0xFF);          // Output LSB of address
    for (i = 0; i < size; i++)      // Loop through number of bytes
    {
        byteout(data[i]);           // Write next byte from array
    }
    CS_port = 1;                         // Bring CS high (inactive)
    WIP_Poll();                     // Perform WIP polling
} // end of LowDensPageWrite(...)

/********************************************************************
 * Function:        void LowDensSeqRead(unsigned char *data,
 *                                      unsigned int address,
 *                                      unsigned char size)
 *
 * Description:     This function performs a sequential read operation
 *                  for low-density (<= 4 Kb) devices. It embeds the
 *                  MSb of the memory address into the instruction in
 *                  order to support the 25XX040X.
 *
 * Parameters:      data - Array to store data read
 *                  address - Memory location at which to start
 *                  size - Number of bytes to read
 *******************************************************************/
void LowDensSeqRead(unsigned char *data, unsigned int address,
                    unsigned char size)
{
    static unsigned char i;         // Loop counter
    static unsigned char command;   // Temp. variable to store cmd.

    // First embed MSb of address (bit 8) into instruction
    command = address >> 5;         // Align MSb of address
    command &= 0x08;                // Mask off extra bits
    command |= READ;                // Merge in READ instruction

    CS_port = 0;                         // Bring CS low (active)
    byteout(command);               // Output command & MSb of address
    byteout(address&0xFF);          // Output LSB of address
    for (i = 0; i < size; i++)      // Loop through number of bytes
    {
        data[i] = bytein();         // Read next byte into array
    }
    CS_port = 1;                         // Bring CS high (inactive)
} // end of LowDensSeqRead(...)

/********************************************************************
 * Function:        void HighDensByteWrite(unsigned char data,
 *                                         unsigned int address)
 *
 * Description:     This function performs a byte write operation for
 *                  high-density (> 4 Kb) devices which feature a
 *                  2-byte address structure. After initiating
 *                  the write cycle, the WIP_Poll function is
 *                  called to determine the end of the cycle. Note
 *                  that this function does not check for page
 *                  boundary violations.
 *
 * Parameters:      data - Byte of data to be written
 *                  address - Memory location at which to start
 *******************************************************************/
void HighDensByteWrite(unsigned char data, unsigned int address)
{
    WriteEnable();                  // Set WEL bit for write
    CS_port = 0;                         // Bring CS low (active)
    byteout(WRITE);                 // Output WRITE command
    byteout((address>>8)&0xFF);     // Output MSB of address
    byteout(address&0xFF);          // Output LSB of address
    byteout(data);                  // Write byte of data
    CS_port = 1;                         // Bring CS high (inactive)
    WIP_Poll();                     // Perform WIP polling
} // end of HighDensByteWrite(...)

/********************************************************************
 * Function:        void HighDensByteRead(unsigned char *data,
 *                                        unsigned int address)
 *
 * Description:     This function performs a byte read operation
 *                  for high-density (> 4 Kb) devices which feature a
 *                  2-byte address structure.
 *
 * Parameters:      data - Pointer to store byte of data read
 *                  address - Memory location at which to start
 *******************************************************************/
void HighDensByteRead(unsigned char *data, unsigned int address)
{
    CS_port = 0;                         // Bring CS low (active)
    byteout(READ);                  // Output READ command
    byteout((address>>8)&0xFF);     // Output MSB of address
    byteout(address&0xFF);          // Output LSB of address
    *data = bytein();               // Read byte of data
    CS_port = 1;                         // Bring CS high (inactive)
} // end of HighDensByteRead(...)

/********************************************************************
 * Function:        void HighDensPageWrite(unsigned char *data,
 *                                         unsigned int address,
 *                                         unsigned char size)
 *
 * Description:     This function performs a page write operation for
 *                  high-density (> 4 Kb) devices which feature a
 *                  2-byte address structure. After initiating
 *                  the write cycle, the WIP_Poll function is
 *                  called to determine the end of the cycle. Note
 *                  that this function does not check for page
 *                  boundary violations.
 *
 * Parameters:      data - Byte array of data to be written
 *                  address - Memory location at which to start
 *                  size - Number of bytes to write
 *******************************************************************/
void HighDensPageWrite(unsigned char *data, unsigned int address,
                       unsigned char size)
{
    static unsigned char i;         // Loop counter

    WriteEnable();                  // Set WEL bit for write
    CS_port = 0;                         // Bring CS low (active)
    byteout(WRITE);                 // Output WRITE command
    byteout((address>>8)&0xFF);     // Output MSB of address
    byteout(address&0xFF);          // Output LSB of address
    for (i = 0; i < size; i++)      // Loop through number of bytes
    {
        byteout(data[i]);           // Write next byte from array
    }
    CS_port = 1;                         // Bring CS high (inactive)
    WIP_Poll();                     // Perform WIP polling
} // end of HighDensPageWrite(...)

/********************************************************************
 * Function:        void HighDensSeqRead(unsigned char *data,
 *                                       unsigned int address,
 *                                       unsigned char size)
 *
 * Description:     This function performs a sequential read operation
 *                  for high-density (> 4 Kb) devices which feature a
 *                  2-byte address structure.
 *
 * Parameters:      data - Array to store data read
 *                  address - Memory location at which to start
 *                  size - Number of bytes to read
 *******************************************************************/
void HighDensSeqRead(unsigned char *data, unsigned int address,
                     unsigned char size)
{
    static unsigned char i;         // Loop counter

    CS_port = 0;                         // Bring CS low (active)
    byteout(READ);                  // Output READ command
    byteout((address>>8)&0xFF);     // Output MSB of address
    byteout(address&0xFF);          // Output LSB of address
    for (i = 0; i < size; i++)      // Loop through number of bytes
    {
        data[i] = bytein();         // Read next byte into array
    }
    CS_port = 1;                         // Bring CS high (inactive)
} // end of HighDensSeqRead(...)

/********************************************************************
 * Function:        void WriteStatusReg(unsigned char status)
 *
 * Description:     This function writes the value specified by
 *                  status to the Status Register of a device.
 *                  Note that after performing a WREN instruction, a
 *                  RDSR instruction is executed to check that the
 *                  WEL bit is set. However, currently no error-
 *                  handling is done if the WEL bit is not set.
 *
 * Parameters:      status - Value to be written to Status Register
 *******************************************************************/
void WriteStatusReg(unsigned char status)
{
    WriteEnable();                  // Set WEL bit for write
    CS_port = 0;                         // Bring CS low (active)
    byteout(WRSR);                  // Output WRSR command
    byteout(status);                // Output value to be written
    CS_port = 1;                         // Bring CS high (inactive)
    WIP_Poll();                     // Perform WIP polling
} // end of WriteStatusReg(...)

/********************************************************************
 * Function:        unsigned char ReadStatusReg(void)
 *
 * Description:     This function reads and returns the value of the
 *                  Status Register of a device.
 *******************************************************************/
unsigned char ReadStatusReg(void)
{
    unsigned char retval;           // Return value variable

    CS_port = 0;                         // Bring CS low (active)
    byteout(RDSR);                  // Output RDSR command
    retval = bytein();              // Read Status Register byte
    CS_port = 1;                         // Bring CS high (inactive)

    return retval;                  // Return value
} // end of ReadStatusReg(void)

/********************************************************************
 * Function:        void WriteEnable(void)
 *
 * Description:     This function performs a Write Enable instruction
 *                  to set the WEL bit in the Status Register.
 *                  Note that after performing the WREN instruction, a
 *                  RDSR instruction is executed to check that the
 *                  WEL bit is set. However, currently no error-
 *                  handling is done if the WEL bit is not set.
 *******************************************************************/
void WriteEnable(void)
{
    static unsigned char status;    // Temp. variable to store status reg.

    CS_port = 0;                         // Bring CS low (active)
    byteout(WREN);                  // Output WREN command
    CS_port = 1;                         // Bring CS high (inactive)
    status = ReadStatusReg();       // Check that WEL bit is set
} // end of WriteEnable(void)

/********************************************************************
 * Function:        void WriteDisable(void)
 *
 * Description:     This function performs a Write Disable instruction
 *                  to clear the WEL bit in the Status Register.
 *******************************************************************/
void WriteDisable(void)
{
    CS_port = 0;                         // Bring CS low (active)
    byteout(WRDI);                  // Output WRDS command
    CS_port = 1;                         // Bring CS high (inactive)
} // end of WriteDisable(void)

/********************************************************************
 * Function:        void byteout(unsigned char byte)
 *
 * Description:     This function outputs a single byte onto the
 *                  SPI bus, MSb first.
 *******************************************************************/
void byteout(unsigned char byte)
{
    static unsigned char i;         // Loop counter

    SCK_port = 0;                        // Ensure SCK is low
    for (i = 0; i < 8; i++)         // Loop through each bit
    {
        if (byte & 0x80)            // Check if next bit is a 1
        {
            SDO_port = 1;                 // If a 1, pull SO high
        }
        else
        {
            SDO_port = 0;                 // If a 0, pull SO low
        }
        SCK_port = 1;                    // Bring SCK high to latch bit
        Nop();                      // Avoid violating Thi
        SCK_port = 0;                    // Bring SCK low for next bit
        byte = byte << 1;           // Shift byte left for next bit
    }
} // end of byteout(...)

/********************************************************************
 * Function:        unsigned char bytein(void)
 *
 * Description:     This function inputs a single byte from the
 *                  SPI bus, MSb first.
 *******************************************************************/
unsigned char bytein(void)
{
    static unsigned char i;         // Loop counter
    static unsigned char retval;    // Return value

    retval = 0;
    SCK_port = 0;                        // Ensure SCK is low
    for (i = 0; i < 8; i++)         // Loop through each bit
    {
        retval = retval << 1;       // Shift byte left for next bit
        SCK_port = 1;                    // Bring SCK high
        if (SDI_port == 1)                // Check if next bit is a 1
        {
            retval |= 0x01;         // If a 1, set next bit to 1
        }
        else
        {
            retval &= 0xFE;         // If a 0, set next bit to 0
        }
        SCK_port = 0;                    // Bring SCK low for next bit
    }

    return retval;
} // end of bytein(void)

/********************************************************************
 * Function:        void WIP_Poll(void)
 *
 * Description:     This function performs WIP polling to determine
 *                  the end of the current write cycle. It does this
 *                  by continuously executing a Read Status Register
 *                  operation until the WIP bit (bit 0 of the Status
 *                  Register) is read low.
 *******************************************************************/
void WIP_Poll(void)
{
    static unsigned char status;    // Variable to store Status Reg.

    do {
        status = ReadStatusReg();   // Perform RDSR operation
    } while(status & 0x01);         // Loop while WIP (bit 0) is 1
} // end of WIP_Poll(void)

 

c18 mplabx proje dosyası ve isis çalışma dosyasını indirmek için tıklayınız.

Yardımları için değerli çalışma arkadaşım İlyas KARACA’ya teşekkür ederim.

M. Gökhan BEKEN

10.12.2013

Bir Cevap Yazın