The 93AA46B is an 1Kbit Microwire compatible serial EEPROM. It uses the SPI interface to communicate to the microprocessor. It memory is arranged into a 16-bit data per address, that's 64x16-bit. It can handle up to 1000000 erase/write cycles with over 200 years data retention.
Schematic Diagram |
This chip also has a Dual In Line Package (DIP-8) allow the hobbyist to prototype the circuit easily.
Pin Diagram and Description |
The ORG pin does not exist for the 93AA46B. So we must left it unconnected. It has the following commands to read, write, erase, etc.
SPI Commands |
The SB and Opcode is a one byte data. For example, the READ command is 0b110 or 0x06.
93C46B DIP-8 Package |
The Address is one byte data. The data is 16-bit wide, or two bytes.
For example, to erase a specific memory location the controller does the following sequence,
- Raise the Chip Select (CS) pin high
- Send the ERASE command 0x07
- Send the Address
- Lower the Chip Select (CS) pin.
Before we can write data to any address we must enable the EWEN(Erase Write Enable) command first. So
- Raise the CS pin
- Send the EWEN command 0x04
- Send the data 0xC0
- Lower the CS pin
Then we can proceed the data writing command. That's,
- Raise the CS pin
- Send the WRITE command 0x05
- Send the the memory address
- Send the 16-bit data (2 bytes)
- Lower the CS pin
To read from any memory address we must do the following sequence,
- Raise the CS pin
- Send the READ command 0x06
- Send the address of the memory
- Receive the two-byte (16-bit) data packages
- Lower the CS pin
The EWEN Timing Diagram |
In this example, the PIC16F887 write and read data from the 93AA46B SPI EEPROM chip. The data will show on PORTD.
/* * File: main.c * Author: Admin * * Created on February 17, 2024, 6:59 PM */ #include <xc.h> #include "config.h" #define _XTAL_FREQ 8000000UL #define CS RC2 #define SCK RC3 #define SDI RC4 #define SDO RC5 const char EWEN = 0x04; const char READ = 0x06; const char WRITE= 0x05; const char clock_time=1; void spi_write(uint8_t data){ for(int8_t i=7;i>=0;i--){ SCK=0; if(data&(1<<i)) SDO=1; else SDO=0; __delay_us(clock_time); SCK=1; __delay_us(clock_time); } SCK=0; SDO=0; } void spi_write_16(uint16_t data){ for(int8_t i=15;i>=0;i--){ SCK=0; if(data&(1<<i)) SDO=1; else SDO=0; __delay_us(clock_time); SCK=1; __delay_us(clock_time); } SCK=0; SDO=0; } void write_93AA46B(uint8_t address, uint16_t data){ CS=1; spi_write(EWEN); spi_write(0xC0); CS=0; __delay_us(100); CS=1; spi_write(WRITE); spi_write(address); spi_write_16(data); CS=0; __delay_ms(10); } uint16_t read_93AA46B(uint8_t address){ uint16_t data_h=0,data_l=0,data=0; CS=1; spi_write(READ); spi_write(address); __delay_us(clock_time); for(int16_t i=16;i>=0;i--){ SCK=0; if(SDI==1) data|=(1<<i); __delay_us(clock_time); SCK=1; __delay_us(clock_time); } CS=0; SCK=0; return data; } void main(void) { uint16_t data=0; OSCCONbits.IRCF=7; PORTC=0; TRISC=0x00; TRISC4=1; PORTD=0; TRISD=0; while(1){ for(uint8_t i=0;i<8;i++){ uint16_t temp=(1<<i)<<8; write_93AA46B(i,temp); data=read_93AA46B(i); PORTD=data>>8; __delay_ms(100); } PORTD=0; __delay_ms(2000); for(uint16_t i=0;i<255;i++){ write_93AA46B(0,i<<8); data=read_93AA46B(0); PORTD=data>>8; __delay_ms(100); } PORTD=0; __delay_ms(2000); } return; }
I use the bit-banging SPI to process the data transfer and receive. However I use only one byte of its 16-bit data.
PIC16F887 Prototyping Board |
I use my own PIC16F887 Prototyping Board to test this program. Click here to download its source file.
No comments:
Post a Comment