|
|
View previous topic :: View next topic |
Author |
Message |
mytolocia
Joined: 11 Jun 2016 Posts: 1
|
93C56LN EEPROM Reading/Writing Data |
Posted: Wed Oct 05, 2016 6:57 am |
|
|
I have PIC18F25J11 and NS93C56LN Serial EEPROM. My aim is to write a data to an address of EEPROM and read it back properly. Unfortunately, i get irrelevant values (i print them to LCD).
And yes, CCS has driver for "9356"(which didn't work for me) but i have 93C56LN which belongs to "National Semiconductor" and the CCS one is for Microchip version (i assume). So i decided to write my own C file by inspiring from what i read on this forum (bitbanging etc, thanks to Asmboy).
Here is the code. Hope i can find what i am doing wrong. Thank you in advance.
Code: |
#include <main.h>
#include <9356_5.c>
#include <LCD.c>
int16 a;
int8 address=0b00001111;
int16 data=0b0000000000000011; // ilgili adrese 3 yaz
void main()
{
setup_comparator(NC_NC_NC_NC); // C portunun üzerindeki comparatoru kapat.
Enable_ext_EEPROM();
delay_ms(10);
write_ext_eeprom(address,data);
while(TRUE)
{
a = read_ext_eeprom(address);
printf(lcd_putc,"\f %Lu",a);
delay_ms(1000);
}
} |
<9356_5.c>
Code: |
#define EEPROM_SELECT PIN_C2
#define EEPROM_CLK PIN_C3
#define EEPROM_DI PIN_C4
#define EEPROM_DO PIN_C5
void Enable_ext_EEPROM()
{
int i;
unsigned int16 work=0b10011000000; // S(1) + OP(00) + 11XXXXXX
#bit pob=work.15
output_low(EEPROM_DI);
delay_cycles(4);
output_low(EEPROM_CLK);
delay_cycles(4);
output_low(EEPROM_SELECT);
delay_cycles(4);
output_high(EEPROM_SELECT);
for(i=1;i<=11;++i)
{
delay_cycles(2);
if(pob) output_high(EEPROM_DI );
else output_low(EEPROM_DI);
output_high(EEPROM_CLK);
work <<=1;
output_low(EEPROM_CLK);
}
output_low(EEPROM_SELECT);
delay_cycles(4);
output_low(EEPROM_DI);
}
void Disable_ext_EEPROM()
{
int cmd[2];
int i;
output_low(EEPROM_DI);
output_low(EEPROM_CLK);
output_low(EEPROM_SELECT);
cmd[0]=0x00;
cmd[1]=0x08;
for(i=1;i<=4;++i)
shift_left(cmd,2,0);
output_high(EEPROM_SELECT);
for(i=1;i<=12;++i)
{
output_bit(EEPROM_DI, shift_left(cmd,2,0));
output_high(EEPROM_CLK);
output_low(EEPROM_CLK);
}
output_low(EEPROM_DI);
output_low(EEPROM_SELECT);
}
void write_ext_eeprom(int8 address, int16 data)
{
int i,k,z;
unsigned int8 work=0b10100000;
#bit pob=work.7
#bit pob2=address.7
#bit pob3=data.15
output_high(EEPROM_SELECT);
delay_cycles(4);
for(i=1;i<=4;++i) // S(1) + OP(01) + A7(dont care- 0);
{
delay_cycles(2);
if(pob) output_high(EEPROM_DI );
else output_low(EEPROM_DI);
output_high(EEPROM_CLK);
work <<=1;
output_low(EEPROM_CLK);
}
for(i=k;k<=7;++k) // Address A6-A0
{
delay_cycles(2);
if(pob2) output_high(EEPROM_DI );
else output_low(EEPROM_DI);
output_high(EEPROM_CLK);
address <<=1;
output_low(EEPROM_CLK);
}
for(z=1;z<=16;++z) // Data A15-A0
{
delay_cycles(2);
if(pob3) output_high(EEPROM_DI );
else output_low(EEPROM_DI);
output_high(EEPROM_CLK);
data <<=1;
output_low(EEPROM_CLK);
}
output_low(EEPROM_SELECT);
delay_cycles(2);
//output_low(EEPROM_DI);
}
int16 read_ext_eeprom(int8 address)
{
int i,k,z;
int16 data;
unsigned int8 work=0b11000000;
#bit pob=work.7
#bit pob2=address.7
output_high(EEPROM_SELECT);
for(i=1;i<=4;++i) // S(1) + OP(10) + A7 (dont care - 0 )
{
delay_cycles(2);
if(pob) output_high(EEPROM_DI );
else output_low(EEPROM_DI);
output_high(EEPROM_CLK);
work <<=1;
output_low(EEPROM_CLK);
}
for(k=1;k<=7;++k) //A6-A0 Address
{
delay_cycles(2);
if(pob2) output_high(EEPROM_DI );
else output_low(EEPROM_DI);
output_high(EEPROM_CLK);
address <<=1;
output_low(EEPROM_CLK);
}
for(z=1;z<=16;z++){ // D15-D0 Okuma
shift_left(&data,2,input(EEPROM_DO));
output_low(EEPROM_CLK); // CLOCK düşün kenarında EEPROM'dan data geliyor.
output_high(EEPROM_CLK);
}
output_low(EEPROM_SELECT);
return(data);
}
} |
Operation Table
93C56LN Datasheet :
panda-bg.com/datasheet/1562-050607-93C56LN-NS.pdf |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Oct 05, 2016 12:37 pm |
|
|
Quote: | And yes, CCS has driver for "9356"(which didn't work for me) but i have
93C56LN which belongs to "National Semiconductor" and the CCS one is
for Microchip version (i assume). |
Can you post a list of the differences that you noticed between the
Microchip eeprom and the National Semiconductor one ?
I could do it by comparing the data sheets, but if you've already done it,
then it would be easier if you posted the list.
I wrote a software SPI driver for the Microchip 93LC56B (x16 org).
See if this works for you:
http://www.ccsinfo.com/forum/viewtopic.php?t=38064 |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Thu Oct 06, 2016 1:47 am |
|
|
There is a comment. Use delay_us, not delay_cycles.
I can't tell how long any of the delays actually are. He doesn't post his clock line. The PIC could be running at 48MHz. If so, delay_cycles(4), gives 4/12000000 sec. 0.33uSec. The chip has a minimum tCs, of 1uSec....
Why fiddle going DIY?. CCS has a nice software SPI driver available for you in #USE SPI (this can be set to use software or hardware), and in software mode this can do variable length operations. The whole thing can be done in about twenty lines using CCS code, with a much higher chance of success. DIY solutions were necessary some years ago, but with the #USE, have become rather pointless. |
|
|
Ttelmah
Joined: 11 Mar 2010 Posts: 19538
|
|
Posted: Thu Oct 06, 2016 2:52 am |
|
|
I've taken a few minutes, to type in a basic test program to show what I mean:
Code: |
#include <18F25J11.h>
//test driver for National NM9356/66
#device ADC=10
#fuses NOWDT, NOXINST, STVREN
#fuses INTRC_PLL_IO, NOFCMEN, NOPROTECT
#fuses NOIOL1WAY, LPT1OSC
#use delay(internal=32MHz)
//Basic debugging setup, maximum clock rate on internal oscillator
#use RS232(UART1, baud=9600, parity=N, bits=8, ERRORS)
//standard RS232 I/O
#define EEPROM_CS PIN_C2
#define EEPROM_CLK PIN_C3
#define EEPROM_DI PIN_C4
#define EEPROM_DO PIN_C5 //connection names at the memory
#use SPI(DO=EEPROM_DI, DI=EEPROM_DO, CLK=EEPROM_CLK, MODE=0, FORCE_SW, STREAM=NM93)
//setup SPI. My output to input on chip, input to output etc..
//by default will clock as fast as possible (chip supports 3MHz).
//Microwire is mode0 only.
#define READ93 (int16)0b11000000000
#define WRITE93 (int16)0b10100000000
#define WEN93 (int16)0b10011000000
#define ERASE93 (int16)0b11100000000
#define ERAL93 (int16)0b10010000000
#define WRALL93 (int16)0b10001000000
#define WDS93 (int16)0b10000000000
//NM93C56/66 instructions
#define NM93C66 FALSE //set TRUE to use 66, instead of 56
void enable_write93(void)
{
//enable write mode
output_high(EEPROM_CS);
spi_xfer(NM93, WEN93, 11); //clock out 11 bit write enable command
output_low(EEPROM_CS);
}
void disable_write93(void)
{
//disable write mode
output_high(EEPROM_CS);
spi_xfer(NM93, WDS93, 11); //clock out 11 bit write disable command
output_low(EEPROM_CS);
}
int16 ReadWord_from93(int8 address)
{
//read a 16bit word from chip 7 bit address for 56, or 8 for 66
int16 tempL;
if (!NM93C66)
address &= 0x7F; //only 7 bit addresses for 56
output_high(EEPROM_CS);
spi_xfer(NM93, READ93 | address, 11); //clock out 11 bits
tempL=spi_xfer(NM93, 0L, 11);
output_low(EEPROM_CS);
return tempL;
}
int1 WriteWord_to93(int8 address, int16 data)
{
//write a 16 bit word to chip
int1 status;
int8 loop=0;
if (!NM93C66)
address &= 0x7F; //only 6 bit addresses for 56
enable_write93(); //enable write mode
output_high(EEPROM_CS);
spi_xfer(NM93, WRITE93 | address, 11); //clock out 11 bits
spi_xfer(NM93, data, 16); //send 16 bits of data
output_low(EEPROM_CS);
do
{//Modifying to wait for status high - should be up to 10mSec
delay_ms(1);
output_high(EEPROM_CS);
//our DI is now the status from the chip
status = input(EEPROM_DO);
output_low(EEPROM_CS); //deselect again
} while ((status==0) && (++loop<12));
//should get here before 12 counts, with status==1
//if reach here with status==0, there has been a problem
//Now need to disable write mode
delay_us(1);
disable_write93();
return status;
}
void main()
{
int16 val16;
int16 tostore=0xAA55; //initial test value
int1 status;
output_low(EEPROM_CS); //ensure starts with CS low.
output_low(EEPROM_CLK); //and clock
while(TRUE)
{
//Now a basic test.
//First try reading address 0
val16=ReadWord_from93(0);
//send to serial
printf("First time chip = %Lu\r\n",val16);
//now try changing this, and get the chip's status after command
status=WriteWord_to93(0, tostore++);
//change the value so loop will give different on second pass
//Read the value again to see if it worked
val16=ReadWord_from93(0);
//display what happened.
printf("status = %u, read back %Lu\r\n", status, val16);
//Now stop, and only repeat if a 'line feed' is sent on serial
while (getc() != '\n')
;
}
}
|
Haven't got a chip handy to test, but this should be close to right.
Have just modified the code to test the chip status at 1mSec intervals, and exit the write as soon as this goes high. Should be faster than just waiting. If it stays low for >10mSec, then there is a problem (will timeout at 12mSec), and exit. |
|
|
|
|
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 vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|