Saturday, February 17, 2024

PIC16F887 SPI 93C46B EEPROM XC8 Example

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. 

PIC16F887 SPI 93AA46B EEPROM XC8 Example
Schematic Diagram

This chip also has a Dual In Line Package (DIP-8) allow the hobbyist to prototype the circuit easily. 

PIC16F887 SPI 93AA46B EEPROM XC8 Example
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.

PIC16F887 SPI 93AA46B EEPROM XC8 Example
SPI Commands
 

The SB and Opcode is a one byte data. For example, the READ command is 0b110 or 0x06.

PIC16F887 SPI 93C46B EEPROM XC8 Example
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,

  1. Raise the Chip Select (CS) pin high
  2. Send the ERASE command 0x07
  3. Send the Address
  4. 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

  1. Raise the CS pin
  2. Send the EWEN command 0x04
  3. Send the data 0xC0
  4. Lower the CS pin

Then we can proceed the data writing command. That's,

  1. Raise the CS pin
  2. Send the WRITE command 0x05
  3. Send the the memory address
  4. Send the 16-bit data (2 bytes)
  5. Lower the CS pin

To read from any memory address we must do the following sequence,

  1. Raise the CS pin
  2. Send the READ command 0x06
  3. Send the address of the memory
  4. Receive the two-byte (16-bit) data packages
  5. Lower the CS pin
 
PIC16F887 SPI 93AA46B EEPROM XC8 Example
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.

  1. /*
  2.  * File: main.c
  3.  * Author: Admin
  4.  *
  5.  * Created on February 17, 2024, 6:59 PM
  6.  */
  7.  
  8. #include <xc.h>
  9. #include "config.h"
  10.  
  11. #define _XTAL_FREQ 8000000UL
  12.  
  13. #define CS RC2
  14. #define SCK RC3
  15. #define SDI RC4
  16. #define SDO RC5
  17.  
  18. const char EWEN = 0x04;
  19. const char READ = 0x06;
  20. const char WRITE= 0x05;
  21.  
  22. const char clock_time=1;
  23.  
  24. void spi_write(uint8_t data){
  25. for(int8_t i=7;i>=0;i--){
  26. SCK=0;
  27. if(data&(1<<i)) SDO=1;
  28. else SDO=0;
  29. __delay_us(clock_time);
  30. SCK=1;
  31. __delay_us(clock_time);
  32. }
  33. SCK=0;
  34. SDO=0;
  35. }
  36.  
  37. void spi_write_16(uint16_t data){
  38. for(int8_t i=15;i>=0;i--){
  39. SCK=0;
  40. if(data&(1<<i)) SDO=1;
  41. else SDO=0;
  42. __delay_us(clock_time);
  43. SCK=1;
  44. __delay_us(clock_time);
  45. }
  46. SCK=0;
  47. SDO=0;
  48. }
  49.  
  50. void write_93AA46B(uint8_t address, uint16_t data){
  51. CS=1;
  52. spi_write(EWEN);
  53. spi_write(0xC0);
  54. CS=0;
  55. __delay_us(100);
  56. CS=1;
  57. spi_write(WRITE);
  58. spi_write(address);
  59. spi_write_16(data);
  60. CS=0;
  61. __delay_ms(10);
  62. }
  63.  
  64. uint16_t read_93AA46B(uint8_t address){
  65. uint16_t data_h=0,data_l=0,data=0;
  66.  
  67. CS=1;
  68. spi_write(READ);
  69. spi_write(address);
  70. __delay_us(clock_time);
  71.  
  72. for(int16_t i=16;i>=0;i--){
  73. SCK=0;
  74. if(SDI==1) data|=(1<<i);
  75. __delay_us(clock_time);
  76. SCK=1;
  77. __delay_us(clock_time);
  78. }
  79. CS=0;
  80. SCK=0;
  81. return data;
  82. }
  83.  
  84. void main(void) {
  85. uint16_t data=0;
  86. OSCCONbits.IRCF=7;
  87. PORTC=0;
  88. TRISC=0x00;
  89. TRISC4=1;
  90. PORTD=0;
  91. TRISD=0;
  92.  
  93. while(1){
  94. for(uint8_t i=0;i<8;i++){
  95. uint16_t temp=(1<<i)<<8;
  96. write_93AA46B(i,temp);
  97. data=read_93AA46B(i);
  98. PORTD=data>>8;
  99. __delay_ms(100);
  100. }
  101. PORTD=0;
  102. __delay_ms(2000);
  103. for(uint16_t i=0;i<255;i++){
  104. write_93AA46B(0,i<<8);
  105. data=read_93AA46B(0);
  106. PORTD=data>>8;
  107. __delay_ms(100);
  108. }
  109. PORTD=0;
  110. __delay_ms(2000);
  111. }
  112. return;
  113. }
  114.  
  115.  

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 SPI 93AA46B EEPROM XC8 Example
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

Search This Blog

Labels

25AA010A (1) 8051 (7) 93AA46B (1) ADC (30) Analog Comparator (1) Arduino (15) ARM (6) AT89C52 (7) ATMega32 (54) AVR (57) CCS PICC (28) DAC (1) DHT11 (2) Display (105) Distance Sensor (3) DS18B20 (3) dsPIC (2) dsPIC30F1010 (2) EEPROM (5) Environment Sensor (4) esp8266 (1) I2C (29) Input/Output (67) Interrupt (19) Keil (5) Keypad (10) LCD (46) Master/Slave (1) MAX7221 (1) MCP23017 (5) MCP23S17 (4) Meter (3) MikroC (2) Motor (15) MPLABX (66) Nokia 5110 LCD (3) OLED (2) One-Wire (6) Oscillator (8) PCB (6) PCD8544 (3) PCF8574 (5) PIC (107) PIC12F (2) PIC16F628A (2) PIC16F630 (1) PIC16F716 (3) PIC16F818 (10) PIC16F818/819 (2) PIC16F84A (15) PIC16F876A (1) PIC16F877A (9) PIC16F88 (1) PIC16F887 (60) PIC18 (19) PIC18F1220 (4) PIC18F2550 (3) PIC18F4550 (12) PWM (11) RTC (8) Sensor (10) SH1106 (1) Shift Register (11) Shift Registers (2) SPI (24) STM32 (6) STM32 Blue Pill (6) STM32CubeIDE (6) STM32F103C8T6 (6) SysTick (3) temperature sensor (11) Thermometer (21) Timer/Counter (30) TM1637 (2) UART (7) Ultrasonic (4) Voltmeter (7) WDT (1) XC16 (2) XC8 (94)