Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

WRITE READ SPI DATA in Oshonsoft

camerart

Well-Known Member
Hi, EDIT: As addresses appear to be a bad idea, I've changed the thread title
I'm setting up a SLAVE PIC to another MASTER PIC, and want to put a STRING of DATA into a specific memory locations.
So far I've succeded in adding the DATA into EEPROM memory, but is this the best place?
The DATA will be updated constantly and very fast.

Camerart.
 
Last edited:
How much data?, how often?, and does it need to be permanently stored?.

To cope with pretty well anything, I would suggest adding a FRAM memory chip, like EEPROM but much faster to write to (no delays required). You can get them as I2C or SPI, I use I2C ones - and the exact same code as for external I2C EEPROM's, with the simple change of using a #define to remove the write delays. The ones I use are 32KByte.
 
How much data?, how often?, and does it need to be permanently stored?.

To cope with pretty well anything, I would suggest adding a FRAM memory chip, like EEPROM but much faster to write to (no delays required). You can get them as I2C or SPI, I use I2C ones - and the exact same code as for external I2C EEPROM's, with the simple change of using a #define to remove the write delays. The ones I use are 32KByte.
Hi N,
At the moment, there are 35xBYTES, this may grow slightly, but I don't predict by much.

It would take a lot of re-design to add a chip, so if possible I would like to use the 18F4431 PIC memory.
C.
 
Hi N,
At the moment, there are 35xBYTES, this may grow slightly, but I don't predict by much.

It would take a lot of re-design to add a chip, so if possible I would like to use the 18F4431 PIC memory.
C.
In which case the data eeprom is probably fine, as you don't need much space - the data EEPROM has a MUCH higher number of write cycles than the program memory, which would be a very bad idea.

But you mention 'continually', and give no idea how fast that is - it could be 'continually on the first of every month', you also give no idea how fast 'fast' is - but as you're using the data EEPROM, presumably you really meant 'slow'.

If by 'continually' you mean every few milliseconds for ever, then get a FRAM - even the data EEPROM will soon wear out at that usage.

Perhaps you might like to explain exactly what you're trying to do?, and why you feel this would be the best way? - it seems like you've not thought it through, and not paid attention to the original hardware design either. Storing it in GPR's (RAM) would make the most sense, and if you need it storing, then store it to EEPROM when the device shuts down - a little hardware design would allow you to do so if the power fails.
 
In which case the data eeprom is probably fine, as you don't need much space - the data EEPROM has a MUCH higher number of write cycles than the program memory, which would be a very bad idea.

But you mention 'continually', and give no idea how fast that is - it could be 'continually on the first of every month', you also give no idea how fast 'fast' is - but as you're using the data EEPROM, presumably you really meant 'slow'.

If by 'continually' you mean every few milliseconds for ever, then get a FRAM - even the data EEPROM will soon wear out at that usage.

Perhaps you might like to explain exactly what you're trying to do?, and why you feel this would be the best way? - it seems like you've not thought it through, and not paid attention to the original hardware design either. Storing it in GPR's (RAM) would make the most sense, and if you need it storing, then store it to EEPROM when the device shuts down - a little hardware design would allow you to do so if the power fails.
Hi N,
This is part of a project, I've been working on for years, and you've contributed to it before.
During the project things have been changed, so what worked before, may not be able to work as it was then.

The PIC is an 18F4431, and has QEI, voltage measurements and GPS DATA, which needs to be sent to the MASTER PIC when called for.
It has been working, but so far never got in SYNC, I think because of timing.
There are other SLAVE peripherals connected to the MASTER via SPI e,g, Altimeter, compass etc, all working happily.
When the PIC as SLAVE is chip selected, it's DATA needs to be sent via SPI also.
In the other peripherals a READ ADDRESS BYTE is sent to them, and they look in that addresss for that DATA.
After many exchanges on this and other forums, no accurate solution has appeared, so I'm trying to guess how a peripheral would store DATA in its memory, so that I can emulate it with this PIC.
I have now succeded in storing DATA in this PICs memory, as mentioned, so next I want to get the MASTER to request it and prove this works.
If it works, then I can change thing a bit and change the type of memory, i,e, RAM.

EDIT: The DATA is READ by the SLAVE PIC and put in RAM, but I need to PARSE out BYTEs for SPI to MASTER, so maybe it can be done by READing the actual RAM?
C
 
Last edited:
Don't store the data in program memory or eeprom, and don't use absolute memory addresses.

Think of the "read address byte 0" request form the master as "read parameter #0", and then the slave can read/write the data from where ever it needs to. That way as things change in the slave it won't effect the master commands.
 
Don't store the data in program memory or eeprom, and don't use absolute memory addresses.

Think of the "read address byte 0" request form the master as "read parameter #0", and then the slave can read/write the data from where ever it needs to. That way as things change in the slave it won't effect the master commands.
Hi T,
How is that particular memory array chosen from the others on the PIC?
C
 
Hi N,
This is part of a project, I've been working on for years, and you've contributed to it before.
During the project things have been changed, so what worked before, may not be able to work as it was then.

The PIC is an 18F4431, and has QEI, voltage measurements and GPS DATA, which needs to be sent to the MASTER PIC when called for.
It has been working, but so far never got in SYNC, I think because of timing.
There are other SLAVE peripherals connected to the MASTER via SPI e,g, Altimeter, compass etc, all working happily.
When the PIC as SLAVE is chip selected, it's DATA needs to be sent via SPI also.
In the other peripherals a READ ADDRESS BYTE is sent to them, and they look in that addresss for that DATA.
After many exchanges on this and other forums, no accurate solution has appeared, so I'm trying to guess how a peripheral would store DATA in its memory, so that I can emulate it with this PIC.
I have now succeded in storing DATA in this PICs memory, as mentioned, so next I want to get the MASTER to request it and prove this works.
If it works, then I can change thing a bit and change the type of memory, i,e, RAM.

EDIT: The DATA is READ by the SLAVE PIC and put in RAM, but I need to PARSE out BYTEs for SPI to MASTER, so maybe it can be done by READing the actual RAM?
C
I'm totally confused as to what you're trying to to do? - but you seem to be making it vastly more complicated than it need be?. But there seems to be zero reason for writing to non-volatile memory?.

If I'm using two PIC's (or one PIC, and say an ESP32 etc.) I simply connect them via a two wire serial (RS232 style) interface.

Both devices are sat looking to receive serial data, and doing anything else that needs doing in the meantime - one could be updating the display, the other could be reading sensors. So the master could send a command to the slave, asking for a specific reading (for example battery voltage), the slave returns the value, and the master processes it (if needed) and displays it accordingly. Likewise, the slave may discover an event that the master needs to know about - like the battery is below acceptable voltage, and it can then send a command to the master informing it of the issue, and the master can take appropriate action, such as shutting the unit down.

A big advantage of this type of connection (other than it's simplicity) if that you can test each part individually using a terminal program on a PC.

One of my current two processor projects uses a PIC and an ESP32 with a SIM800 modem - the commands received from the ESP32 are these:

C:
// list of incoming commands to search for
#define NumCommands 13

char master_list[NumCommands][10] = {
                                  "READING=",
                                  "SIGNAL=",
                                  "NETWORK",
                                  "APNOK",
                                  "BATTERY=",
                                  "SHUTDOWN=",
                                  "NETFAIL",
                                  "APNFAIL",
                                  "ESP32=",
                                  "OK",
                                  "REPLY",
                                  "IMEI=",
                                  "ERROR="
                              };

Some are single words (NETWORK, OK etc.), while ones that end in '=' have values, one or more, delimited with commas, attached to them. Once a full command (terminated by CR/LF) is received, the data is parsed and processed accordingly.

The serial ports are all interrupt driven, and use a circular buffer large enough to hold more than the largest anticipated data, so there's no issue with it missing any commands.

The slave operates in a similar manner, with a list of available commands to look for.

The PIC part does display, keyboard reading, and battery charging (including the actual buck PWM charging generation), the ESP32 does all the modem related stuff. Oh, and the PIC also stores any altered settings in EEPROM, so that next time you turn it ON, it comes on set to how you left it - it's a nice feature of most PIC's.
 
I'm totally confused as to what you're trying to to do? - but you seem to be making it vastly more complicated than it need be?. But there seems to be zero reason for writing to non-volatile memory?.

If I'm using two PIC's (or one PIC, and say an ESP32 etc.) I simply connect them via a two wire serial (RS232 style) interface.

Both devices are sat looking to receive serial data, and doing anything else that needs doing in the meantime - one could be updating the display, the other could be reading sensors. So the master could send a command to the slave, asking for a specific reading (for example battery voltage), the slave returns the value, and the master processes it (if needed) and displays it accordingly. Likewise, the slave may discover an event that the master needs to know about - like the battery is below acceptable voltage, and it can then send a command to the master informing it of the issue, and the master can take appropriate action, such as shutting the unit down.

A big advantage of this type of connection (other than it's simplicity) if that you can test each part individually using a terminal program on a PC.

One of my current two processor projects uses a PIC and an ESP32 with a SIM800 modem - the commands received from the ESP32 are these:

C:
// list of incoming commands to search for
#define NumCommands 13

char master_list[NumCommands][10] = {
                                  "READING=",
                                  "SIGNAL=",
                                  "NETWORK",
                                  "APNOK",
                                  "BATTERY=",
                                  "SHUTDOWN=",
                                  "NETFAIL",
                                  "APNFAIL",
                                  "ESP32=",
                                  "OK",
                                  "REPLY",
                                  "IMEI=",
                                  "ERROR="
                              };

Some are single words (NETWORK, OK etc.), while ones that end in '=' have values, one or more, delimited with commas, attached to them. Once a full command (terminated by CR/LF) is received, the data is parsed and processed accordingly.

The serial ports are all interrupt driven, and use a circular buffer large enough to hold more than the largest anticipated data, so there's no issue with it missing any commands.

The slave operates in a similar manner, with a list of available commands to look for.

The PIC part does display, keyboard reading, and battery charging (including the actual buck PWM charging generation), the ESP32 does all the modem related stuff. Oh, and the PIC also stores any altered settings in EEPROM, so that next time you turn it ON, it comes on set to how you left it - it's a nice feature of most PIC's.
Hi N,
As mentioned this has been developed over years, and what you are suggesting was how it worked previously, with a switch between different UARTs.

The UART is used for RADIO communication, between another 2xPICs also connected via SPI.

Best keep it as simple as possible.

I need a way that the MASTER can send an address to the SLAVE via SPI so that the SLAVE returns the BYTE stored in that address.

Her's an example showing 3x memory arrays, say I want the 1st byte of the green array.

EDIT: some of what I wrote above is not quite right, but you get the idea!
C.
 

Attachments

  • memories.jpg
    memories.jpg
    133.1 KB · Views: 129
Last edited:
Why can't you just use a variable array for this? Why store and retrieve it from memory?
 
The master tells the slave "send me array element 1" and the slave does so.

Either I'm missing something or you're trying to make this way more difficult than needed.
 
You're just momentarily holding data until the master wants it, right? You don't need nonvolatile memory to archive the data?
 
When the slave has to return data to the master your code has to read a variable and put it into the SSPBUF register so that on the next transaction the master will get it.

That's the way it works... there's no automatic "read from address xxx and transfer it" with the MSSP SPI peripheral. You have to code it.

Master-slave SPI with the MSSP peripheral requires code on both ends, and as I've mentioned before it's surprisingly harder to get it working reliably than it appears that first glance. There's no buffering and no synchronization.
 
  • Like
Reactions: jjw
Hi.,
I've had advice from this and other forums, and much of it seems as if it is what many of you are suggesting, and I've had it working with approval from the forums, but I never got the DATA to be synchronised, and my tests seemed to suggest it was timing related, so this is why I'm trying to guess how, the working peripherals are working.
They all have the MASTER sending the SLAVE the address where the DATA is in the SLAVE, as indicated in the D/S
This is what I'm trying to do.

It appears that my question is difficult to either understand, or the suggestions want me to try what I've tried before. I'm not sure.

The tests, I'm trying seem to be almost working, as I guess it all through.
Perhaps it's best, that I carry on with my existing tests, and I'll report back.
Thanks.
C
 
Hi.,
I've had advice from this and other forums, and much of it seems as if it is what many of you are suggesting, and I've had it working with approval from the forums, but I never got the DATA to be synchronised, and my tests seemed to suggest it was timing related, so this is why I'm trying to guess how, the working peripherals are working.
They all have the MASTER sending the SLAVE the address where the DATA is in the SLAVE, as indicated in the D/S
This is what I'm trying to do.

It appears that my question is difficult to either understand, or the suggestions want me to try what I've tried before. I'm not sure.

The tests, I'm trying seem to be almost working, as I guess it all through.
Perhaps it's best, that I carry on with my existing tests, and I'll report back.
Thanks.
C
There is no timing?, or 'synchronisation', it's not working because you don't know what you're doing and you're making it FAR too complicated. As we've explained, one device simply sends a request to the other one, the second one replies - end of story. It's easier to do via serial (and takes less pins), and far easier to debug and develop (as you can use a PC to test it in sections), but doing it via SPI would work just as well, just more complicated and not so easy to develop and debug.
 
There is no timing?, or 'synchronisation', it's not working because you don't know what you're doing and you're making it FAR too complicated. As we've explained, one device simply sends a request to the other one, the second one replies - end of story. It's easier to do via serial (and takes less pins), and far easier to debug and develop (as you can use a PC to test it in sections), but doing it via SPI would work just as well, just more complicated and not so easy to develop and debug.
Hi N,
The serial is being used for other things, and only one use is allowed.
Do you mean like this?
C
--------------------------------------------------------------
MASTER
For spipsn = 0 To 34 'spipsn To 34 '49 'GPS=31 $-W INC QEI=2 BATVOLT=1 SPARE DATA=1<<£
SSPBUF = m2s(spipsn)
While Not SSPSTAT.BF
Wend
s2m(spipsn) = SSPBUF '£ ADDED
'Hserout "S2M(SPIPSN) ", #spipsn, " ", s2m(spipsn), CrLf '£
'WaitMs 5 '<<<<<<<<<<<<<<
Next spipsn
--------------------------------------------------------------
SLAVE
For spipsn = 0 To 34 'GPS=30 $-W INC, QEI=2 BATVOLT=1 SPARE DATA=1'<<<<<<<<<<<<<<<<<£
SSPBUF = s2m(spipsn)
While Not SSPSTAT.BF
Wend
m2s(spipsn) = SSPBUF 'M2S
Next spipsn
---------------------------------------------
 
Many PIC's have two serial ports, and it's always a good idea to choose one that does.

It's also very trivial to use a simple software serial port to output debugging data, and it just requires a single output pin - I add one on pretty well everything I build, and use a hardware serial port if there's a spare one (the PPI facility is very useful for moving peripherals to the pin you want).

You want to avoid 'blocking' in your routines, as you've probably got other things going on that need servicing, rather than sat waiting for something to happen. By using interrupts and flags your main routine can just loop round waiting for flags to appear.

I would also suggest writing routines that use the size of the data for transmission and reception, rather than having to hardcode FOR loops in the program.
 

Latest threads

New Articles From Microcontroller Tips

Back
Top