Hello
I have SRAM 23LC1024 chip and I want to write a value to the SRAM chip and then read it.
But it doesn't seem to work...
Can you help?
Here is my code:
sbit Chip_Select at RD2_bit;
sbit Chip_Select_Direction at TRISD2_bit;
unsigned char read_bytes = 0;
const char READ = 0x03;
const char WRITE = 0x02;
void InitMain()
{
Chip_Select_Direction = 0; // Set CS# pin as Output
Chip_Select = 1; // Deselect DAC
SPI1_Init();
//Delay_ms(100);
}
void Write_SRAM(long int Address, unsigned char Data)
{
Chip_Select = 0;
SPI1_Write(WRITE);
SPI1_Write((Address >> 16) & 0xFF); //24 bit adress
SPI1_Write((Address >> & 0xFF);
SPI1_Write(Address & 0xFF);
SPI1_Write(Data);
Chip_Select = 1;
}
int Read_SRAM(long int Address)
{
Chip_Select = 0;
SPI1_Write(READ);
SPI1_Write((Address >> 16) & 0xFF);
SPI1_Write((Address >> & 0xFF);
SPI1_Write(Address & 0xFF);
read_bytes = SPI1_Read(0);
Chip_Select = 1;
return read_bytes;
}
void main()
{
long int Address = 0x000;
unsigned char Data = 0x05;
unsigned char Data2;
unsigned char txt[4];
ANSEL = 0;
ANSELH = 0;
/*
TRISC3_bit = 0; //SCK
TRISC4_bit = 1; //SDI
TRISC5_bit = 0; //SDA
*/
UART1_Init(9600);
delay_ms(100);
InitMain();
Write_SRAM(Address, Data);
Data2 = Read_SRAM(Address);
ByteToStr(Data2, txt);
while (1)
{
UART1_Write(txt);
Delay_ms(1000);
}
}
SPI 16F887 SPI1_Read doesn't work
Re: SPI 16F887 SPI1_Read doesn't work
Hi,
The SPI library fro the 16F887 works OK. maybe there is an issue with the communication with the SRAM 23LC1024.
Regards,
Filip.
The SPI library fro the 16F887 works OK. maybe there is an issue with the communication with the SRAM 23LC1024.
Regards,
Filip.
-
- Posts: 6
- Joined: 16 Dec 2013 16:50
Re: SPI 16F887 SPI1_Read doesn't work
I know this is old topic ... but anyway I am trying to do the same thing and it does'nt work.
I looked on web for example on how to save and write to SPI eeprom and I found that
you need to write to buffer before data are sent to eeprom.
Does MikroE library takes care of that and I don't need that in my code?
I am using PIC16F1789 and eeprom is ST95020WP.
So this code shoul work:
//RC3 is SCK
//RC4 is SDI
//RC5 is SDO
//RB4 is SS
sbit CS at RB4_bit;
void spi_eeprom_write(unsigned int address,unsigned int value)
{
SPI1_Write(0x02); // write command for writing data
SPI1_Write(address >> ;
SPI1_Write(address);
SPI1_Write(value); //write value
CS = 1; // disable
}
unsigned char spi_eeprom_read(unsigned int address) //
{
CS = 0; // enable
SPI1_Write(0x03); // write instruction for read data
SPI1_Write(address >> ;
SPI1_Write(address);
value = SPI1_Read(0); //read byte
CS = 1; // disable
return value;
}
Thank you for your ansver.
I looked on web for example on how to save and write to SPI eeprom and I found that
you need to write to buffer before data are sent to eeprom.
Does MikroE library takes care of that and I don't need that in my code?
I am using PIC16F1789 and eeprom is ST95020WP.
So this code shoul work:
//RC3 is SCK
//RC4 is SDI
//RC5 is SDO
//RB4 is SS
sbit CS at RB4_bit;
void spi_eeprom_write(unsigned int address,unsigned int value)
{
SPI1_Write(0x02); // write command for writing data
SPI1_Write(address >> ;
SPI1_Write(address);
SPI1_Write(value); //write value
CS = 1; // disable
}
unsigned char spi_eeprom_read(unsigned int address) //
{
CS = 0; // enable
SPI1_Write(0x03); // write instruction for read data
SPI1_Write(address >> ;
SPI1_Write(address);
value = SPI1_Read(0); //read byte
CS = 1; // disable
return value;
}
Thank you for your ansver.
Last edited by tejcasrejca on 01 Dec 2023 08:55, edited 1 time in total.
- IvanJeremic
- mikroElektronika team
- Posts: 316
- Joined: 05 Sep 2022 14:32
Re: SPI 16F887 SPI1_Read doesn't work
Hi,
Did you initialize the SPI before calling the write and read functions?
You can see from the previous answer how he used the SPI interface.
You can also find in the help section in the compiler how to use the SPI functions.
There are also some example in the project explorer.
Regards,
Ivan.
Did you initialize the SPI before calling the write and read functions?
You can see from the previous answer how he used the SPI interface.
You can also find in the help section in the compiler how to use the SPI functions.
There are also some example in the project explorer.
Regards,
Ivan.
-
- Posts: 6
- Joined: 16 Dec 2013 16:50
Re: SPI 16F887 SPI1_Read doesn't work
It is best if I show you all of my code for testing.
//PIC16F1789 and ST95020 SPI eeprom
//RC3 is SCK to Pin 6 on ST95020
//RC4 is SDI to Pin 2 on ST95020
//RC5 is SDO to Pin 5 on ST95020
//RB4 is SS to Pin 1 on ST95020
//WP and HOLD on ST95020 are tied to +5V
#include "__T6963C.h"
sbit T6963C_ctrlcd at RE2_bit; // CD command/data signals pin8 PIC RE2
sbit T6963C_ctrlrd at RA7_bit; // RD read signal pin 6 PIC RA7
sbit T6963C_ctrlwr at RA6_bit; // WR write signal pin 5 PIC RA6
sbit T6963C_ctrlrst at RE1_bit; // RST reset signal pin 10 prej RC4
sbit T6963C_ctrlcd_Direction at TRISE2_bit; // CD command/data signal
sbit T6963C_ctrlrd_Direction at TRISA7_bit; // RD read signal
sbit T6963C_ctrlwr_Direction at TRISA6_bit; // WR write signal
sbit T6963C_ctrlrst_Direction at TRISE1_bit; // RST reset signal
// Signals not used by library, they are set in main function
sbit T6963C_ctrlce at RE0_bit; // CE signal pin 7 PIC RE0
sbit T6963C_ctrlfs at RC0_bit; // FS signal pin 19 PIC RC0
sbit T6963C_ctrlce_Direction at TRISE0_bit; // CE signal direction
sbit T6963C_ctrlfs_Direction at TRISC0_bit; // FS signal direction
sbit CS at RB4_bit;
int stevec, tlong, value, address;
void spi_eeprom_write(unsigned int address,unsigned int value)
{
CS = 0; // enable
SPI1_Write(0x02); // write command for writing data
SPI1_Write(address >> ;
SPI1_Write(address);
SPI1_Write(value); //write value
CS = 1; // disable
}
unsigned char spi_eeprom_read(unsigned int address) //
{
CS = 0; // enable
SPI1_Write(0x03); // write instruction for read data
SPI1_Write(address >> ;
SPI1_Write(address);
value = SPI1_Read(0); //read byte
CS = 1; // disable
return value;
}
void main() {
OSCCON = 0b11111000; //16MHz internal oscilator
CM1CON0 = 0x00; // Disable comparators
CM1CON1 = 0x00;
CM2CON0 = 0x00;
CM2CON1 = 0x00;
CM3CON0 = 0x00;
CM3CON1 = 0x00;
DAC1CON0 = 0x00;
DAC1CON1 = 0x00;
PORTA = 0b00111111;
TRISA = 0b00111111;
PORTB = 0b11000000;
TRISB = 0b11000000;
PORTC = 0b11010000;
TRISC.RC0 = 0; // output signal FS for LCD
TRISC.RC1 = 0; // output for PWM2
TRISC.RC2 = 0; // output for PWM1
TRISC.RC3 = 0; // SCL as output
TRISC.RC4 = 1; // SDI as input
TRISC.RC5 = 0; // SDO ničla ker je nastavljen kot izhod
TRISC.RC6 = 1; // input for key
TRISC.RC7 = 1; // input for key
TRISD = 0x00; // Port D as output
PORTE = 0b00001000;
TRISE = 0b00001000; // Port E as input
ANSELA = 0b00000000; // no analog inputs
ANSELB = 0b00000000;
ANSELC = 0b00000000;
ANSELD = 0b00000000;
ANSELE = 0x00;
APFCON1 = 0b00000000;
APFCON2 = 0b00000100; // SS on pin RB4
T6963C_ctrlce_Direction = 0;
T6963C_ctrlce = 0; // Enable T6963C
T6963C_ctrlfs_Direction = 0; // set font
T6963C_ctrlfs = 0;
delay_ms(1);
T6963C_init(240, 64, ; // Initialize T6963C
T6963C_text(1);
T6963C_cursor(0); // cursor = off
T6963C_panelFill(0); //Clear LCD screen
value = 28; //some randome value for testing
address = 0;
SPI1_Init();
spi_eeprom_write(0x58, value); //some random address for testing
delay_ms(10);
while (1) {
stevec = spi_eeprom_read(0x58); //save to stevec
tlong = stevec / 10;
T6963C_write_char(48+tlong, 10, 0, T6963C_ROM_MODE_XOR);
tlong = stevec % 10;
T6963C_write_char(48+tlong, 11, 0, T6963C_ROM_MODE_XOR);
}
}
//PIC16F1789 and ST95020 SPI eeprom
//RC3 is SCK to Pin 6 on ST95020
//RC4 is SDI to Pin 2 on ST95020
//RC5 is SDO to Pin 5 on ST95020
//RB4 is SS to Pin 1 on ST95020
//WP and HOLD on ST95020 are tied to +5V
#include "__T6963C.h"
sbit T6963C_ctrlcd at RE2_bit; // CD command/data signals pin8 PIC RE2
sbit T6963C_ctrlrd at RA7_bit; // RD read signal pin 6 PIC RA7
sbit T6963C_ctrlwr at RA6_bit; // WR write signal pin 5 PIC RA6
sbit T6963C_ctrlrst at RE1_bit; // RST reset signal pin 10 prej RC4
sbit T6963C_ctrlcd_Direction at TRISE2_bit; // CD command/data signal
sbit T6963C_ctrlrd_Direction at TRISA7_bit; // RD read signal
sbit T6963C_ctrlwr_Direction at TRISA6_bit; // WR write signal
sbit T6963C_ctrlrst_Direction at TRISE1_bit; // RST reset signal
// Signals not used by library, they are set in main function
sbit T6963C_ctrlce at RE0_bit; // CE signal pin 7 PIC RE0
sbit T6963C_ctrlfs at RC0_bit; // FS signal pin 19 PIC RC0
sbit T6963C_ctrlce_Direction at TRISE0_bit; // CE signal direction
sbit T6963C_ctrlfs_Direction at TRISC0_bit; // FS signal direction
sbit CS at RB4_bit;
int stevec, tlong, value, address;
void spi_eeprom_write(unsigned int address,unsigned int value)
{
CS = 0; // enable
SPI1_Write(0x02); // write command for writing data
SPI1_Write(address >> ;
SPI1_Write(address);
SPI1_Write(value); //write value
CS = 1; // disable
}
unsigned char spi_eeprom_read(unsigned int address) //
{
CS = 0; // enable
SPI1_Write(0x03); // write instruction for read data
SPI1_Write(address >> ;
SPI1_Write(address);
value = SPI1_Read(0); //read byte
CS = 1; // disable
return value;
}
void main() {
OSCCON = 0b11111000; //16MHz internal oscilator
CM1CON0 = 0x00; // Disable comparators
CM1CON1 = 0x00;
CM2CON0 = 0x00;
CM2CON1 = 0x00;
CM3CON0 = 0x00;
CM3CON1 = 0x00;
DAC1CON0 = 0x00;
DAC1CON1 = 0x00;
PORTA = 0b00111111;
TRISA = 0b00111111;
PORTB = 0b11000000;
TRISB = 0b11000000;
PORTC = 0b11010000;
TRISC.RC0 = 0; // output signal FS for LCD
TRISC.RC1 = 0; // output for PWM2
TRISC.RC2 = 0; // output for PWM1
TRISC.RC3 = 0; // SCL as output
TRISC.RC4 = 1; // SDI as input
TRISC.RC5 = 0; // SDO ničla ker je nastavljen kot izhod
TRISC.RC6 = 1; // input for key
TRISC.RC7 = 1; // input for key
TRISD = 0x00; // Port D as output
PORTE = 0b00001000;
TRISE = 0b00001000; // Port E as input
ANSELA = 0b00000000; // no analog inputs
ANSELB = 0b00000000;
ANSELC = 0b00000000;
ANSELD = 0b00000000;
ANSELE = 0x00;
APFCON1 = 0b00000000;
APFCON2 = 0b00000100; // SS on pin RB4
T6963C_ctrlce_Direction = 0;
T6963C_ctrlce = 0; // Enable T6963C
T6963C_ctrlfs_Direction = 0; // set font
T6963C_ctrlfs = 0;
delay_ms(1);
T6963C_init(240, 64, ; // Initialize T6963C
T6963C_text(1);
T6963C_cursor(0); // cursor = off
T6963C_panelFill(0); //Clear LCD screen
value = 28; //some randome value for testing
address = 0;
SPI1_Init();
spi_eeprom_write(0x58, value); //some random address for testing
delay_ms(10);
while (1) {
stevec = spi_eeprom_read(0x58); //save to stevec
tlong = stevec / 10;
T6963C_write_char(48+tlong, 10, 0, T6963C_ROM_MODE_XOR);
tlong = stevec % 10;
T6963C_write_char(48+tlong, 11, 0, T6963C_ROM_MODE_XOR);
}
}
-
- Posts: 6
- Joined: 16 Dec 2013 16:50
Re: SPI 16F887 SPI1_Read doesn't work
Can anyone help me with this?
- IvanJeremic
- mikroElektronika team
- Posts: 316
- Joined: 05 Sep 2022 14:32
Re: SPI 16F887 SPI1_Read doesn't work
Hi,
Sorry for the delay.
You can take a look at the examples for the clicks below:
https://www.mikroe.com/eeprom-2-click
https://www.mikroe.com/eeprom-4-click
https://www.mikroe.com/eeprom-7-click
They should be similar to what you are trying to do.
Regards,
Ivan.
Sorry for the delay.
You can take a look at the examples for the clicks below:
https://www.mikroe.com/eeprom-2-click
https://www.mikroe.com/eeprom-4-click
https://www.mikroe.com/eeprom-7-click
They should be similar to what you are trying to do.
Regards,
Ivan.
-
- Posts: 6
- Joined: 16 Dec 2013 16:50
Re: SPI 16F887 SPI1_Read doesn't work
Thoose are for mikrobus examples and are totaly different from help file.
Is there and other example for storing a single variable on external eeprom?
For I2C you have beatifull example and know how to use it.
Tejca
Is there and other example for storing a single variable on external eeprom?
For I2C you have beatifull example and know how to use it.
Tejca
- IvanJeremic
- mikroElektronika team
- Posts: 316
- Joined: 05 Sep 2022 14:32
Re: SPI 16F887 SPI1_Read doesn't work
Hi,
The MikroBUS does not change much, SPI initialized just like when using some other header.
Also i found this code, maybe it will be of help to you:
Regards,
Ivan.
The MikroBUS does not change much, SPI initialized just like when using some other header.
Also i found this code, maybe it will be of help to you:
Code: Select all
/*
SPI_EEPROM.C
SPI EEPROM LIBRARY FOR 25LC** SERIES EEPROMS
If #HOLD not used, set #define NOTHOLD = 0
SPI inits: I make a habit of setting SPI in every routine
as I have many SPI devices on my bus. I use all SPI_Read()'s
because they are queued up, as SPI_Write()'s can overwrite
each other.
I insert asm_nop's for breakpoints for debugging
** STRUCTURE / ARRAY FUNCTIONS **
These routines let you copy an entire structure to/from
the spi_eeprom with one command. For large structs/arrays
THIS CAN TAKE TIME! We must write ONE byte at a time &
allow EEPROM to finish it's write!
Since we want to read/write ONE BYTE at a time, we have
declared a "char *" as the pointer to the variable:
void spi_eeprom_array_xxxxx(char *ptr,int num,int addr)
So this means we have to typecast the address we pass
to routines as a CHAR* (pointer to ONE BYTE). We typecast
the address by using syntax (char*)(&variable).
PARAMETERS:
pointer to object (&foo = address of 1st byte of foo)
number of bytes (using 'sizeof' will always be correct!)
address to write to (up to you to keep from overlapping!)
STRUCTURES/ARRAYS
EXAMPLE: a structure with any data (even other structs)
struct FOO
{
char proportional_val;
char offset_val;
float pid_val;
int whatmeworry[10];
}foo;
// store starting at EEPROM address 0
spi_eeprom_write_array((char*)&foo,sizeof(foo),0);
// read (say on power up to restore all values at once)
spi_eeprom_read_array((char*)&foo,sizeof(foo),0);
example: floats to/from eeprom at address 0:
spi_eeprom_write_array((char*)&floatname,sizeof(float),0);
spi_eeprom_read_array((char*)&floatname,sizeof(float),0);
*/
#define NOTHOLD 1 // using #hold pin
// for simplicity define the instructions
#define READ 0x03 // read data
#define WRITE 0x02 // Write data
#define WREN 0x06 // Set write enable latch
#define WRDI 0x04 // Reset write enable latch
#define RDSR 0x05 // read STATUS register
#define WRSR 0x01 // write STATUS register
unsigned char val;
// function prototypes (can copy to *.h file)
void spi_eeprom_write_byte(int, unsigned char);
unsigned char spi_eeprom_read_byte(int);
unsigned char spi_eeprom_ready(void);
// define your #CS & #HOLD (if used) here!
sbit SPI_EEPROM_CS at RB4_bit;
sbit SPI_EEPROM_CS_Direction at TRISB4_bit;
#ifdef NOTHOLD
sbit SPI_EEPROM_HOLD at RB3_bit;
sbit SPI_EEPROM_HOLD_Direction at TRISB3_bit;
#endif
void spi_eeprom_init(void)
{
SPI_EEPROM_CS_Direction = 0; // output
SPI_EEPROM_CS = 1; // disable
// just setting inactive, can implement in each routine if used
#ifdef NOTHOLD
SPI_EEPROM_HOLD_Direction = 0; // output
SPI_EEPROM_HOLD = 1; // hold active
#endif
asm nop;
}
void spi_eeprom_write_byte(int address, unsigned char value)
{
unsigned char tempchar = 0;
while(spi_eeprom_ready()); // wait if writing
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE,
_SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
SPI_EEPROM_CS = 0; // enable
tempchar = SPI1_Read(WREN); // enable write
SPI_EEPROM_CS = 1; // disable
Delay_us(100);
SPI_EEPROM_CS = 0; // enable
//write instruction
tempchar = SPI1_Read(WRITE); // write
// write address
tempchar = SPI1_Read((unsigned char)address >> 8);
tempchar = SPI1_Read((unsigned char)address & 0x0F);
//write byte
tempchar = SPI1_Read(value);
SPI_EEPROM_CS = 1; // disable
asm nop;
}
unsigned char spi_eeprom_read_byte(int address)
{
unsigned char tempchar = 0;
while(spi_eeprom_ready()); // wait if writing
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE,
_SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
SPI_EEPROM_CS = 0; // enable
tempchar = SPI1_Read(READ); //write instruction
// write address
tempchar = SPI1_Read((unsigned char)address >> 8);
tempchar = SPI1_Read((unsigned char)address & 0x0F);
//read byte
tempchar = SPI1_Read(0);
SPI_EEPROM_CS = 1; // disable
asm nop;
return tempchar;
}
char spi_eeprom_ready(void)
{
unsigned char tempchar = 0xFF; // set to non-zero to be sure we read
// real data (all 0's is normal)
SPI1_Init_Advanced(_SPI_MASTER_OSC_DIV64, _SPI_DATA_SAMPLE_MIDDLE,
_SPI_CLK_IDLE_LOW, _SPI_LOW_2_HIGH);
SPI_EEPROM_CS = 0; // enable
tempchar = SPI1_Read(RDSR); //write instruction
tempchar = SPI1_Read(0); //read byte
SPI_EEPROM_CS = 1; // disable
asm nop;
if(tempchar & 0x01) // test WIP bit
{
return 1;
}
else
{
return 0;
}
}
/************************************
STRUCT/ARRAY FUNCTIONS
*************************************/
void spi_eeprom_read_array(char *ptr,int num,int addr)
{
int count;
for (count=0;count<num;count++)
{
ptr[count]=spi_eeprom_read_byte(addr+count);
}
asm nop; // breakpoint to look at debugger
}
void spi_eeprom_write_array(char *ptr,int num,int addr)
{
int count;
for (count=0;count<num;count++)
{
spi_eeprom_write_byte(addr+count,ptr[count]);
}
asm nop; // breakpoint to look at debugger
}
Ivan.
-
- Posts: 6
- Joined: 16 Dec 2013 16:50
Re: SPI 16F887 SPI1_Read doesn't work
Thank you for the code.
And quick look at the code something feels unlogical or am I missing something.
Especialy this part. SPI1_Read si for reading and WREN is write enable latch.
tempchar = SPI1_Read(WREN);
Is this OK?
And quick look at the code something feels unlogical or am I missing something.
Especialy this part. SPI1_Read si for reading and WREN is write enable latch.
tempchar = SPI1_Read(WREN);
Is this OK?
-
- Posts: 1
- Joined: 05 Jan 2024 10:14
Re: SPI 16F887 SPI1_Read doesn't work
Hi, according to the datasheet for the used memory chip, I think that there is a need to initialize SPI1_Init() in an advanced mode.tejcasrejca wrote: ↑01 Dec 2023 10:05value = 28; //some randome value for testing
address = 0;
SPI1_Init();
spi_eeprom_write(0x58, value); //some random address for testing
delay_ms(10);
-
- Posts: 6
- Joined: 16 Dec 2013 16:50
Re: SPI 16F887 SPI1_Read doesn't work
Hello guys. Sorry it took me so long to write back.
I have finaly made it and it works now.
The biggest problem that I had was with hardware.
JLCPCB made a mistake - I was missing 1,5mm of a track and I totaly overlooked it.
Its a good thing that I have a osciloscope to check if the signals are getting to the eeprom.
The second one was that I have overlooked the size of my eeprom becos it has only 255 byte addresses so
I did'nt need the line (Address >> .
This is all I need to write and read to eeprom.
void Write_SPI(int Address, char stevec) {
Chip_Select = 0;
SPI1_Write(WREN);
Chip_Select = 1;
delay_ms(1);
Chip_Select = 0;
SPI1_Write(write);
SPI1_Write(Address);
SPI1_Write(stevec);
Chip_Select = 1;
}
char Read_SPI(int Address) {
Chip_Select = 0;
SPI1_Write(read);
SPI1_Write(Address);
stevec = SPI1_Read(0);
Chip_Select = 1;
return stevec;
}
Anyway thank you all who have tryed to help me and If we ever meet I would buy you a beer.
Cheers
I have finaly made it and it works now.
The biggest problem that I had was with hardware.
JLCPCB made a mistake - I was missing 1,5mm of a track and I totaly overlooked it.
Its a good thing that I have a osciloscope to check if the signals are getting to the eeprom.
The second one was that I have overlooked the size of my eeprom becos it has only 255 byte addresses so
I did'nt need the line (Address >> .
This is all I need to write and read to eeprom.
void Write_SPI(int Address, char stevec) {
Chip_Select = 0;
SPI1_Write(WREN);
Chip_Select = 1;
delay_ms(1);
Chip_Select = 0;
SPI1_Write(write);
SPI1_Write(Address);
SPI1_Write(stevec);
Chip_Select = 1;
}
char Read_SPI(int Address) {
Chip_Select = 0;
SPI1_Write(read);
SPI1_Write(Address);
stevec = SPI1_Read(0);
Chip_Select = 1;
return stevec;
}
Anyway thank you all who have tryed to help me and If we ever meet I would buy you a beer.
Cheers