![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
PIC24HJ128GP306 SPI problem with 24LC1024 EEPROM |
Posted: Thu Apr 11, 2013 1:38 pm |
|
|
MCU: PIC24HJ128GP306
Compiler: 4.132
Hello,
I have this really really weird issue:
I have a PIC24 dev board (the CCS dev board) mounted with a PIC24HJ128GP306. To this board, on the breakout connector I tied a 23LC1024 SPI EEPROM in a PDIP form factor and tied the pins like this:
PIN_G6: SPI_CLK
PIN_G7: SPI_IN (into the PIC, out of the EEPROM)
PIN_G8: SPI_OUT (out of the PIC, into the EEPROM)
PIN_G13: SPI_CS
Next to the CCS dev board, I have a PCB that I designed but got manufactured professionally. This is mounted with the same PIC device and has a footprint for a the same EEPROM (in different form factor). At this stage, no EEPROM is mounted on my board but I do have an additional SPI breakout header so that I can tie an external EEPROM to it (for testing).
The only real difference between the two boards is that the CCS board is mounted with a 38.4MHz clock versus my board which is mounted with a 36.864MHz clock (I have other reasons for using that precise speed).
To configure SPI on the CCS board, this is the code:
Code: | #use delay( crystal = 38400000, clock = 76800000 )
#use spi ( MASTER, BITS=8, SPI2 ) |
In my .c file, I have the following:
Code: |
setup_spi2( SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4 ); |
In my .h file, I have the following to configure SPI2 as the HW SPI:
Code: |
#use delay( crystal = 36864000, clock = 73728000 )
#use spi ( MASTER, BITS=8, SPI2 ) |
In my .c file, I have the following:
Code: | setup_spi2( SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4 ); |
So really, the **only** difference is the clock speed (faster on the CCS dev board).
PROBLEM:
The EEPROM works perfectly fine on the CCS dev board. I can read and write to it without a problem.
If I physically disconnect it from the CCS dev board and tie it to my board on the breakout connector, I cannot seem to be able to access the EEPROM.
I have a multi-channel logic analyzer tied to the 4 EEPROM lines. The analyzer has a built-in protocol analyzer that parses and displays the data in a readable way.
So when connecting the analyzer to the CCS board, I can see the PIC device sending commands to the EEPROM at specific addresses and I see the EEPROM responding back with the proper data.
Connecting the analyzer to my board shows the PIC device sending the commands, which are all fine, but no response from the EEPROM.
EEPROM is powered with 3.5VDC, I traced and re-traced and re-re-traced the 4 lines to / from the EEPROM / PIC and all is fine. I just don't know what else to look for.
Also, to make sure that the PIC on my board was fully functional, on power-up, I added a little option that will make the PIC go in an infinite while loop that will toggle on/off the SPI_CLK, SPI_OUT and SPI_CS pins. At the same time, I read the SPI_IN pin and if hi, I toggle PIN_B5 hi and if lo, I toggle PIN_B5 low. So this points to me that the PIC SPI pins are working fine (including the SPI_IN pin that shows me state changes through the status of PIN_B5).
There aren't any shorts between any of the PIC legs ( I checked under a microscope and for continuity using a meter).
The logic analyzer also shows me that the SPI_CLK is 8MHz, which is fine because the EEPROM can go up to 20.
Other than the clock speed, it is the same code in both. I don't have a 38.4MHz crystal to put on my board but since the current one is a bit slower, there's absolutely no reason it shouldn't work.
Any idea, anyone? I really don't know what else it could be. I have a lot of way more complex things on this board and they all work. The simplest of all, the EEPROM, regardless what I try, doesn't work.
Last edited by benoitstjean on Mon Apr 15, 2013 6:25 am; edited 2 times in total |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Thu Apr 11, 2013 5:06 pm |
|
|
Quote: | SPI problem with 24LC1023 EEPROM
on the breakout connector I tied a 23LC1024 SPI EEPROM
|
These are two different part numbers.
Can you clarify the part number of the eeprom that you have ?
Read the label on the chip and edit your post to correct the typo. |
|
![](templates/subSilver/images/spacer.gif) |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
|
Posted: Thu Apr 11, 2013 7:32 pm |
|
|
Sorry, my mistake, it is a 23LC1024, not 1023 (does not exist). For those who are wondering, the initial title of this post had 1023 in it. It was a typo.
I'm still thinking about this tonight while my stuff is at work and it just boggles my mind.
Why would the 1024 work on the CCS dev board using a 38.4MHz crystal against a PIC24HJ128GP306 but not on my own board, using the **same physical** 1024 chip, using the same type of PIC but with a lower crystal frequency (36.864MHz)???
Again, the PIC's I/O's seem fine because I can disable SPI (in the .h file and in the .c file) and toggle each "SPI" pin individually and read from what is the "input" pin on the SPI port... I have a breakout SPI connector and no EEPROM on the board. The "good" EEPROM is tied to this breakout connector and I even tried swapping the MOSI and MISO pins just to make sure I didn't get them mixed, I even swapped the CS and CLK pins and tried every possible combination but it's just not working. Then putting it back on the CCS dev board, tadam! Works fine.
My logic analyzer sees all the proper data but I just never get any reply from the EEPROM... and everything else on my circuit works fine.... except that damn SPI port!
Benoit |
|
![](templates/subSilver/images/spacer.gif) |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Apr 12, 2013 8:33 am |
|
|
UPDATE 2013-04-12
I went even as far as removing the PIC device and changing it with another one. Same problem. The stupid EEPROM will just NOT respond. |
|
![](templates/subSilver/images/spacer.gif) |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Apr 12, 2013 9:25 am |
|
|
Wow, I found the problem but it was really not what I expected....
I really didn't know what else could be wrong on the circuit because I changed the PIC device and used a known functional EEPROM so I started looking into the code...
For the last year or so since I've been using the CCS development board, this was my SPI setup line:
setup_spi2( SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4 );
I started looking into the help file and saw that there was also an SPI_XMIT_L_TO_H flag. So I replaced it with the original SPI_L_TO_H flag and voilĂ , it suddenly worked.
So, is there *anything* that perhaps Microchip would have changed internally on the PIC device?? Why would my original line of code work for a year on a PIC24 with a certain date code and not work on a PIC24 with a different date code?
I'll open a ticket with Microchip and post my findings here.
Benoit
Last edited by benoitstjean on Mon Apr 15, 2013 6:26 am; edited 1 time in total |
|
![](templates/subSilver/images/spacer.gif) |
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Fri Apr 12, 2013 12:54 pm |
|
|
You are doing many strange things.
1. CCS has two methods of interfacing to an SPI device.
A. The orginal method uses setup_spi() to initalize the MSSP module in
the PIC. Then, you use spi_write(), spi_read(), etc., to talk to the
SPI slave device.
B. The newer method is the #use spi() library. The parameters that
you specify for the library will setup the initialization of the MSSP module.
You then use the spi_xfer() function to talk to the SPI slave chip.
You are supposed to choose only one method. For some reason, you
are mixing both of them together in the same program. Why ?
2. The data sheet for the 23LC1024 shows that it uses SPI mode 0.
Look at FIGURE 1-2: SERIAL INPUT TIMING (SPI MODE) on page 4.
http://ww1.microchip.com/downloads/en/DeviceDoc/25142A.pdf
It shows that SCK idles at a low level, and that data is clocked into
the eeprom on the positive edge of SCK. This is SPI mode 0.
Quote: |
setup_spi2( SPI_MASTER | SPI_L_TO_H | SPI_CLK_DIV_4 ); |
The constant that you are using in setup_spi() will configure a 16F or 18F
PIC for SPI mode 1. But it may produce a different result for the
PCD compiler. I don't know. I don't have PCD, so I can't check it.
Also, in you #use spi() statement, you have not specified an SPI mode
parameter. Normally, you should do this. For the 18F compiler, if you
don't specify any parameter, it looks to me that it defaults to SPI mode 1.
Again, it could be different for the PCD compiler.
So I think there is some doubt about what SPI mode your PIC is setup for.
You should check the SCK and SDO signals (on the PIC pins) to
verify that it is setup for SPI Mode 0.
These are the SPI mode constants for 16F and 18F. But I do not know
if they also work for PCD.
Code: |
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H) |
|
|
![](templates/subSilver/images/spacer.gif) |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
|
Posted: Fri Apr 12, 2013 1:08 pm |
|
|
Well, to be honest, not sure who's doing something weird. Why would the code work on one board and not on the other given that they are technically "identical"... Imagine taking a 9V battery out of your fire alarm and putting it in another fire alarm, same make, same model, just a year older and it doesn't work. That would be strange right? Well this is what happened to me: same PIC device (just a different manufacturing date), same EEPROM (and I mean same as *exact* same taken from the "good" board and putting it on the "other" board), same compiler version with the exact same code (other than the crystal frequency)...
As for using such a such functions, I wrote the code last year and I don't remember what lead me to doing what I'm currently doing... however, as I am writing this message, I am briefly skimming through the documentation on SPI in CCS's documentation and I think I remember that it might be because CCS's documentation is quite poor and misleading so I probably fiddled around a bit until it worked.
Anyhow, important thing is that it works and it is consistent.
Thanks for your help.
Benoit |
|
![](templates/subSilver/images/spacer.gif) |
ckielstra
Joined: 18 Mar 2004 Posts: 3680 Location: The Netherlands
|
|
Posted: Fri Apr 12, 2013 3:21 pm |
|
|
Your problem sounds very well explainable to me.
Your circuits have a lot of similarities but are not identical, you have identified three differences (other PIC, though same model, different frequency, other PCB).
From PCM's information it seems very likely you are using SPI in the wrong mode. Then it is possible you have a configuration where you are clocking data in at a moment where the data line is in the transition phase from one bit to the next. Depending on bus capacitance, clock speed, temperature, chip deviations and day of the month, the circuit will work as expected or fail.
Quote: | Anyhow, important thing is that it works and it is consistent. | I hope no lives are dependent on your device. Instead of using the given hints and fixing the identified problems you accept your lucky shot as a solution. |
|
![](templates/subSilver/images/spacer.gif) |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
PIC24HJ128GP306 SPI problem with 24LC1024 EEPROM [unsolved] |
Posted: Mon Apr 15, 2013 6:25 am |
|
|
Yes, of course lives are dependant on it. It is part of the fuel controls on the new Boeing Dreamliner series...
I am not "accepting lucky shots as a solution". It is still on my list of bugs to fix. However, we are Monday today. I though Friday that it was fixed but I think it is not because I am still seeing some odd behavior.
But again, I re-iterate that it has been working flawlessly for at least the last 4 months. Suddenly, it doesn't work. Yes, I know, the PCB is a different one but it's about as simple as the CCS PCB. There are only 4 traces from the PIC to the EEPROM and I looked at them under a microscope and all is fine so PCB is ruled-out (in my book at least). Both circuits are side by side. Both circuits were professionally made.
The PIC device is from another batch (but same device). The one mounted on the CCS board is from last year. The new one is from this year but I take for granted that the PIC is the same internally.
So the only thing left that is really different is the clock speed: 36.864Mhz vs 38.4MHz. Since it is off by 1.536MHz from the original, the window with the problem has been shifted. Maybe it was "faulty" from the very beginning but the frequency of 38.4MHz caused the "flaw" to be perfectly timed so I never encountered the issue. Now that the frequency is off, the flaw is shifted inside the "window" of where I need it to work.
I'll look at the mode thing because that's what all of you are saying.
And NO, it is not going inside the fuel controls of the Boeing Dreamliner... it is going inside the fuel controls of the F-35... |
|
![](templates/subSilver/images/spacer.gif) |
temtronic
Joined: 01 Jul 2010 Posts: 9177 Location: Greensville,Ontario
|
|
Posted: Mon Apr 15, 2013 7:38 am |
|
|
general comments...
1) do not take anything for granted! Different batches of PICs can have differences,that's why 'errata' documentation exists.
2)you've changed the clock speed,about 3-4%,which will affect overall 'things'...
3)does a 'good' PIC(last years model) work in the 'new' board' with a 'new' eeprom ?
4)I see you've got 2 PICs,2 PCBs,2 xtals and 2 eeproms.The only way I know to figure it out is to carefully test every combination WITH the identical code in the PICs. yes, a pain to do,might take a day, but is necessary to figure out the cause.
5) any chance there's 'solder paste,goo,???' under any components? this weekend I cleaned a 'dead' DVR PCB...'gunk' underneath an SMT device 'klled' the whole unit.It's now happily running.I used windshield washer fluid and air compressor to effect the repair.
6) when you do solve it, please post what you found and the cure.Gremlims aren't fun!
hth
jay |
|
![](templates/subSilver/images/spacer.gif) |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Apr 15, 2013 10:51 am |
|
|
So given that it seems I should be using the "newer" method with #use SPI and use the spi_xfer functions, maybe someone can clarify the following:
In my .h file, this is what I will use:
Code: | #define SPI_READ 0x03
#define SPI_WRITE 0x02
#use spi ( MASTER, STREAM=SPI_EEPROM, BITS=8, SPI2, FORCE_HW, MODE=0 ) |
In my .c file, this is where I'm confused:
WRITE DATA:
I want to write value 0x55 at address 0x22 on SPI 2... is this what I need to do:
Code: |
spi_xfer( SPI_EEPROM, SPI_WRITE ); // (write the
spi_xfer( SPI_EEPROM, 0x55); // (write the address)
spi_xfer( SPI_EEPROM, 0x22); // (write the value)
|
READ DATA:
I want to read what's at address 0x55:
Code: | spi_xfer( SPI_EEPROM, SPI_READ ); // (write the
retval = spi_xfer( SPI_EEPROM, 0x55); // (write the address and get the value back)
|
I will try it but maybe someone can clarify? |
|
![](templates/subSilver/images/spacer.gif) |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Apr 15, 2013 12:07 pm |
|
|
I think I got it to work FINALLY... but it's not with the SPI_XFER functions.
I implemented the SPI_XFER function and captured the data using my logic analyzer and the clock was just garbage and I wasn't getting what I expected... So I went back to the previous way and it works now.
It was probably some combination of using the setup_spi2 and #use spi that made the data inconsistent. I completely removed the #use spi and now use only setup_spi2 and it seems stable and reliable. Capturing that data with my analyzer shows clean and consistent data.
In my code, I added an option to clear all the data through a loop and reset every address space to 0xFF. I also added an option to read all addresses from 0x00 to 0xFF and write data 0-255 in addresses 0x00 through 0xFF (address 0 has value 0, address 1 has value 1 etc).
So, in my .C code, this is what I use:
Code: | setup_spi2( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_CLK_DIV_4 ); |
I then re-used the functions I had written that work well now:
Code: |
//*****************************************************************************
//** EXT_SPI_Write
//** -------------
//**
//** Writes the 8-bit <uiData> byte in the 32bit-wide uiAddress.
//**
//** IN> unsigned int ui32Address: unsigned 32-bit value
//** IN> unsigned int uiData: unsigned 8-bit value
//** OUT> none
//** NOTE: Maximum address can only be 0x01FFFF (131071) for 23LC1024 SRAM
//*****************************************************************************
void EXT_SPI_Write( unsigned int32 ui32Address, unsigned int uiData )
{
output_low( SPI_CS ); // Assert chip
spi_write2( SPI_WRITE ); // Send SPI write command for 23LC1024
spi_write2(( ui32Address & 0x010000 ) >> 16 ); // Isolate and send hi-address byte
spi_write2(( ui32Address & 0x00FF00 ) >> 8 ); // Isolate and send mid-address byte
spi_write2(( ui32Address & 0x0000FF )); // Isolate and send low-address byte
spi_write2( uiData ); // Send 8-bit data
output_high( SPI_CS ); // Deassert chip
}
//*****************************************************************************
//** EXT_SPI_Read
//** ------------
//**
//** Reads byte (8 bits) from the 32bit-wide uiAddress.
//**
//** IN> unsigned int ui32Address: unsigned 32-bit value
//** OUT> unsigned int: unsigned 8-bit value
//** NOTE: Maximum address can only be 0x01FFFF (131071) for 23LC1024 SRAM
//*****************************************************************************
unsigned int EXT_SPI_Read( unsigned int32 ui32Address )
{
unsigned int uiData;
output_low( SPI_CS ); // Assert chip
spi_write2( SPI_READ ); // Send SPI read command for 23LC1024
spi_write2(( ui32Address & 0x010000 ) >> 16 ); // Isolate and send hi-address byte
spi_write2(( ui32Address & 0x00FF00 ) >> 8 ); // Isolate and send mid-address byte
spi_write2(( ui32Address & 0x0000FF )); // Isolate and send low-address byte
uiData = spi_read2(0); // Wait for returned 8-bit data
output_high( SPI_CS ); // Deassert chip
return( uiData );
}
|
Yes, I know, I am passing an unsigned 32-bit number as parameter and only masking the first 16 bits but for this particular EEPROM, it's 128kbytes so I don't need to go more than 0x01FFFFF. But these two functions can easily be modified to go all the way up to 32-bit addresses.
I won't mark this post as solved yet but I'll be monitoring and if I see that in a few days its been stable, I'll update the title.
Benoit |
|
![](templates/subSilver/images/spacer.gif) |
benoitstjean
Joined: 30 Oct 2007 Posts: 553 Location: Ottawa, Ontario, Canada
|
|
Posted: Mon Apr 22, 2013 6:53 am |
|
|
So I'm still having SPI issues. I really have no idea here on what to use. CCS's documentation is not helping, I understand how the SRAM chip works but using CCS's code isn't helping. I've changed my code based on the replies I received but the code doesn't jive with what I'm capturing on my analyzer. I might end-up writing my own bit-toggling code as I think it'll be easier but here's what I have at the moment and it's just junk:
.h file:
#use spi ( MASTER, STREAM=SPI_EEPROM, BITS=8, SPI2, FORCE_HW, MODE=0, CLK=PIN_G6, ENABLE=PIN_G13, DO=PIN_G8, DI=PIN_G7 )
.c file:
spi_xfer( SPI_EEPROM, ui32Address, 24 );
spi_xfer( SPI_EEPROM, uiData, 8 );
So if I base myself on CCS's docs, the first spi_xfer command above should transfer on SPI_EEPROM (SPI2), 24 bits of data to the address provided in ui32Address. I use MODE=0 because I want BYTE OPERATION MODE. As for the address, I realize that ui32 is a 32-bit address but that shouldn't matter since I specify that I am sending only 24 bits therefore internally, the spi_xfer function should take care of that. I would assume that the function would toggle the clock 24 times while sending the first 24 bits of the 32-bit address. Also, I will not be passing more than a 17-bit address since the SRAM is 128kbytes. Also, the reason I am passing a 24-bit address is that Microchip's specs (DS25142A) for this chip, page 5, section 2.2, says "The Command followed by the 24-bit address is clocked into the device and the data to/from the device is transferred on the next eight clocks"... So I am using MODE0 as specified in the #use SPI and I am in fact telling via the spi_xfer function that I am transferring 24 bits.
Then, on the next spi_xfer, I am sending the 8-bit value I want to send.
This all makes perfect sense and that's the way it should work... But in reality, that's not working at all. If I look at the data captured on my analyzer, I see a total of 7 clock signals that are all different, I see 2 pulses on the SI pin and I see two CS assertions which I guess correspond to the two spi_xfer commands but that's wrong since CS should be asserted once only for the length of the entire write command.
If someone has a functional solution, can you PLEASE post it? I just want to get this over with. I want to see the .h #use SPI command and I want to see a functional "write_spi( SPI2, address, value )" function.
Thanks.
[UPDATE]
It seems to be working now. I think it has to do with the clock speed which would explain why I was seeing only 6 clock signals with some of them of different lengths. Adding the SPI_CLK_DIV_16 flag worked instantly.
setup_spi2( SPI_MASTER | SPI_XMIT_L_TO_H | SPI_CLK_DIV_16 |SPI_MODE_8B );
Benoit |
|
![](templates/subSilver/images/spacer.gif) |
RF_Developer
Joined: 07 Feb 2011 Posts: 839
|
|
Posted: Mon Apr 22, 2013 8:22 am |
|
|
Oh dear, lots of SPI confusion
There a number of things to remember:
SPI transfers data in two directions at once, controlled by a common clock. There are no pure "reads" and "writes" only bi-directional transfers where you can chose to ignore one or the other direction if you like. While SPI can transfer any number of bits in one transfer, generally most SPI implementations work, or can easily be made to work with transfers of eight bits at a time. To transfer more than eight bits simply requires a suitable number of consequtive eight bit transfers, maybe with ignoring some bits, generally at the end of a transfer.
The PICs have SPI hardware that transfers eight bits at a time and can deal with slave selects (sometimes called chip selects) on slaves, but cannot deal with chip selects on masters as masters are often talking to several slaves.
CCS C provides two methods of setting up and using the SPI hardware. One of these also provides a way of emulating SPI hardware in compiler generated firmware.
Method 1, the old way: setup_spi(), spi_write() and spi_read() (and setup_spi2() etc for the second SPI port). This sets up and operates the hardware SPI interface. It cannot emulate an SPI port in software. These use the somewhat confusing and unmemorable SPI_L_TO_H | SPI_XMIT_L_TO_H constants to set mode, so we recommend the use of defines as posted by PCM Programmer:
Code: |
#define SPI_MODE_0 (SPI_L_TO_H | SPI_XMIT_L_TO_H)
#define SPI_MODE_1 (SPI_L_TO_H)
#define SPI_MODE_2 (SPI_H_TO_L)
#define SPI_MODE_3 (SPI_H_TO_L | SPI_XMIT_L_TO_H)
|
spi_write() doesn't really just write data, it reads it as well (all transfers are bi-directional remember) but ignores any data read. spi_read() doesn't just read, it also writes if needed:
Code: |
Data_Read = spi_read(Data_To_Write);
|
So, you could forget spi_write() and just use spi_read() to do both as needed.
Trying to force use_spi to use hardware is pointless as it only uses the hardware.
Method 2, the newer way: #use_spi () and spi_xfer(). This is more flexible than use_spi() and the read/write routines. It can produce a software SPI which can transfer a much wider range of bits in one transfer, and which can deal with slave selects on masters. It will also use the hardware where it can. I understand that if you specify sixteen bit transfers it will produce code that does two hardware transers, of eight bits each, for each transfer call.
As all SPI transfers are bi-directional and there really aren't any true reads and writes, this method does away with separate read and writes and simply has a single transfer routine which does both: spi_xfer(). Also this avoids confusion (for the compiler) with the old spi_read and spi_write routines.
Software SPI is very slow compared to hardware. Unless you specify the bit rate (set the clock rate dividere in setup_spi, or the BAUD= setting in #use_spi) then the compiler will clock the SPI as fast as it can, which may not be all that fast in most cases. In general, the clock rate of the master must be less than or equal to the slowest clock rate of the devices on the SPI bus. Though it is possible to change bit clock rates from device to device, the CCS compiler makes this difficult as it assumes you're going to set one rate and leave it there for all the code.
spi_xfer() can set the chip/slave select for you on a master. However, it will do this for each and every call of spi_xfer(). It does not know that you may want to use a number of consequetive spi_xfer() calls to make one sequence to a device. It assumes you will transfer all the bits in ONE spi_xfer() call. This can be used to advantage with some SPI devices, for example ADCs where every reading is one say 24 bit transfer, but its not much use with memories which have command sequences of varying lengths. For these, and frankly I find it easier for all SPI transfers, to keep to the default 8 bits per transfer, and handle chip/slave selects in my code. Using your example:
In your .h file:
Code: |
#define MEM_READ 0x03 // SPI_READ can get confused with spi_read, the function call.
#define MEM_WRITE 0x02 // I'm assuming these are the correct commands: I haven't checked the datasheet.
#define MEM_SELECT PIN_XX // slave select for the eeprom
#use spi ( MASTER, STREAM=SPI_EEPROM, BITS=8, SPI2, MODE=0 )
|
In your .c file:
Note the read and wrtie byte command sequences are five bytes each: a command byte, three address bytes then a data byte to or from the eeprom. These are similar to your newest routines that use setup_spi(), just that these use spi and spi_xfer.
WRITE DATA:
To write value 0x22 at address 0x000055 to 23LC1024 eeprom on SPI 2
Code: |
output_low( MEM_SELECT );
spi_xfer( SPI_EEPROM, MEM_WRITE ); // write command byte
spi_xfer( SPI_EEPROM, 0x00); // write the MSB of the address
spi_xfer( SPI_EEPROM, 0x00); // Each address is 24 bits, i.e. three bytes
spi_xfer( SPI_EEPROM, 0x55); // write the LSB of the address
spi_xfer( SPI_EEPROM, 0x22); // (write the value)
output_high( MEM_SELECT );
|
READ DATA:
I want to read what's at address 0x000055:
Code: |
output_low( MEM_SELECT );
spi_xfer( SPI_EEPROM, MEM_READ ); // read command
spi_xfer( SPI_EEPROM, 0x00); // MSB of the address)
spi_xfer( SPI_EEPROM, 0x00); // middle byte
spi_xfer( SPI_EEPROM, 0x55); // LSB of the address - up til now there has been nothing to read.
retval = spi_xfer( SPI_EEPROM, 0) // get the value back in the fifth byte, doesn't matter what was sent.
output_high( MEM_SELECT );
|
Its not advisable to confuse the two and use a mixture: either setup_spi and spi_read/spi_write or #use_spi and spi_xfer. If you are using the SPI hardware in eight bit mode you may be able to get away with mixing them, but this is NOT advised. It is very easy to get confused and mix them up, with unpredictable results.
RF Developer. |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|